Home  
  Home Lecture Link BBS Blame  



¢ÂMax Plugin¢Â

Ç÷¯±×ÀÎ(Plugin)ÀÇ ¶æÀ» ã¾Æº¸¸é ÇÁ·Î±×·¥¿¡ ¾ø´ø »õ ±â´ÉÀ» Ãß°¡Çϱâ À§ÇØ ³¢¿ö ³Ö´Â¡¹ºÎ°¡ÀûÀÎ ÇÁ·Î±×·¥À¸·Î ÀÚüÀûÀ¸·Î´Â ½ÇÇà´É·ÂÀº ¾øÁö¸¸ ƯÁ¤ÇÑ ÇÁ·Î±×·¥ ¼Ó¿¡¼­ ÇÔ²² ½ÇÇàµÇ¾î ±â´ÉÀ» ¹ßÈÖÇÑ´Ù°í µÇ¾î ÀÖ½À´Ï´Ù.

Autodesk 3D Max(ÀÌÇÏ MAX: ¸Æ½º) PluginÀº »ç¿ëÀÚÀÇ ¸ñÀû¿¡ ¸Â°Ô ¸Æ½º ÇÁ·Î±×·¥ÀÇ ±â´ÉÀ» º¸°­Çϱâ À§Çؼ­ ¸¸µç ÇÁ·Î±×·¥ÀÔ´Ï´Ù. À©µµ¿ì ¿î¿µÃ¼Á¦¿¡¼­ MAX¿ë Ç÷¯±×ÀÎÀÇ ±¸ÇöÀº DLL (Dynamic Linking Library)ÀÔ´Ï´Ù. µû¶ó¼­ ¿ø·¡ ÇÁ·Î±×·¥ÀÇ Çü½Ä°ú À©µµ¿ì DLLÀÇ Ç¥ÁØ¿¡ ¸Â°Ô ÇÁ·Î±×·¥À» ¸¸µç´Ù¸é Ç÷¯±×ÀÎÀ» ¸¸µé ¼ö ÀÖ½À´Ï´Ù.

¸Æ½º Ç÷¯±×ÀÎÀº ¾Æ¹«°Å³ª ¸¸µé ¼ö ÀÖ´Â °ÍÀÌ ¾Æ´Ï¶ó ¸Æ½º¿¡¼­ Áö¿øµÇ´Â °Í¸¸ ¸¸µé ¼ö ÀÖ½À´Ï´Ù. ¾î¶² Ç÷¯±×ÀÎÀ» ¸¸µé °ÍÀÎÁö´Â Visual Studio¿¡¼­ ¸Æ½º Ç÷¯±×ÀÎ ¸¸µå´Â Wizard·Î È®ÀÎÇÒ ¼ö ÀÖÀ¸¸ç ÀÌ Áß¿¡¼­ "File Export"°¡ ¿ì¸®°¡ ¸¸µé°íÀÚ ÇÏ´Â Ç÷¯±×ÀÎ ÀÔ´Ï´Ù.

"File Export" Ç÷¯±×ÀÎÀº °ÔÀÓ¿¡¼­ ÇÊ¿äÇÑ ¸Æ½º ÆÄÀÏÀÇ ÀϺθ¦ ²¨³»¿À´Â °ÍÀÔ´Ï´Ù. ¹°·Ð ´Ù ²¨³»¿À¸é ÁÁ°ÚÁö¸¸ ±×·¸°Ô Çϱâ´Â Èûµé°í ¼³·É ´Ù °¡Á®¿Â´Ù ÇÏ´õ¶óµµ ¸Æ½º ÇÁ·Î±×·¥°ú °ÔÀÓ ÇÁ·Î±×·¥ÀÇ ÀÚ·á ÇØ¼® Â÷ÀÌ·Î È­¸é¿¡ º¸ÀÌ´Â ¸ð½ÀÀº ¾à°£ÀÇ Â÷À̰¡ ÀÖÀ» ¼ö ÀÖ½À´Ï´Ù. ÁÁÀº "File Export" Ç÷¯±×ÀÎÀº ¸Æ½º È­¸é°ú °ÔÀÓ È­¸éÀÇ Â÷À̸¦ ÁÙÀ̰í ÃÖ´ëÇÑ ÀÏÄ¡½ÃŰ´Â °ÍÀ̶ó ÇÒ ¼ö ÀÖ½À´Ï´Ù.

º¸Åë °æ·ÂÀڵ鵵 ¾µ¸¸ÇÑ "File Export" Ç÷¯±×ÀÎÀ» ¸¸µå´Âµ¥ °ÅÀÇ 4~6°³¿ùÀÇ ½Ã°£ÀÌ ¼Ò¿äµË´Ï´Ù. À̰ÍÀº ¸Æ½º¿Í D3D´Â °°Àº µ¥ÀÌÅÍ¶óµµ Ã³¸®ÇÏ´Â ¹æ½ÄÀÌ ´Ù¸£°í ±¸Ã¼ÀûÀÎ ¸Æ½ºÀÇ ³»¿ëÀ» ¸ð¸£´Â »óÅ¿¡¼­ ÀÛ¾÷À» Çϱ⠶§¹®ÀÔ´Ï´Ù. ¶ÇÇÑ ¸Æ½º ÇÁ·Î±×·¥ÀÇ È­¸é¿¡¼­´Â Á¤»óÀûÀÎ ¸ð½ÀÀ¸·Î ³ªÅ¸³ªÁö¸¸ ExportingÀ» ÇÏ¸é ¹Ìó ó¸®ÇÏÁö ¸øÇÑ µ¥ÀÌÅÍ·Î ÀÎÇØ ¿øÄ¡ ¾Ê´Â ¸ð½ÀÀÌ Á¾Á¾ ³ªÅ¸³³´Ï´Ù. µû¶ó¼­ ¿Ïº®ÇÑ Ç÷¯±×ÀÎÀ» ¸¸µé±â±îÁö ³Ê¹« ¸¹Àº ½Ã°£ÀÌ ¼Ò¿äµÈ´Ù¸é ȸ»ç·Î¼­µµ ºñ¿ëÀÇ ¹®Á¦°¡ ¹ß»ýÇϱ⠶§¹®¿¡ ¹ö±×¸¦ ÇÇÇÏ´Â ¹æ¹ýÀ» ±×·¡ÇÈ ´ã´çÀÚµé°ú ³íÀǸ¦ ÇÏ°í ±×·¡ÇÈ ÀÛ¾÷ÀÇ ¼ø¼­¸¦ °áÁ¤ÇÕ´Ï´Ù.

 

ÀÌ ÀåÀº ¿Ïº®ÇÏÁö ¾ÊÁö¸¸ ±×·¡µµ ¾î´À Á¤µµ ¾µ ¸¸ÇÑ Ç÷¯±×ÀÎÀ» ¸¸µé¾îº¸´Â °ÍÀÌ ¸ñÀûÀÔ´Ï´Ù. ¸ðµç ¸Æ½º µ¥ÀÌÅÍ¿¡ ´ëÇØ¼­ µ¥ÀÌÅ͸¦ ExportÇÑ´Ù°í´Â ÇÒ ¼ö ¾ø°í ±×·¯ÇÑ ¹®Á¦µéÀº µ¶ÀÚÀÇ ¸ñÀ¸·Î ³²°Ü ³õ°Ú½À´Ï´Ù. ¶ÇÇÑ 3D ¸Æ½º°¡ 2010 ¹öÀü±îÁö Ãâ½ÃµÇ¾úÁö¸¸ ¿©±â¼­´Â 8.0±âÁØÀ¸·Î Ç÷¯±×ÀÎÀ» ¸¸µé°Ú½À´Ï´Ù. ±×°ÍÀº ¸Æ½ºÀÇ °¡°ÝÀÌ 500¸¸¿øÀÌ ³Ñ½À´Ï´Ù. º¸Åë ±³À°±â°üÀ̳ª ±â¾÷ü¿¡¼­ ¼ÒÇÁÆ®¿þ¾î°¡ »õ·Î Ãâ½ÃµÇ¸é Çлýµé ¶Ç´Â °³¹ßÀÚµéÀ» À§ÇØ »õ·Î¿î ¼ÒÇÁÆ®¿þ¾î¸¦ °ø±ÞÇÏ´Â °ÍÀÌ ÀϹÝÀûÀÌÁö¸¸ °³¹ßÀÚ ¿ù±Þ º¸´Ù ÈξÀ ºñ½Ñ ¼ÒÇÁÆ®¿þ¾î¸¦ ¾÷±×·¹À̵å ÇÑ´Ù´Â °ÍÀº ȸ»ç ¿î¿µ»ó ¸ÂÁö ¾Ê±â ¶§¹®¿¡ ´ëºÎºÐ ÀÌÀü ¹öÀüÀ» ±×´ë·Î »ç¿ëÇÏ´Â °æÇâÀÌ ¸¹½À´Ï´Ù. ÇÁ·Î±×·¡¸ÓÀÇ ÀÔÀÚ¿¡¼­ ¹Ù¶óº¸¾Æµµ ¸Æ½º ¹öÀüÀÌ ¿Ã¶ó°¡µµ ÇÊ¿äÇÑ SDK ³»¿ëÀº °ÅÀÇ ±×´ë·ÎÀÎ °ÍÀÌ ´ëºÎºÐÀÔ´Ï´Ù.

8.0À» ¼±ÅÃÇÑ ÁÖµÈ ÀÌÀ¯´Â °¡Àå ¸¹ÀÌ »ç¿ëµÇ´Â ¹öÀüÀ̱⵵ ÇÏÁö¸¸ ÀÌÀü¿¡´Â ¸Æ½º¿¡¼­ ¾Ö´Ï¸ÞÀÌ¼Ç ÀÛ¾÷À» ÇÒ ¶§ Physique¸¦ ÁÖ·Î »ç¿ëÇߴµ¥ 8.0 ÀÌÈÄ¿¡´Â ½ºÅ°´×(Skinning)ÀÌ Áö¿øµÇ¾î ÀÌ ¹æ½ÄÀ¸·Î ÀÛ¾÷À» ¸¹ÀÌ ÇÑ´Ù°í ÇÕ´Ï´Ù. ½ºÅ°´×À¸·Î ¾Ö´Ï¸ÞÀ̼ÇÀ» ÀÛ¾÷ÇÏ¸é ±×·¡ÇȰú °ÔÀÓ¿¡¼­ ÀÏÄ¡ÇÏÁö ¾Ê´Â ¹ö±× ã±âµµ ¼ö¿ùÇÏ´Ù°í ÇÕ´Ï´Ù.

 

 

5.1 SDK

5.1.1 SDK ¼³Ä¡¿Í VC Project

¸Æ½º´Â ¿ë·®ÀÌ Å©¹Ç·Î Program Files¿¡ ¼³Ä¡Çϱ⠺¸´Ù´Â Çϵ带 ºÐÇÒÇØ¼­ C ´ë½Å D³ª E¿¡ ¼³Ä¡ÇÏ´Â °ÍÀÌ ÁÁ½À´Ï´Ù. Àú´Â "D:\_3dsMax8" ¿¡ ¼³Ä¡ Çß½À´Ï´Ù.

¸Æ½º SDK´Â ¸Æ½º¿Í µû·Î ¼³Ä¡µË´Ï´Ù. ´ÙÀ½°ú °°ÀÌ install CD°¡ ÀÖÀ¸¸é SDK¸¦ ¼³Ä¡ÇÕ´Ï´Ù. Àú´Â "D:\_3dsMax8\maxsdk"¿¡ ¼³Ä¡Çß½À´Ï´Ù.

 

<MAX SDK ¼³Ä¡>

 

SDK¸¦ ¼³Ä¡ÇÏ°í ³ª¼­ ¸Æ½º SDK°¡ ¼³Ä¡µÈ Æú´õ ¿¹¸¦ µé¾î "D:\_3dsMax8\maxsdk\howto"¿¡ °¡¸é "3dsmaxPluginWizard" Æú´õ°¡ ÀÖ½À´Ï´Ù. ÀÌ Æú´õÀÇ "Readme.txt"ÆÄÀÏÀ» Àо¸é ÀÌ À§Àúµå´Â "Visual Studio 7.1"¿ë À§Àúµå ÀÓÀ» ¾Ë¸®°í ÀÖ½À´Ï´Ù.

 

¶ÇÇÑ Installing 2¹øÀ» º¸¸é "3dsmaxPluginWizard.vsz" ÆÄÀÏÀ» ¿­¾î¼­ ´ÙÀ½ ºÎºÐÀ» °íÄ¡¶ó°í ÇÕ´Ï´Ù.

Param="ABSOLUTE_PATH = [Absolute Path Location of 3dsmaxPluginWizard Root Directory]"

 

À̰ÍÀº Visual Studio¿¡¼­ À§Àúµå¸¦ ½ÇÇàÇÒ ¶§ ¸Æ½º SDKÀÇ À§Àúµå¸¦ ½ÇÇàÇÒ ¼ö ÀÖ´Â Àý´ë °æ·Î¸¦ ¼³Á¤Ç϶ó´Â °ÍÀ¸·Î ±×¸²Ã³·³ "dsmaxPluginWizard.vsz" ÆÄÀÏÀÌ ÀÖ´Â °æ·Î¸¦ º¹»çÇØ¼­ ´ÙÀ½°ú ÀÌ ¸¸µì´Ï´Ù.

 

Param="ABSOLUTE_PATH = [D:\_3dsMax8\maxsdk\howto\3dsmaxPluginWizard]"

 

¶ÇÇÑ °æ·Î À̸§¿¡ '\'¸¦ Ãß°¡ÇÏÁö ¸»¶ó°í ÇÕ´Ï´Ù. (±×³É Ž»ö±â¿¡ ÀÖ´Â °æ·Î¸¦ ºÙÀÌ¸é ¹®Á¦ ¾ø½À´Ï´Ù.)

< dsmaxPluginWizard.vsz ÆÄÀÏÀÇ °æ·Î º¹»ç>

 

´ÙÀ½À¸·Î Installing 3¹ø¿¡ º¸¸é

 

3dsmaxPluginWizard.ico

3dsmaxPluginWizard.vsdir

3dsmaxPluginWizard.vsz

 

ÆÄÀÏ 3°³¸¦ Visual Studio°¡ ¼³Ä¡µÈ Æú ´õ ¹Ø¿¡ "Visual Studio Æú´õ\Vc7\vcprojects Vc7\vcprojects" Æú´õ¿¡ º¹»çÇ϶ó°í Çϴµ¥ ´ÙÀ½°ú °°ÀÌ ÇÏ¸é µË´Ï´Ù.

 

<Visual Studio À§Àúµå ÇÁ·ÎÁ§Æ® ¼³Ä¡>

 

ÀÌ·¸°Ô Çϸé À§Àúµå ¼³Ä¡´Â ³¡ÀÌ ³³´Ï´Ù. Visual StudioÀÇ »õ ÇÁ·ÎÁ§Æ®¸¦ ½ÇÇàÇÏ¸é ´ÙÀ½ ±×¸²Ã³·³ ¸Æ½º Ç÷¯±×ÀÎ À§Àúµå ¼±Åà ¾ÆÀÌÄÜÀÌ ÀÖ½À´Ï´Ù.

 

<¸Æ½º Ç÷¯±×ÀÎ À§Àúµå ½ÇÇà>

 

È®ÀÎ ¹öưÀ» ´©¸£¸é ¾î¶² Ç÷¯±×ÀÎÀ» ¸¸µé °ÍÀÎÁö ¼±Åà ȭ¸éÀÌ ³ª¿É´Ï´Ù. "File Export"¸¦ ¼±ÅÃÇÕ´Ï´Ù.

 

<Ç÷¯±×ÀÎ Á¾·ù ¼±ÅÃ: "File Exporter">

 

´ÙÀ½ â¿¡ Plugin Detail âÀÌ ÀÖ½À´Ï´Ù. ±×³É ³Ñ¾î°©´Ï´Ù. ±× ´ÙÀ½ â¿¡´Â ¸Æ½º SDK°¡ ¼³Ä¡µÈ Æú´õ, Ç÷¯±×ÀÎÀÌ ÄÄÆÄÀÏ µÇ¸é º¹»çµÉ °æ·Î, ¸Æ½ºÀÇ ½ÇÇà °æ·Î¸¦ ÁöÁ¤ÇÏ´Â °ÍÀÌ ³ª¿É´Ï´Ù. ¸Æ½º´Â ½ÇÇà ÆÄÀÏÀÌ ÀÖ´Â ÇÏÀ§ Æú´õ "plugins" ¿¡ ÀÖ´Â Ç÷¯±×ÀεéÀ» ½ÇÇàÇÒ ¶§ ÀüºÎ ¿Ã¸³´Ï´Ù. µû¶ó¼­ À̰÷¿¡ ÀÚµ¿À¸·Î º¹»çÇϵµ·Ï ¼³Á¤ÇÏ´Â °ÍÀÌ ÁÁ½À´Ï´Ù. À̰ÍÀÌ ¼³Á¤ÀÌ ¾ÈµÇ¸é ¸Å ¹ø Ç÷¯±×ÀÎÀ» À̰÷¿¡ º¹»çÇØ ³õ¾Æ¾ß ÇÕ´Ï´Ù.

 

<SDK Çì´õ ÆÄÀÏ Path, Ç÷¯±×ÀÎ Ãâ·Â À§Ä¡, ¸Æ½º ½ÇÇà ÆÄÀÏ °æ·Î ¼³Á¤>

 

Finish ¹öưÀ» ´©¸£¸é À§Àúµå Äڵ尡 ¸¸µé¾îÁý´Ï´Ù. 2005ÀÇ °æ¿ì¿¡´Â ÇÁ·ÎÁ§Æ®°¡ Visual Studio¿¡ ¿Ã¶ó¿ÀÁö ¾ÊÀ» °ÍÀÔ´Ï´Ù. À̰ÍÀº ÀÌ À§Àúµå°¡ 2003 ¹öÀü¿¡ ¸ÂÃß¾îÁ® Àֱ⠶§¹®ÀÔ´Ï´Ù. Visual Studio¸¦ ´Ý°í ¾Õ¼­ ¸¸µç maxProject1.vcproj ¸¦ ´Ù½Ã ½ÇÇàÇÏ¸é º¯È¯ ¸¶¹ý»ç°¡ ÁøÇàÀÌ µË´Ï´Ù. ¸¶¹ý»ç¸¦ ÁøÇàÇØµµ ´ÙÀ½°ú °°Àº ¿¡·¯°¡ ¹ß»ýÇÒ °ÍÀÔ´Ï´Ù.

 

"XML ±¸¹®À» ºÐ¼®ÇÏ´Â µ¿¾È ´ÙÀ½°ú °°Àº ¿À·ù°¡ ¹ß»ýÇß½À´Ï´Ù. ÆÄÀÏ: E:\_Document\_vc\maxProject1\maxProject1.vcproj ÁÙ: 86 ¿­: 22 ¿À·ù ¸Þ½ÃÁö: ºÎ¸ð ¿ä¼Ò 'Configuration'ÀÇ ÄÜÅÙÃ÷ ¸ðµ¨¿¡ µû¸£¸é 'IntelOptions'Àº(´Â) ¿¹±âÄ¡ ¾ÊÀº ¿ä¼ÒÀÔ´Ï´Ù. ¡¦"

 

´çȲÇÏÁö ¸»°í ¸Þ¸ðÀåÀ¸·Î vcproj ÆÄÀÏÀ» ¿­¾î¼­ ´ÙÀ½ ºÎºÐÀ» °ú°¨È÷ »èÁ¦ ÇÕ´Ï´Ù. ´Ù½Ã Visual Studio¸¦ ½ÇÇàÇÏ°í º¯È¯ ¸¶¹ý»ç¸¦ ÁøÇàÇÏ¸é ¹«»çÈ÷ ÇÁ·ÎÁ§Æ®°¡ ¿Ã¶ó ¿É´Ï´Ù.

 

<ÇÁ·ÎÁ§Æ® ¿É¼Ç ¼³Á¤>

 

¿©±â±îÁö ÇßÀ¸¸é ´Ù µÈ °Í °°Àºµ¥ ¾ÈŸ±õ°Ôµµ ÇÁ·ÎÁ§Æ®¸¦ ºôµå ÇÏ¸é ¿¡·¯°¡ 10°³ Á¤µµ ¸¸µé¾î Áý´Ï´Ù. À̰ÍÀº Visual Studio 2005 ¹öÀüÀÌ ÀÌÀü ¹öÀüº¸´Ù C++ Ç¥ÁØÀ» ¾ö°ÝÈ÷ µû¸£´Ù º¸´Ï ¸¸µé¾îÁø ¹®Á¦µéÀÔ´Ï´Ù. ã¾Æ¼­ ÇØ°áÇÏ¸é µË´Ï´Ù.

 

ù ¹øÂ° ¿¡·¯´Â d:\_3dsmax8\maxsdk\include\manipulator.h(463) ÆÄÀÏÀÇ ManipExport Invalidate() { mValid = NEVER; }¿¡¼­ ³ª¿Ô±º¿ä.

2005 ÀÌÀü¿¡´Â ÇÔ¼öÀÇ ¹Ýȯ ÇüÀ» ÀûÁö ¾ÊÀ¸¸é intÇüÀ¸·Î ÄÄÆÄÀÏ·¯°¡ ÀνÄÇß°í ¹ÝȯÀ» ÁöÁ¤ÇÏÁö ¾Ê¾Æµµ Warning¸¸ ¸¸µé¾îÁö°í ÄÄÆÄÀÏÀº µÆ½À´Ï´Ù. ÄÚµåÀÇ ³»¿ë»óÀ¸·Î ºÁ¼­ ¹ÝȯÀº ¾ø¾î void°¡ ¸Â°ÚÁö¸¸ ÀÌÀü¿¡´Â intÇüÀ̾úÀ¸¹Ç·Î Invalidate ¾Õ¿¡ int¸¦ Àû¾î ÁÝ´Ï´Ù. ManipExport int Invalidate() { mValid = NEVER; }

 

¶Ç ´Ù¸¥ ¿¡·¯´Â

"e:\_document\_vc\maxproject1\maxproject1.cpp(48):error C2065: 'themaxProject1'" ¿¡¼­ ¸¸µé¾î Á³½À´Ï´Ù.

 

"void* Create(BOOL loading = FALSE) { return &themaxProject1; }" À¸·Î ÀÛ¼ºµÇ¾î ÀÖ´Â ºÎºÐÀ» ÇÁ·ÎÁ§Æ®ÀÇ À̸§°ú °°Àº Ŭ·¡½ºÀÇ ÀνºÅϽº¸¦ ¸¸µå´Â ÄÚµå·Î ÀüȯÇÕ´Ï´Ù.

 

void* Create(BOOL loading = FALSE) { return new maxProject1(); }

 

±× ´ÙÀ½ÀÇ maxProject1ObjClassDesc Ŭ·¡½º ÄÚµåºÎÅÍ Äݹé(Call Back) ÇÔ¼ö maxProject1OptionsDlgProc() Àü±îÁö ÇÊ¿ä ¾ø´Â ÄÚµåÀ̹ǷΠÀüºÎ »èÁ¦ÇØ ¹ö¸³´Ï´Ù. ´ë·« 80~ 224 ¶óÀÎÀÌ µÉ °Í °°½À´Ï´Ù. ÀÌ·¸°Ô Áö¿ì¸é Ŭ·¡½º´Â maxProject1, maxProject1ClassDesc µÎ °³¸¸ ³²¾Æ ÀÖÀ» °ÍÀÔ´Ï´Ù. ´Ù½Ã ÄÄÆÄÀÏ Çϸé À̹ø¿¡´Â ¸®¼Ò½º ÆÄÀÏ(rc)¿¡¼­ ¿¡·¯°¡ ¸¸µé¾îÁú °ÍÀÔ´Ï´Ù. ¿¡·¯ ºÎºÐÀº Áö¿ó´Ï´Ù.

 

´Ù½Ã ºôµå Çϸé À̹ø¿¡´Â "DllEntry.obj : error LNK2019: "class ClassDesc2 * __cdecl GetmaxProject1ObjDesc" ¿¡·¯°¡ ¹ß»ýÇÕ´Ï´Ù. À̰ÍÀº ¾Õ¼­ maxProject1ClassDesc Ŭ·¡½º¸¦ Áö¿ü±â ¶§¹®ÀÔ´Ï´Ù.

 

DllEntry.cppÀÇ 16¶óÀÎ "extern ClassDesc2* GetmaxProject1ObjDesc();"

ºÎºÐ°ú 59¶óÀÎ "case 1: return GetmaxProject1ObjDesc();"À» »èÁ¦ÇÕ´Ï´Ù.

 

´Ù½Ã ºôµå ÇÏ¸é ¸µÅ© ¿¡·¯ "error LNK2001: "public: virtual class Manipulator * __thiscall maxProject1ClassDesc"°¡ ¸¸µé¾îÁý´Ï´Ù.

Ŭ·¡½º maxProject1ClassDesc ¾ÈÀÇ "BOOL IsManipulator() { return TRUE; }" ºÎÅÍ

"Manipulator* CreateManipulator(RefTargetHandle hTarget, INode* pNode);"±îÁö ÀüºÎ Áö¿ó´Ï´Ù.

 

ÀÌ·¸°Ô Áö¿ì°í ³ª¸é maxProject1ClassDesc Ŭ·¡½º´Â ´ÙÀ½°ú °°Àº ÇÔ¼ö¸¸ ³²¾Æ ÀÖÀ» °ÍÀÔ´Ï´Ù.

 

class maxProject1ClassDesc : public ClassDesc2 {

public:

        int            IsPublic() { return TRUE; }

        void *         Create(BOOL loading = FALSE) { return new maxProject1(); }

        const TCHARClassName() { return GetString(IDS_CLASS_NAME); }

        SClass_ID      SuperClassID() { return SCENE_EXPORT_CLASS_ID; }

        Class_ID       ClassID() { return maxProject1_CLASS_ID; }

        const TCHAR*   Category() { return GetString(IDS_CATEGORY); }

        const TCHAR*   InternalName() { return _T("maxProject1"); }

        HINSTANCE      HInstance() { return hInstance; }

};

 

¼Ö·ç¼ÇÀ» ´Ù½Ã ºôµåÇϸé "plugins" Æú´õ¿¡ "maxProject1.dle" ÆÄÀÏÀÌ ¸¸µé¾î Áý´Ï´Ù. ¿¬½À »ï¾Æ Äڵ尡 µ¿ÀÛ ÇÏ´ÂÁö ´ÙÀ½°ú °°ÀÌ »ý¼ºÀÚ ¼Ò¸êÀÚ, ±×¸®°í Ext() ÇÔ¼ö¿¡ ¸Þ½ÃÁö ¹Ú½º¸¦ ¶ç¿ö ³õ°í()ºê·¹ÀÌÅ© Æ÷ÀÎÆ®¸¦ ¼³Á¤(F9 Ű)ÇÕ´Ï´Ù.

 

maxProject1::maxProject1()

{

¡Ü      MessageBox(NULL, "Create maxProject1", "Message", 0);

}

 

maxProject1::~maxProject1()

{

¡Ü      MessageBox(NULL, "Destory maxProject1", "Message", 0);

}

 

const TCHAR *maxProject1::Ext(int n)

{             

¡Ü      MessageBox(NULL, "Call maxProject1 Exporter", "Message", 0);

        return _T("");

}

 

µð¹ö±× ¸ðµå·Î ½ÇÇàÇÏ¸é ´ÙÀ½°ú °°ÀÌ Ã¢ÀÌ ¿Ã¶ó¿À°í ¿©±â¿¡ ¸Æ½º ÇÁ·Î±×·¥ÀÇ À§Ä¡¸¦ ã¾Æ¼­ ³ÖÀ¸¸é ¸Æ½º°¡ ½ÇÇàÀÌ µË´Ï´Ù.

 

<Visual Studio¿¡¼­ Ç÷¯±×ÀÎ µ¿ÀÛÀ¸·Î À§ÇØ ¸Æ½º ½ÇÇà: mxp00_maxProject1.zip >

 

µð¹öµù Á¤º¸ ¾øÀ½ âÀÌ ³ª¿Íµµ "¿¹"¸¦ ¼±ÅÃÇϽʽÿÀ.

¾Æ¹« µµÇüÀ̳ª ´ëÃæ ±×¸®°í ´ÙÀ½ ±×¸²°ú °°ÀÌ Export¸¦ ¼±ÅÃÇØ¼­ ½ÇÇàÇÏ¸é ¼³Á¤ÇÑ ºê·¹ÀÌÅ© Æ÷ÀÎÅͰ¡ µ¿ÀÛÇÏ°í °£´ÜÇÑ ¸Þ½ÃÁö âÀÌ ¿Ã¶ó¿À´Â °ÍÀ» È®ÀÎÇÒ ¼ö ÀÖ½À´Ï´Ù.

 

<Ç÷¯±×ÀÎ ½ÇÇà>

 

 

5.1.2 ´Ù¸¥ ÇÁ·ÎÁ§Æ® ¼öÁ¤

´Ù¸¥ »ç¶÷ÀÌ ÀÛ¼ºÇÑ Ç÷¯±×ÀÎ ÇÁ·ÎÁ§Æ®¸¦ ¼öÁ¤ÇÏ°í ½ÍÀ» ¶§µµ ÀÖ½À´Ï´Ù. ¿¹¸¦ µé¾î "mxp00_mymax0.zip" ¸¦ LcMax¶ó´Â ÇÁ·ÎÁ§Æ®·Î ¸ðµÎ ¹Ù²Û´Ù°í ÇսôÙ. ¸ÕÀú ÇØ ¾ßÇÒ ÀÏÀº ÆÄÀÏ "mymax.*"·Î µÇ¾î ÀÖ´Â À̸§À» "LcMax.*"·Î ¹Ù²Ù´Â °ÍÀÔ´Ï´Ù.

 

<ÆÄÀÏ À̸§ ¹Ù²Ù±â>

 

´ÙÀ½À¸·Î editplus µîÀÇ ÆíÁý±â¸¦ ÀÌ¿ëÇØ¼­ ±×¸²ÀÇ ¸ðµç ÆÄÀÏÀ» ¿­¾î¼­ "mymax"¶ó´Â À̸§À»  ÀüºÎ LcMax·Î ¹Ù²Ù¾î ÁÖ¾î¾ß ÇÕ´Ï´Ù.

<ÇÁ·ÎÁ§Æ® ³»¿ë ÀüºÎ ¹Ù²Ù±â>

 

ÀÌ·¸°Ô ÆÄÀÏ À̸§°ú ÇÁ·ÎÁ§Æ®ÀÇ ³»¿ëÀ» ¹Ù²Ù°í ³ª¼­ ´ÙÀ½°ú °°Àº Class_IDÀÇ °ªÀ» ã¾Æ¼­ ¹Ù²Ù¾î¾ß ÇÕ´Ï´Ù.

 

#define ¡¦_CLASS_ID   Class_ID(0x¡¦, 0x¡¦)

 

Class_ID °ªÀº Guid Number ¸¦ Á÷Á¢ Á¶ÇÕÇØ¼­ ¸¸µé¾îµµ µÇ°í ¸Æ½º SDK°¡ ¼³Ä¡µÈ ÇÏÀ§ Æú´õ help ¾Æ·¡ gencid.exe("¸Æ½º SDK Æú´õ\help\gencid.exe") ÆÄÀÏÀÌ ÀÖ½À´Ï´Ù. À̰ÍÀ» ½ÇÇàÇϰí New Class ID ¹öưÀ» ´©¸£°í Copy To Clipboard ¹öưÀ» ´©¸¥ ´ÙÀ½ Class_ID À§¿¡ "Ctrl+V" ۸¦ ´©¸£¸é »õ·Î¿î °ªÀÌ ºÙ¿©Áý´Ï´Ù.

´ÙÀ½À¸·Î È®ÀåÀÚ¸¦ ¹ÝȯÇÏ´Â Ext(int n) ÇÔ¼öµµ ÀÚ½ÅÀÌ Á¤ÇÑ À̸§¿¡ ¸Â°Ô °íĨ´Ï´Ù.

 

const TCHAR *LcMax::Ext(int n)

{

        return _T("acm");

}

 

ºôµå ÈÄ ½ÇÇàÇϰí Menu à "File" à "Export¡¦" ¸¦ ÁøÇà ÇÏ¸é ´ÙÀ½ ±×¸²Ã³·³ ExportÇÒ Áغñ°¡ µÇ¾î ÀÖÀ½À» º¼ ¼ö ÀÖ½À´Ï´Ù.

 

<´Ù¸¥ ÇÁ·ÎÁ§Æ®¸¦ ¹Ù²Ù¾î »ç¿ëÇÒ ¶§: mxp01_lcmax.zip>

 

 

5.1.3 ASE ÇÁ·ÎÁ§Æ® ¼öÁ¤

¸Æ½º SDK°¡ ¼³Ä¡µÈ Æú´õ¿¡¼­ "samples" Æú´õ¿¡´Â ´Ù¾çÇÑ Ç÷¯±×ÀÎ ¿¹Á¦µéÀÌ ÀÖ½À´Ï´Ù. ÀÌÁß¿¡¼­ "¸Æ½º SDK Æú´õ\samples\import_export\asciiexp" ¿¡´Â ¿©·¯ºÐ¿¡°Ô Ä£¼÷ÇÑ ASE ÆÄÀÏÀ» ¸¸µå´Â ¿¹Á¦°¡ ÀÖ½À´Ï´Ù. "asciiexp.vcproj" ÇÁ·ÎÁ§Æ®¸¦ ¿­°í º¯È¯À» ½ÃµµÇÏ¸é ´ÙÀ½°ú °°Àº ¿¡·¯¿¡ ´ëÇÑ ¸Þ½ÃÁö¸¦ º¼ ¼ö ÀÖ½À´Ï´Ù.

 

"±¸¹®À» ºÐ¼®ÇÏ´Â µ¿¾È ´ÙÀ½°ú °°Àº ¿À·ù°¡ ¹ß»ýÇß½À´Ï´Ù."

"ÆÄÀÏ: D:\_3dsMax8\maxsdk\samples\import_export\asciiexp\asciiexp.vcproj ÁÙ: 204 ¿­: 22 ¿À·ù ¸Þ½ÃÁö: ºÎ¸ð ¿ä¼Ò 'Configuration'ÀÇ ÄÜÅÙÃ÷ ¸ðµ¨¿¡ µû¸£¸é 'IntelOptions'Àº(´Â) ¿¹±âÄ¡ ¾ÊÀº ¿ä¼ÒÀÔ´Ï´Ù."

 

ÀÌ ¸Þ½ÃÁöÁö´Â Àü¿¡µµ º»ÀûÀÌ ÀÖ´Â ¸Þ½ÃÁö ÀÔ´Ï´Ù. asciiexp.vcproj ÆÄÀÏÀ» ¸Þ¸ðÀåÀ̳ª Edit plusµîÀ¸·Î ¿­¾î¼­ ÇØ´ç ¿­À» »èÁ¦ÇÕ´Ï´Ù.

 

"¸Æ½º SDK Æú´õ\help\ gencid.exe"¸¦ ½ÇÇàÇØ¼­ »õ·Î¿î ID¸¦ asciiexp.cppÆÄÀÏÀÇ »ó´Ü¿¡ ´ë·« 25¶óÀο¡ ÀÖ´Â Class_ID ¸¦ »õ·Î¿î ¾ÆÀ̵ð·Î ¹Ù²Ù¾î ÁÝ´Ï´Ù.

 

asciiexp.cppÆÄÀÏÀÇ 135 ¶óÀÎ ±ÙóÀÇ Ext(int n) ÇÔ¼öÀÇ ¹ÝȯÀ» ASE¿Í ±¸ºÐÇϱâ À§Çؼ­ ´ÙÀ½°ú °°ÀÌ asd·Î ¹Ù²Ù¾î ÁÝ´Ï´Ù.

 

const TCHAR * AsciiExp::Ext(int n)

{

        switch(n) {

        case 0:

               return _T("asd");

        }

        return _T("");

}

 

¸¶Áö¸·À¸·Î ÇÁ·ÎÁ§Æ®ÀÇ Ç÷¯±×ÀÎÀÌ Ãâ·ÂÇÒ Æú´õ¸¦ º¯°æÇÕ´Ï´Ù. ¸Þ´º à ÇÁ·ÎÁ§Æ® à "asciiexp" ¼Ó¼ºÀ» ¿­¾î¼­

"..\..\..\..\maxsdk\plugin\asciiexp.dle" ºÎºÐÀ» "..\..\..\..\plugins\asciiexp.dle" À¸·Î º¯°æÇÕ´Ï´Ù.

"maxsdk\plugin" ±×´ë·Î µÎ¸é ÄÄÆÄÀÏ ÇÑ ÈÄ¿¡ ´Ù½Ã Ç÷¯±×ÀÎÀ» ¿Å°Ü¾ß ÇÕ´Ï´Ù.

 

<¼öÁ¤µÈ ase: Ãâ·Â °æ·Î º¯°æ>

 

¸®¼Ò½º ºä¸¦ ¿­¾î IDD_ASCIIEXPORT_DLG¿¡ Å×½ºÆ®·Î ´ÙÀ½°ú °°ÀÌ ¹öưÀ» Ãß°¡ÇØ º¾½Ã´Ù.

 

<¸®¼Ò½º ºä: ´ÙÀ̾ó·Îµå ¼öÁ¤>

 

ÄÄÆÄÀÏ ÇÑ ´ÙÀ½ ½ÇÇàÇÏ°í ³ª¼­ ¸Æ½º¿¡¼­ ÆÄÀÏÀÌ Export°¡ µÇ´ÂÁö °£´ÜÇÑ ¹Ú½º ÇÑ °³¸¦ ±×¸³´Ï´Ù. ±×¸®°í ³ª¼­ ¸Þ´º à ÆÄÀÏ à Export ¸¦ ¼±ÅÃÇϸé ASD¸¦ ¼±ÅÃÇÒ ¼ö ÀÖ°í ´ÙÀ½°ú °°ÀÌ ÀúÀåÇØ º¾´Ï´Ù.

 

<Export ÆÄÀÏ ÀúÀå>

 

ÀÌ·¸°Ô Çϸé ÀÌÀü¿¡ ¸®¼Ò½º ºä¿¡¼­ ¼öÁ¤ÇÑ ´ÙÀ̾ó·Î±× È­¸éÀÌ ³ªÅ¸³ª°í OK ¹öưÀ» ´©¸£¸é È®ÀåÀÚ°¡ asd°¡ ºÙÀº ÆÄÀÏÀÌ »ý¼ºÀÌ µË´Ï´Ù.

 

"¸Æ½º Æú´õ\stdplugs" ¿¡´Â ±âº»ÀûÀ¸·Î Á¦°øµÇ´Â ¸Æ½º Ç÷¯±×ÀÎÀÌ ÀÖ½À´Ï´Ù. ¿©±â¿¡ 3ds¿Í aseµµ °°ÀÌ ÀÖ½À´Ï´Ù. À̵éÀ» ´Ù¸¥ °÷À¸·Î ¿Å°Ü ³õÀ¸¸é Export ¼±Åÿ¡¼­ Áö¿öÁý´Ï´Ù.

 

¸¸¾à asciexp ÇÁ·ÎÁ§Æ®¸¦ ´Ù¸¥ °÷À¸·Î ¿Å°Ü¼­ »ç¿ëÇÏ·Á¸é ¼Ó¼ºÀ» ¿­¾î¼­ C/C++ ÀÏ¹Ý à Ãß°¡ Æ÷ÇÔ µð·ºÅ丮°¡ »ó´ëÀûÀ¸·Î ¼³Á¤µÇ¾îÀÖ´Â °ÍÀ» Àý´ëÀûÀ¸·Î ¹Ù²Ù¾î ÁÝ´Ï´Ù.

 

"..\..\..\include" à "¸Æ½º SDK Æú´õ\include"

 

¸µÄ¿ à ÀÏ¹Ý à "Ãâ·Â ÆÄÀÏ À§Ä¡"¸¦ º¯°æÇÕ´Ï´Ù.

 

"..\..\..\..\plugins\asciiexp.dle" à "D:\_3dsMax8\plugins\asciiexp.dle"

 

¸µÄ¿ à ÀÔ·Â à "Ãß°¡ Á¾¼Ó¼º"¿¡ ¶óÀ̺귯¸®¸¦ Ãß°¡ÇÕ´Ï´Ù.

 

"odbc32.lib odbccp32.lib comctl32.lib"

à "odbc32.lib odbccp32.lib comctl32.lib core.lib geom.lib maxutil.lib mesh.lib"

 

¸®¼Ò½º à ÀÏ¹Ý à "Ãß°¡ Æ÷ÇÔ µð·ºÅ丮"¸¦ º¯°æÇÕ´Ï´Ù.

 

"..\..\..\include" à "¸Æ½º SDK Æú´õ\include"

 

¼Ö·ç¼Ç Ž»ö±â¿¡¼­ Libraries¸¦ ÀüºÎ »èÁ¦ÇÕ´Ï´Ù. ÀÌ ¶óÀ̺귯¸®µéÀº ¸µÄ¿ÀÇ ¶óÀ̺귯¸® Ãß°¡ Á¾¼Ó¼º¿¡ ÀÌ¹Ì Æ÷ÇÔ½ÃÄ×½À´Ï´Ù.

"¸Æ½º Æú´õ\plugins" ¿¡¼­ ÀÌÀü¿¡ ¿¬½ÀÀ¸·Î ÀÛ¼ºÇÑ Ç÷¯±×ÀÎ µéÀ» ÀüºÎ Á¤¸®ÇÏ°í ¼öÁ¤µÈ asciiexp¸¦ ÄÄÆÄÀÏ ÇØ¼­ À̰÷¿¡ »õ·Î »ý¼ºÀÌ µÇ´ÂÁö È®ÀÎÇÕ´Ï´Ù.

<ÇÁ·ÎÁ§Æ®¿¡ Æ÷ÇÔµÈ ¼Ö·ç¼Ç ¶óÀ̺귯¸® »èÁ¦>

 

mxp01_modified_ase.zipÀº asciiexpÀÇ ÇÁ·ÎÁ§Æ® À̸§°ú ÆÄÀÏ À̸§ µîÀ» ¼öÁ¤ÇÑ ¿¹Á¦ÀÔ´Ï´Ù.

°£´ÜÇÑ Ç÷¯±×ÀÎÀ̶ó¸é ase ÇÁ·ÎÁ§Æ®¸¦ Á¤¸®Çؼ­ »ç¿ëÇÏ´Â °ÍÀÌ °¡Àå ¹«³­ÇÕ´Ï´Ù. ase´Â °­Ã¼ ¾Ö´Ï¸ÞÀ̼Ç(Rigid Body Animation)À¸·Î ±¸¼ºµÇ¾î ÀÖ½À´Ï´Ù. ¸¸¾à ½ºÅ°´×À» ÃßÃâÇÏ·Á¸é ase¿Í ´Ù¸£°Ô ±¸¼ºÇØ¾ß ÇÕ´Ï´Ù. ¸ÕÀú ase¿¡¼­ »ç¿ëµÈ µ¥ÀÌÅÍ ÃßÃâ°ú ¾Ö´Ï¸ÞÀ̼ÇÀ» ±¸ÇöÇØ º¸°í ÀÌÈÄ¿¡ SkinngÀ» ±¸ÇöÇØ º¾½Ã´Ù.

 

 

5.1.4 Wrapper Ç÷¯±×ÀÎ

¸Æ½º´Â ÇÁ·Î±×·¥À» ½ÃÀÛÇÒ ¶§ Ç÷¯±×ÀÎÀ» ÀüºÎ ·Îµå Çϰí ÀÖ½À´Ï´Ù. µû¶ó¼­ Ç÷¯±×ÀÎÀ» Áö¿ì°Å³ª ±³Ã¼ÇÏ·Á¸é ¸Æ½º¸¦ ÁßÁö ½ÃÄÑ¾ß ÇÕ´Ï´Ù. À̰ÍÀº ÀÚÁÖ µð¹öµù ÇØ¾ß ÇÏ´Â Ç÷¯±×ÀÎ Á¦ÀÛ¿¡¼­´Â »ó´çÈ÷ ºÒÆíÇÕ´Ï´Ù. ÀÌ ¹®Á¦·Î °í»ýÇÏ´Ù°¡ Tom Hudson ¶ó´Â ºÐÀÌ Ç÷¯±×ÀÎÀ» Wrapping ÇÏ´Â ¹æ¹ýÀ» ÀÎÅͳݿ¡ ¾ÆÀ̵ð¾î¿Í Äڵ带 ¿Ã·Á³õ¾Ò½À´Ï´Ù. ´ÙÀ½ÀÇ ³»¿ëÀº Tom HudsonÀÌ ¸¸µç °ÍÀ» Á¤¸®ÇÑ °ÍÀÔ´Ï´Ù.

 

mxp01_lcmax.zip ¿¡¼­ »ý¼ºÀÚ LcMax Ŭ·¡½ºÀÇ »ý¼ºÀÚ ÇÔ¼ö, ¼Ò¸êÀÚ ÇÔ¼ö, Ext() ÇÔ¼ö, DoExport()ÇÔ¼ö¿¡ ´ÙÀ½°ú °°Àº ¸Þ½ÃÁö âÀ» ³Ö°í µð¹ö±×·Î ½ÇÇàÇØ º¾½Ã´Ù.

 

LcMax::LcMax()

{

¡Ü      MessageBox(NULL, "Constructor LcMax", "Message", 0);

}

 

LcMax::~LcMax()

{

¡Ü      MessageBox(NULL, "Destroyer LcMax", "Message", 0);

}

 

const TCHAR *LcMax::Ext(int n)

{

¡Ü      MessageBox(NULL, "Constructor LcMax", "Message", 0);

        return _T("acm");

}

 

int     LcMax::DoExport(¡¦)

{

¡Ü      MessageBox(NULL, "Do Export LcMax", "Message", 0);

 

}

 

¸Æ½º¿¡¼­ ¹Ú½º¸¦ Çϳª ±×¸®°í ÆÄÀÏ à Export¸¦ ¼±ÅÃÇÕ´Ï´Ù. ±×·¯¸é LcMax Ŭ·¡½ºÀÇ »ý¼ºÀÚÀÇ ºê·¹ÀÌÅ© Æ÷ÀÎÅÍ¿¡ ÇÁ·Î¼¼½º°¡ °É¸³´Ï´Ù. ¶Ç ÁøÇà Çϸé Ext() ÇÔ¼ö¿¡¼­, ±×¸®°í ´Ù½Ã ÁøÇàÇÏ¸é ¼Ò¸êÀÚ¿¡¼­ ÇÁ·Î¼¼½º°¡ ÁøÇàµÊÀ» ¾Ë ¼ö ÀÖ½À´Ï´Ù. ÀÌ µ¿ÀÛÀº Export¸¦ ¼±ÅÃÇÒ ¶§ ¸Æ½º°¡ Ç÷¯±×ÀεéÀÇ À̸§À» ¾ò´Â °úÁ¤ÀÎ °ÍÀ» ¾Ë ¼ö ÀÖ½À´Ï´Ù. ÀúÀåÇÒ À̸§À» ¼±ÅÃÇÏ°í °è¼ÓÇÏ¸é »ý¼ºÀÚ à DoExport() à ¼Ò¸êÀÚ·Î ÇÁ·Î¼¼½º°¡ ÁøÇàµÊÀ» º¼ ¼ö ÀÖ½À´Ï´Ù.

ÀÌ µÎ µ¿ÀÛÀ» Á¤¸®ÇÏ¸é ¸Æ½º´Â Ç÷¯±×ÀÎÀ» ÇÁ·Î±×·¥¿¡¼­ ·ÎµåÇϰí ÀÖ°í ¸¸¾à Export°¡ ¿äûÀÌ µÇ¸é SceneExport Ŭ·¡½º¸¦ »ó¼Ó¹ÞÀº °´Ã¼ÀÇ »ý¼ºÀÚ à ÀÛ¾÷¿¡ ÇÊ¿äÇÑ ÇÔ¼ö È£Ãâ à ¼Ò¸êÀÚ¸¦ ¹Ýº¹ÇÑ´Ù°í ÇÒ ¼ö ÀÖ½À´Ï´Ù.

 

¾Õ¼­ ¸Æ½ºÀÇ Ç÷¯±×ÀÎÀº DLLÀ̶ó°í Çß½À´Ï´Ù. Wrapper Ç÷¯±×ÀÎÀÇ ÀÛµ¿ ¼ø¼­´Â ÀÛ¾÷ ¿äûÀÌ ¿À¸é ±× ÀÛ¾÷¿¡ ÇØ´çÇÏ´Â Child Ç÷¯±×ÀÎÀ» ·Îµå Çϰí Child Ç÷¯±×ÀÎÀÇ ÀÛ¾÷À» ½ÇÇàÇÑ ´ÙÀ½, ¼Ò¸êÀÚ¿¡¼­ Child DLLÀ» ÇØÁ¦ÇÕ´Ï´Ù. À̰ÍÀ» ±×¸²À¸·Î Ç¥ÇöÇÏ¸é ´ÙÀ½°ú °°½À´Ï´Ù.

 

<¸Æ½º¿¡ »ç¿ëµÇ´Â Ç÷¯±×ÀÎ: ÀϹÝÀûÀÎ Ç÷¯±×Àΰú Wrapper Ç÷¯±×ÀÎ>

 

Wrapper Ç÷¯±×ÀÎÀ» ¸¸µé±â À§Çؼ­ LcMax Ç÷¯±×ÀÎÀÇ À̸§À» LcWrapper·Î ¹Ù²ß´Ï´Ù. ´ÙÀ½À¸·Î Å×½ºÆ®¸¦ À§ÇØ "plugins" Æú´õ¿¡ ÀÖ´ø "asdexp.dle" C µå¶óÀÌºê ·çÆ®·Î ¿Å°Ü ³õ¾Ò½À´Ï´Ù. ÀÌ Ç÷¯±×ÀÎÀ» LcWrapper Ç÷¯±×ÀÎÀÌ ·¡ÇÎ(Wrapping)ÇÒ °ÍÀÔ´Ï´Ù.

 

LcWrapper Ŭ·¡½º´Â ´ÙÀ½°ú °°ÀÌ 3 °³ÀÇ ¸â¹ö º¯¼ö¸¦ Ãß°¡ÇÕ´Ï´Ù.

 

class LcWrapper : public SceneExport

¡¦

        HINSTANCE      m_hInst;       // DLL Instance

        ClassDesc*     m_pChildDesc;  // DLL ¿¡¼­ ¾òÀº Child °´Ã¼ ÁÖ¼Ò

        SceneExport*   m_pChild;      // Export¿¡ ¿äûµÇ´Â ÀÛ¾÷À» ´ã´çÇÒ °´Ã¼

 

m_pChildDesc º¯¼ö´Â DLL¿¡¼­ ¾òÀº ClassDesc2 Ŭ·¡½º¸¦ »ó¼Ó¹ÞÀº °´Ã¼ÀÇ ÁÖ¼ÒÀÔ´Ï´Ù. ÀÌ °´Ã¼ÀÇ  Create()ÇÔ¼ö¸¦ ÀÌ¿ëÇØ¼­ m_pChild °´Ã¼¸¦ »ý¼ºÇÕ´Ï´Ù.

 

À̰ÍÀ» ±¸Ã¼ÀûÀ¸·Î ±¸ÇöÇϸé LcWrapper Ŭ·¡½ºÀÇ »ý¼ºÀÚ´Â ·¡ÇÎ ´ë»ó Ç÷¯±×ÀÎ(DLL)À» ·ÎµåÇϱâ À§ÇØ LoadLibray()ÇÔ¼ö¸¦ »ç¿ëÇÕ´Ï´Ù. ´ÙÀ½À¸·Î GetProcAddress() ÇÔ¼ö¸¦ ÀÌ¿ëÇØ¼­ ClassDesc °´Ã¼ÀÇ ÁÖ¼Ò¸¦ ¾ò¾î¿É´Ï´Ù. ¸¶Áö¸·À¸·Î ClassDesc Ŭ·¡½ºÀÇ Create()ÇÔ¼ö¸¦ È£ÃâÇØ¼­ SceneExport °´Ã¼¸¦ »ý¼ºÇÕ´Ï´Ù.

 

LcWrapper::LcWrapper()

{

m_hInst        = NULL;

        m_pChildDesc   = NULL;

        m_pChild       = NULL;

 

        // Load Plugin(DLL)

        m_hInst = LoadLibrary( "c:/asdexp.dle");

 

        if (!m_hInst)

        {

               MessageBox(NULL, "Load c:/asdexp.dle Failed", "Err", MB_ICONWARNING);

               m_hInst = NULL;

               return;

        }

 

        // DLL¿¡¼­ Á¦°øÇÏ´Â ÇÔ¼ö Áß Export¸¦ »ý¼ºÇÒ ¼ö ÀÖ´Â °´Ã¼ ÁÖ¼Ò ¹Ýȯ ÇÔ¼ö ¾ò±â

        typedef ClassDesc* (__stdcall *_LibClassDesc)(int i);

 

        _LibClassDesc pLibClassDesc

 = (_LibClassDesc) GetProcAddress(m_hInst, "LibClassDesc");

 

        if (pLibClassDesc)

        {

               m_pChildDesc = pLibClassDesc(0);

 

               // Export¸¦ ´ã´çÇÒ °´Ã¼ »ý¼º

               m_pChild = (SceneExport*)m_pChildDesc->Create();

        }

}

 

DLLÀÇ .def ÆÄÀÏ¿¡ ÀÖ´Â EXPORTS ¼½¼Ç¿¡ "LibClassDesc @3"·Î Á¤ÀǵǾî ÀÖ¾î ÇÔ¼öÀÇ À̸§´ë½Å ¼ýÀÚ·Î ´ë½ÅÇØµµ µË´Ï´Ù. ¼ýÀÚ¸¦ »ç¿ëÇϸé 󸮰¡ Á» ´õ »¡¶óÁø´Ù°í ÇÕ´Ï´Ù.

 

GetProcAddress(m_hInst, (LPCSTR)3);

 

¼Ò¸êÀÚ´Â »ý¼ºÀÚ¿¡¼­ ¸¸µé¾îÁø SceneExport °´Ã¼ m_pChild¸¦ ¸ÕÀú ÇØÁ¦ Çϰí Ç÷¯±×ÀÎÀ» ÇØÁ¦ÇÕ´Ï´Ù.

 

LcWrapper::~LcWrapper()

{

        if(m_pChild)

        {

               delete m_pChild;

               m_pChild = NULL;

        }

 

        // Plugin ÇØÁ¦

        if(m_hInst)

        {

               FreeLibrary(m_hInst);

               m_hInst = NULL;

        }

}

 

°¡Àå Áß¿äÇÑ ÇÔ¼ö DoExport() ÇÔ¼ö¸¦ ´ÙÀ½°ú °°ÀÌ ¼öÁ¤ÇÕ´Ï´Ù.

 

int     LcWrapper::DoExport(const TCHAR *name,ExpInterface *ei

,Interface *i, BOOL suppressPrompts, DWORD options)

{

        if(m_pChild)

               return m_pChild->DoExport(name, ei, i, suppressPrompts, options);

        return FALSE;

}

 

ÀÌ·± ¹æ½ÄÀ¸·Î ³ª¸ÓÁö ÇÔ¼öµéµµ ÀüºÎ ¹Ù²Ù¾î ÁÝ´Ï´Ù.

 

const TCHAR *LcWrapper::Ext(int n)

{

        if(m_pChild)

               return m_pChild->Ext(n);

        return _T("Failed Ext");

}

 

<Wrapper Plugin: mxp01_wrapper.zip>

 

Àüü ÄÚµå´Â mxp01_wrapper.zipÀ» Âü°í Çϱ⠹ٶø´Ï´Ù. ·¡ÇÎÀÌ Á¦´ë·Î µÇ°í ÀÖ´ÂÁö È®ÀÎÇϱâ À§Çؼ­ ´ÙÀ½°ú °°ÀÌ ¸¸µé¾î º¸¾Ò½À´Ï´Ù.

 

const TCHAR *LcWrapper::ShortDesc()

static TCHAR s[1024];

        if(m_pChild)   _stprintf(s, "Wrap(%s)", m_pChild->ShortDesc());

        else           _stprintf(s, _T("Failed to load Wrap"));

        return s;

 

 

5.2 Data Export

5.2.1 Node Export

¸Æ½º´Â ¸ðµç °´Ã¼¸¦ ³ëµå(Node)·Î °ü¸®ÇÕ´Ï´Ù. ÀÌ ³ëµå´Â ´ÙÀ½ ±×¸²°ú °°ÀÌ ³ª¹« ÀÚ·á ±¸Á¶(Tree Data Structure)·Î ±¸¼ºµÇ¾î ÀÖ½À´Ï´Ù.

 

<³ª¹« ÀÚ·á ±¸Á¶(Tree Data Structure)>

 

¸Æ½º´Â INode ¶ó´Â ÀÎÅÍÆäÀ̽º¸¦ Á¦°øÇϸç INode ÀÎÅÍÆäÀ̽º ÀÇ ¿©·¯ ÇÔ¼ö Áß¿¡¼­ NumberOfChildren(), GetChildNode(index), GetParentNode(), GetParentNode() ÇÔ¼ö µîÀ¸·Î ÇÏÀ§³ëµå ¼ýÀÚ, ÇÏÀ§ ³ëµå, ºÎ¸ð ³ëµå, Root ³ëµå µîÀ» ãÀ» ¼ö ÀÖ½À´Ï´Ù.

 

¸Æ½º´Â Exporter ¸í·ÉÀÌ ÁÖ¾îÁö¸é SceneExport Ŭ·¡½º¸¦ »ó¼Ó¹ÞÀº Ŭ·¡½º ¸â¹ö ÇÔ¼ö Áß¿¡¼­ DoExport() ÇÔ¼öÀÇ ¼¼ ¹øÂ° ÀμöÀÎ Interface* °´Ã¼ÀÇ GetRootNode() ÇÔ¼ö¸¦ ÀÌ¿ëÇØ¼­ Root Node¸¦ ¾òÀ» ¼ö ÀÖ½À´Ï´Ù. °£´ÜÇÏ°Ô Root Node¿Í À̸§, ÇÏÀ§³ëµåµéÀ» ã´Â´Ù¸é ´ÙÀ½°ú °°ÀÌ ÄÚµù ÇÏ¸é µË´Ï´Ù.

 

int LcMax::DoExport(¡¦,Interface *pi,¡¦)

 

INode*  pRoot = m_pI->GetRootNode();

TCHAR*  sName  = pRoot->GetName();

INT     nChild = pRoot->NumberOfChildren();

 

À̰ÍÀ» ½ÇÇàÇÏ¸é ¸Æ½ºÀÇ Root Node À̸§Àº "Scene Root"·Î Ãâ·ÂÀÌ µË´Ï´Ù.

¸¸¾à ¸Æ½º¿¡ ÀÛ¾÷ÇÑ ¸ðµç Node¸¦ ExportÇÒ ¶§´Â Scene RootºÎÅÍ ÇÏÀ§ ³ëµå(Child Node)µéÀ» Àç±Í(Recursive) ¼øÈ¯À» Àû¿ëÇØ¼­ ã¾Æ¾ß ÇÕ´Ï´Ù. À̸¦ À§Çؼ­ ¸ÕÀú ´ÙÀ½°ú °°ÀÌ INode °´Ã¼ ÁÖ¼Ò¸¦ ÀúÀå Çϱâ À§ÇØ STLÀÇ º¤ÅÍ ÄÁÅ×À̳ʸ¦ ¼±¾ðÇÕ´Ï´Ù.

 

std::vector<INode*>    m_vMaxNode;            // ¸Æ½ºÀÇ ³ëµå ÀڷᱸÁ¶

 

±×¸®°í ´ÙÀ½°ú °°Àº Àç±Í ÇÔ¼ö¸¦ ÀÌ¿ëÇØ¼­ ÀÌ º¤ÅÍ ÄÁÅ×À̳ʿ¡ ³ëµåÀÇ ÁÖ¼Ò¸¦ ÀúÀåÇÕ´Ï´Ù.

 

void LcMax::GatherNode(INode* pNode)

{

        if(!pNode)

               return;

 

        INT iChild = pNode->NumberOfChildren();

 

        for(int i=0; i<iChild; ++i)

        {

               INode* pChild = pNode->GetChildNode(i);

 

               if(pChild)

                       GatherNode(pChild);

        }

}

 

ÀÌ ¹æ½ÄÀº ±íÀÌ ¿ì¼± Ž»ö ¹æ½Ä(DFS)ÀÔ´Ï´Ù. ÀÌ·¸°Ô ³ëµå¸¦ ¸ðÀ¸°í À̰ÍÀ» ÆÄÀÏ·Î ÀúÀåÇÕ´Ï´Ù.

 

FILE*   fp = fopen(m_sN, "wt");

 

INode*  pRoot = m_pI->GetRootNode();

 

GatherNode(pRoot);

 

for(n =0; n<m_vMaxNode.size(); ++n)

{

        INode*  pNode = m_vMaxNode[n];

        TCHAR*  sName  = pNode->GetName();

        INT     nChild = pNode->NumberOfChildren();

 

if(pRoot == pNode->GetParentNode())

                       fprintf(fp, "\n");

 

        fprintf(fp, "Node Name: %s, Child Number: %d\n", sName, nChild);

}

 

fclose(fp);

 

ÇÁ·Î±×·¥À» ¿ÏÀüÇϱâ À§ÇØ ¸®¼Ò½º ºä¿¡¼­ ´ÙÀ̾ó·Î±×¿¡ ´ÙÀ½°ú °°Àº ¹öưÀ» ¸¸µì´Ï´Ù.

 

 

¶ÇÇÑ DoExport¹öưÀ» ´©¸£¸é Export°¡ ½ÇÇàµÇµµ·Ï ´ÙÀ½°ú °°ÀÌ Äݹé ÇÔ¼ö¸¦ ¼öÁ¤ÇÕ´Ï´Ù.

 

INT_PTR CALLBACK LcMaxOptionsDlgProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam)

¡¦

        WPARAM wLoParam = LOWORD(wParam);

        WPARAM wHiParam = HIWORD(wParam);

 

        if( WM_INITDIALOG == uMsg)

¡¦

        else if( WM_COMMAND == uMsg)

        {

               if(imp && IDC_EXPORT == wLoParam)

               {

                       imp->m_bDoExport = TRUE;

                       SendMessage(hWnd, WM_CLOSE, 0, 0);

               }

 

               return TRUE;

        }

¡¦

 

´ÙÀ̾ó·Î±×¿¡ ¹öư Ãß°¡¿Í ¸Þ½ÃÁö 󸮿¡ ´ëÇÑ ÀÚ¼¼ÇÑ ³»¿ëÀº WinAPI¸¦ Âü°í Çϱ⠹ٶø´Ï´Ù.

ÀÌ·¸°Ô ¸¸µç Äڵ带 Å×½ºÆ®Çϱâ À§Çؼ­ ´ÙÀ½°ú °°ÀÌ ¸Æ½º¸¦ ½ÇÇàÇÏ°í ¸Þ´º à Create à System à Biped¸¦ ¼±ÅÃÇØ¼­ Biped ÀÎÇü 2°³¸¦ È­¸é¿¡ ±×¸³´Ï´Ù.

 

<Biped Ãß°¡>

 

¶Ç´Â ¿ìÃøÀÇ Create Tab¿¡¼­ Åé´Ï¹ÙÄû µÎ °³°¡ ¹°·Á ÀÖ´Â ¹öưÀ» ´©¸£¸é Systems ¹öưÀÌ ³ª¿À°í ÀÌÁß¿¡¼­ Biped ¹öưÀ» ¼±ÅÃÇÑ ´ÙÀ½ Biped¸¦ Ãß°¡ÇÕ´Ï´Ù.

ÀÌ Biped´Â ¸Æ½º°¡ ¾Ö´Ï¸ÞÀ̼ÇÀ» Æí¸®ÇÏ°Ô ÀÛ¼ºÇÒ ¼ö ÀÖµµ·Ï Á¦°øµÇ´Â À¯Æ¿¸®Æ¼ÀÌ¸ç ³ª¹« ±¸Á¶(Tree Structure)·Î ±¸¼ºµÇ¾î ÀÖ½À´Ï´Ù. ÀÌ BipedÀÇ ³ëµå¸¦ ÆÄÀÏ·Î ÀúÀåÇÒ ¼ö ÀÖÀ¸¸é ³ª¸ÓÁö ¸Æ½º¿¡¼­ ±¸¼ºµÈ ¿ÀºêÁ§Æ®ÀÇ ³ëµåµéµµ °°Àº ¹æ¹ýÀ¸·Î ÆÄÀÏ¿¡ ÀúÀåÇÒ ¼ö ÀÖ½À´Ï´Ù.

ÀÌ·¸°Ô Biped 2°³¸¦ ¸¸µé°í ExportÇÑ ´ÙÀ½ ÆÄÀÏÀ» ¿­¾îº¸¸é "Scene Root" ºÎÅÍ "Bip01", " Bip02"·Î ½ÃÀÛÇÏ´Â ³ëµåµéÀÌ ¸ðµÎ ±â·ÏµÇ¾î ÀÖÀ½À» º¼ ¼ö ÀÖ½À´Ï´Ù.

 

Âü°í·Î ¸Æ½ºÀÇ Schematic View¸¦ ¼±ÅÃÇϸé ÇöÀç ¸Æ½º¿¡ ÀÖ´Â °´Ã¼°¡ ³ªÅ¸³³´Ï´Ù.

 

<Schematic View>

 

Àüü ÄÚµå´Â mxp11_nodes.zip¸¦ Âü°í Çϱ⠹ٶø´Ï´Ù.

 

 

5.2.2 Object Export

Root ³ëµå¸¦ Á¦¿ÜÇÑ ¸ðµç ³ëµå´Â Object¸¦ °¡Áö°í ÀÖ½À´Ï´Ù. ÀÌ Object´Â NodeÀÇ ¿ªÇÒÀ̶ó »ý°¢ÇÏ¸é µË´Ï´Ù. ¸Æ½ºÀÇ Object´Â ½Ã½ºÅÛ¿¡¼­ ÆÄ»ýµÈ Derived Object¿Í Procedural Object µÎ Á¾·ù°¡ ÀÖ½À´Ï´Ù. Derived Object´Â ½Ã½ºÅÛÀÇ ÇÑ ºÎºÐÀ¸·Î¼­ º¯°æÀÌ ºÒ°¡´ÉÇϸç Procedural Object´Â Ä«¸Þ¶ó, Á¶¸í, Helper, Geometry µî ¼öÁ¤ÀÌ °¡´ÉÇÑ ObjectÀÔ´Ï´Ù.

 

<¸Æ½ºÀÇ ¿©·¯ Á¾·ù Object>

 

³ëµåÀÇ ¿ªÇÒÀ» ¾Ë¾Æº¸±â À§ÇØ ´ÙÀ½°ú °°ÀÌ Object TypeÀ» È®ÀÎÇÕ´Ï´Ù.

 

Object* pObject = pNode->GetObjectRef();

 

if(pObject)

{

        SClass_ID lSuperID = pObject->SuperClassID();

        Class_ID lClassID = pObject->ClassID();

 

        if(GEOMOBJECT_CLASS_ID == lSuperID)

        {

               if( BONE_OBJ_CLASSID == lClassID || Class_ID(BONE_CLASS_ID, 0) == lClassID)

               {

               }

               else

               {

               }

        }

        else if(CAMERA_CLASS_ID == lSuperID)

¡¦

        else if(LIGHT_CLASS_ID == lSuperID)

¡¦

}

 

Ä«¸Þ¶ó, Á¶¸í, Helper, Shape µîÀº °ÔÀÓ ³»ºÎ¿¡¼­ Á¤ÇÑ µ¥ÀÌÅ͸¦ »ç¿ëÇÕ´Ï´Ù. µû¶ó¼­ À̵éÀº Ưº°ÇÑ °æ¿ì°¡ ¾Æ´Ï¶ó¸é º¸ÅëÀº Á¦¿Ü´ë»óÀÌ¸ç ¿ì¸®ÀÇ ÁÖ °ü½ÉÀº Geometry Object ÀÔ´Ï´Ù.

Geometry Objectµµ ClassID() ÇÔ¼ö·Î ÇÑ ¹ø Á¶»çÇØ¾ß ÇÒ ³»¿ëÀÌ ÀÖ½À´Ï´Ù. ¾Ö´Ï¸ÞÀ̼ÇÀ» Á» ´õ Æí¸®ÇÏ°Ô Çϱâ À§Çؼ­ Bone, ¶Ç´Â Bipe¸¦ ÀÌ¿ëÇÕ´Ï´Ù. À̵鵵 Æú¸®°ïÀÌ ÀÖÀ¸¸ç Geometry class ÀÔ´Ï´Ù. ExportµÈ µ¥ÀÌÅ͸¦ È®ÀÎÇÏ´Â Viewer ÇÁ·Î±×·¥¿¡¼­ ¾Ö´Ï¸ÞÀ̼ÇÀ» ´«À¸·Î »ìÇDZâ À§ÇØ BoneÀ» È­¸é¿¡ Ç¥½ÃÇϹǷΠÀûÁ¤ÇÑ Á¤Á¡ ±¸Á¶Ã¼¿Í Æ÷¸ËÀ¸·Î À̵鵵 ÃßÃâÇØ¾ß ÇÕ´Ï´Ù. Bone 󸮿¡ ´ëÇØ¼­´Â ÀÌÈÄ ¾Ö´Ï¸ÞÀ̼ǿ¡¼­ ´Ù½Ã ÇϰڽÀ´Ï´Ù.

 

Àüü ÄÚµå´Â mxp12_object.zipÀÇ LcMax::DoExport() ÇÔ¼ö¸¦ Âü°íÇϱ⠹ٶø´Ï´Ù.

 

 

5.2.3 Mesh

¸Æ½º´Â Mesh¸¦ ÅëÇØ¼­ È­¸é¿¡ ¿ÀºêÁ§Æ®¸¦ Ç¥ÇöÇÕ´Ï´Ù. ¸Þ½¬´Â Á¤Á¡ µ¥ÀÌÅÍ, À妽º µ¥ÀÌÅÍ µîÀ» Æ÷ÇÔÇϰí À־ ¿ì¸®´Â À̰ÍÀ» ExportÇØ¼­ °ÔÀÓ¿¡¼­ Á¤Á¡ ¹öÆÛ¿Í À妽º ¹öÆÛ·Î »ç¿ëÇØ¾ß ÇÕ´Ï´Ù.

 

¿ì¸®´Â °ÔÀÓ¿¡¼­ ÁÖ·Î »ï°¢ÇüÀ» ±âº»À¸·Î ·»´õ¸µ ¿ÀºêÁ§Æ®¸¦ ±¸¼ºÇÕ´Ï´Ù. ±×·±µ¥ ¸Æ½ºÀÇ Primitive´Â D3D º¸´Ù ´Ù¾çÇØ¼­ ¸Æ½ºÀÇ ¸Þ½¬¸¦ D3D¿¡¼­ »ç¿ëÇÒ ¼ö ÀÖµµ·Ï ¹Ù²Ù¾î¾ß ÇÕ´Ï´Ù.

¸ÕÀú ¸Æ½ºÀÇ Object¿¡°Ô »ï°¢ÇüÀ¸·Î ¸Þ½¬ÀÇ ±¸Á¶¸¦ ¹Ù²Ü ¼ö ÀÖ´ÂÁö CanConvertToType() ÇÔ¼ö·Î È®ÀÎÇϰí, ÀüȯÀÌ °¡´ÉÇϸé ConvertToType() ÇÔ¼ö·Î Æú¸®°ïÀ» ±¸¼ºÇÏ´Â TriObject¸¦ ´ÙÀ½°ú °°ÀÌ ¾ò¾î ³À´Ï´Ù.

 

if(!pObj->CanConvertToType(Class_ID(TRIOBJ_CLASS_ID, 0)))

        continue;

 

TriObject* pTri = (TriObject *)pObj->ConvertToType(0, Class_ID(TRIOBJ_CLASS_ID, 0));

 

´ÙÀ½À¸·Î TriObject¿¡¼­ Mesh¸¦ ´ÙÀ½°ú °°ÀÌ ¾ò½À´Ï´Ù.

 

Mesh* pMesh    = &pTri->GetMesh();

 

ÀÌ Mesh¿¡ Æú¸®°ïÀ» ±¸¼ºÇÏ´Â °¢°¢ÀÇ »ï°¢Çü¿¡ ´ëÇÑ À妽º µ¥ÀÌÅÍ¿Í Á¤Á¡ µ¥ÀÌÅͰ¡ Æ÷ÇÔµÇ¾î ´ÙÀ½°ú °°ÀÌ À妽º, Á¤Á¡ÀÇ ¼ýÀÚ¸¦ ¾ò°í, ÀÌ ¼ýÀÚ¸¸Å­ ȸÀüÇϸ鼭 À妽º, Á¤Á¡ µ¥ÀÌÅ͸¦ ¾ò¾î ³À´Ï´Ù.

 

INT     iNvtx   = pMesh->getNumVerts();

INT     iNfce   = pMesh->getNumFaces();

 

// À妽º µ¥ÀÌÅÍ Ãâ·Â

for (i=0; i<iNfce; ++i)

{

        INT a, b, c;

        a = pMesh->faces[i].v[0];

        b = pMesh->faces[i].v[1];

        c = pMesh->faces[i].v[2];

 

        fprintf(fp, "  %4d %4d %4d\n", a, b, c);

}

 

// Á¤Á¡ µ¥ÀÌÅÍ Ãâ·Â

for (i=0; i<iNvtx; ++i)

{

        Point3 v = pMesh->verts[i];

        fprintf(fp, "  %12.5f %12.5f %12.5f\n", v.x, v.y, v.z);

}

 

Àüü ÄÚµå´Â mxp13_mesh01.zipÀ» Âü°íÇϱ⠹ٶø´Ï´Ù.

 

 

5.2.4 Viewer

¿ì¸®°¡ Exporter¸¦ ¸¸µå´Â °ÍÀº °ÔÀÓ¿¡¼­ ÇÊ¿äÇÑ µ¥ÀÌÅ͸¦ ¸¸µé±â À§ÇÔÀÔ´Ï´Ù. µû¶ó¼­ Áö±ÝºÎÅÍ ÃßÃâÇÑ µ¥ÀÌÅͰ¡ ¿øÇÏ´Â ÇüÅ·Π±¸¼ºµÇ¾î ÀÖ´ÂÁö ºä¾î(Viewer) ÇÁ·Î±×·¥À¸·Î È®ÀÎ ÇØ¾ß Çϰí À̸¦ À§Çؼ­ ÀڷᱸÁ¶°¡ ÇÊ¿äÇÕ´Ï´Ù.

ÀÌÀü¿¡ ÀÛ¼ºÇÑ Mesh¸¦ ¼öÁ¤Çؼ­ View¿¡ ¿Ã¸± ¼ö ÀÖ´Â ÇüÅ·ΠÀڷᱸÁ¶¸¦ ±¸¼ºÇØ º¾½Ã´Ù.

¸ÕÀú Á¤Á¡ÀÇ À妽º¿Í À§Ä¡¸¦ ÀúÀåÇÒ ´ÙÀ½°ú °°Àº ±¸Á¶Ã¼¸¦ ¼±¾ðÇÕ´Ï´Ù.

 

struct VtxIdx

{

        WORD a, b, c;

};

 

struct VtxPos

{

        FLOAT x, y, z;

};

 

struct LcGeo

{

        INT            nFce;   // Number of Face

        INT            nPos;   // Number of Position

        VtxIdx*        pFce;   // Face List

        VtxPos*         pPos;   // Position List

};

 

LcMax Ŭ·¡½º¿¡ ´ÙÀ½°ú °°Àº ¸â¹ö º¯¼ö¸¦ Ãß°¡ÇÕ´Ï´Ù.

 

class LcMax : public SceneExport

¡¦

INT     m_nGeo;        // Number of Geometry

LcGeo*  m_pGeo;        // Geometry Data

 

ÀÌÀüó·³ ÆÄÀÏ¿¡ ±×³É Ãâ·ÂÀ» ÇÏ¸é ºä¾î¿¡¼­ µ¥ÀÌÅ͸¦ Àоî¿À´Âµ¥ Àϰü¼ºÀÌ ¶³¾îÁö¹Ç·Î Node¸¦ ¸ðÀ¸°í ³ª¼­ Geometry Data¸¦ ¸¸µé°í µ¥ÀÌÅ͸¦ ä¿î ÈÄ¿¡ ÆÄÀÏ·Î Ãâ·ÂÀ» ÇØ¾ß ÆÄÀÏ ±¸Á¶°¡ ¿Ï¼º µË´Ï´Ù. ¶ÇÇÑ Geometry¿¡ ´ëÇÑ ÀÚ·á ±¸Á¶°¡ ¿Ï¼ºµÇ¾î ÀÖÀ¸¸é ºä¾î¿¡¼­ ÅØ½ºÆ® ÆÄÀÏÀ» Àд °Íº¸´Ù ÀÌÁø(Binary) ÆÄÀÏÀ» Àд °ÍÀÌ Æí¸®Çؼ­ °ÔÀÓ ¶Ç´Â ºä¾î¿¡¼­´Â ÀÌÁø ÆÄÀÏÀ» »ç¿ëÇÏ°í ´«À¸·Î È®ÀÎ Çϱâ À§ÇÑ ¿ëµµ·Î´Â ÅØ½ºÆ® ÆÄÀÏÀ» »ç¿ëÇÕ´Ï´Ù. À̸¦ À§ÇØ ¸¶Áö¸·¿¡ ÀÌ µÎ Á¾·ùÀÇ ÆÄÀÏ¿¡ µ¥ÀÌÅ͸¦ ÀúÀåÇÕ´Ï´Ù.

 

int     LcMax::DoExport(¡¦)

¡¦

// 1. Gather Node

INode*  pRoot = m_pI->GetRootNode();

GatherNode(pRoot);

 

// 2. Create and Setup Geometry

if(FAILED(SetupGeometry()))

        return FALSE;

 

// 3. Geometry¸¦ ÀÌ¿ëÇØ Binary, Text ÆÄÀÏ·Î Ãâ·Â

WriteBinary();

WriteText();

¡¦

 

void LcMax::WriteBinary()

¡¦

        fwrite(&m_nGeo, 1, sizeof(INT), fp);

 

        for(n =0; n<m_nGeo; ++n)

        {

               LcGeo* pGeo = &m_pGeo[n];

               fwrite(pGeo->sName,  1, sizeof(char)*32, fp); // Node Name

               fwrite(&pGeo->nType, 1, sizeof(INT )  , fp);  // Node Type

               fwrite(&pGeo->nFce,  1, sizeof(INT )  , fp);  // Index Number

               fwrite(&pGeo->nPos,  1, sizeof(INT )  , fp);  // Vertex Number

¡¦

               fwrite(pGeo->pFce, pGeo->nFce, sizeof(VtxIdx), fp);

               fwrite(pGeo->pPos, pGeo->nPos, sizeof(VtxPos), fp);

        }

 

Àüü ÄÚµå´Â mxp13_mesh02.zip¸¦ Âü°í Çϱ⠹ٶø´Ï´Ù.

 

´ÙÀ½À¸·Î ºä¾î¸¦ ¸¸µé¾î¾ß ÇÕ´Ï´Ù. ºä¾î¿¡¼­ ÀÌÁø ÆÄÀÏÀ» Àд ¹æ¹ýÀº void LcMax::WriteBinary()

ÇÔ¼öÀÇ fwrite() ÇÔ¼ö ´ë½Å fread() ÇÔ¼ö·Î ¹Ù²Ù°í new ¿¬»êÀÚ·Î µ¿Àû ÇÒ´çÀ» ÇÏ¸é µË´Ï´Ù.

mxp13_viewer1.zipÀº mxp13_mesh02.zip¿¡¼­ ÃßÃâÇÑ µ¥ÀÌÅ͸¦ È®ÀÎÇÏ´Â ºä¾îÀ̸ç CLcmAcm Ŭ·¡½º´Â ÀÌÁø ÆÄÀÏÀ» Àо È­¸é¿¡ Ãâ·ÂÇϴ Ŭ·¡½º ÀÔ´Ï´Ù. ÀÌ Å¬·¡½ºÀÇ LoadMdl() ÇÔ¼ö´Â ¸ðµ¨À» ÀÐ¾î ¿À´Â ÇÔ¼ö·Î LcMax::WriteBinary()¿Í ´ëÀÀÇÏ´Â ÇÔ¼öÀÔ´Ï´Ù. ÆÄÀÏ¿¡¼­ µ¥ÀÌÅ͸¦ Àоî¿Ã ¶§ Geometry¿Í À妽º, ¹öÅØ½º µ¥ÀÌÅÍ´Â new ¿¬»êÀÚ·Î µ¥ÀÌÅ͸¦ µ¿Àû ÇÒ´çÇϰí ÀÖÀ½À» ÁÖÀÇÇØ¾ß ÇÕ´Ï´Ù.

 

INT CLcmAcm::LoadMdl(char* sFile)

¡¦

        fread(&m_nGeo, 1, sizeof(INT), fp);

¡¦

        m_pGeo = new LcGeo[m_nGeo];

 

        for(n =0; n<m_nGeo; ++n)

        {

               LcGeo* pGeo = &m_pGeo[n];

               fread(&pGeo->nFce, 1, sizeof(INT) , fp);

               fread(&pGeo->nPos, 1, sizeof(INT) , fp);

¡¦

               pGeo->pFce = new VtxIdx[pGeo->nFce];

               pGeo->pPos = new VtxPos[pGeo->nPos];

 

               fread(pGeo->pFce, pGeo->nFce, sizeof(VtxIdx), fp);

               fread(pGeo->pPos, pGeo->nPos, sizeof(VtxPos), fp);

        }

 

·»´õ¸µÀº User Memory Pointer DrawIndexedPrimitiveUP() ÇÔ¼ö¸¦ ÀÌ¿ëÇϰí ÀÖ½À´Ï´Ù.

 

void CLcmAcm::Render()

¡¦

        for(i=0; i<m_nGeo; ++i)

        {

               LcGeo*  pGeo    = &m_pGeo[i];

¡¦

               m_pDev->SetFVF(VtxPos::FVF);

               m_pDev->DrawIndexedPrimitiveUP(D3DPT_TRIANGLELIST, 0, pGeo->nPos

                              , pGeo->nFce, pGeo->pFce, (D3DFORMAT)VtxIdx::FVF

                              , pGeo->pPos, sizeof(VtxPos)

                       );

        }

 

mxp13_viewer1.zip¸¦ ½ÇÇàÇϰí "_Exec/model/object.acm" À» ºÒ·¯¿À¸é ´ÙÀ½ÀÇ ¿À¸¥ÂÊ ±×¸²°ú °°ÀÌ Ãâ·ÂµË´Ï´Ù.

 

 

<¸Æ½º µ¥ÀÌÅÍ: max_object1.zip. Viewer¿¡¼­ È®ÀÎÇÑ µ¥ÀÌÅÍ: mxp13_viewer1.zip>

 

±×¸²À» ºñ±³ÇØ º¸¸é ¸Æ½º È­¸é°ú ViewerÀÇ È­¸éÀÌ Â÷À̰¡ ÀÖ½À´Ï´Ù. À̰ÍÀº ASE Parsing¿¡¼­µµ À̾߱â ÇßµíÀÌ ´ÙÀ½ ±×¸²°ú °°ÀÌ ¸Æ½º´Â ¿À¸¥¼Õ ÁÂÇ¥°è¸¦ »ç¿ëÇϰí D3D´Â ¿Þ¼Õ ÁÂÇ¥°è¸¦ »ç¿ëÇϱ⠶§¹®ÀÔ´Ï´Ù.

 

<¸Æ½º¿Í D3D ÁÂÇ¥°è>

 

ASE¿¡¼­´Â ÆÄÀÏÀ» Àоî¿Ã ¶§ À§Ä¡¿¡ ´ëÇØ¼­´Â y¿Í z¸¦ ±³È¯Çϰí À妽º´Â b¿Í c¸¦ ±³È¯ÇÑ´Ù°í Çß½À´Ï´Ù. À̰ÍÀ» ÆÄÀÏÀ» ÀÐ¾î ¿Ã ¶§ ó¸®ÇÏÁö ¾Ê°í Ç÷¯±×ÀÎ ³»ºÎ¿¡¼­ À妽º¿Í Á¤Á¡ µ¥ÀÌÅ͸¦ ÀúÀåÇÒ ¶§ ´ÙÀ½°ú °°ÀÌ Ã³¸®ÇÕ´Ï´Ù.

 

INT LcMax::SetupGeometry()

¡¦

// À妽º µ¥ÀÌÅÍ ÀúÀå

for (i=0; i<iNfce; ++i)

{

        pGeo->pFce[i].a = pMesh->faces[i].v[0];

        pGeo->pFce[i].b = pMesh->faces[i].v[2];      // b <--> c ±³È¯

        pGeo->pFce[i].c = pMesh->faces[i].v[1];

}

 

// Á¤Á¡ µ¥ÀÌÅÍ ÀúÀå

for (i=0; i<iNvtx; ++i)

{

        Point3 v = pMesh->verts[i];

        pGeo->pPos[i].x = v.x;

        pGeo->pPos[i].y = v.z; //y <--> z ±³È¯

        pGeo->pPos[i].z = v.y;

}

 

µÎ ¹øÂ°·Î ºä¾î¿¡¼­ È®ÀÎÇÑ ¸ðµ¨Àº ÀüºÎ (0, 0, 0)À» Áß½ÉÀ¸·Î ±×¸®°í ÀÖÀ½À» º¼ ¼ö ÀÖ½À´Ï´Ù. À̰ÍÀº °¢°¢ÀÇ Geometry°¡ Áö¿ªÁÂÇ¥°è·Î ±×¸®±â ¶§¹®ÀÔ´Ï´Ù. ³ëµå¿¡ Àû¿ëµÈ ¿ùµå Çà·ÄÀ» ¾ò±â À§Çؼ­ INode ÀÎÅÍÆäÀ̽º¿¡¼­ GetObjTMAfterWSM() ÇÔ¼ö¸¦ ÀÌ¿ëÇÕ´Ï´Ù. ÀÌ ÇÔ¼ö´Â WSM(World Space Modifier)°¡ Àû¿ëµÈ ÈÄÀÇ Transform Matrix¸¦ ¹ÝȯÇÏ´Â ÇÔ¼öÀÔ´Ï´Ù. ƯÈ÷, ¾Ö´Ï¸ÞÀ̼ÇÀÌ ÀÖ´Â °æ¿ì¿¡ ÀÌ ÇÔ¼ö¸¦ »ç¿ëÇØ¼­ ¿ùµå Çà·ÄÀ» ¾ò¾î ¿É´Ï´Ù. ³ëµå¿¡ Àû¿ëµÇ´Â ¿ùµå Çà·ÄÀº ´ÙÀ½ °ø½Äó·³ ¸¸µé ¼ö ÀÖ½À´Ï´Ù.

 

³ëµåÀÇ ¿ùµå Çà·Ä = ³ëµåÀÇ Áö¿ª Çà·Ä (Local Matrix) * ºÎ¸ð ³ëµåÀÇ ¿ùµå Çà·Ä

 

¾Ö´Ï¸ÞÀ̼ÇÀÌ ¾ø´Â µ¥ÀÌÅͶó¸é ¿ùµå Çà·Ä¸¸ °¡Áö°í Àְųª ¾Æ´Ï¸é Á¤Á¡ÀÇ À§Ä¡¿¡ ¿ùµå Çà·ÄÀ» °öÇÑ °ªÀ» Àû¿ëÇÏ´Â °ÍÀÌ ´õ ³ªÀ» ¼ö ÀÖ½À´Ï´Ù. ÇÏÁö¸¸ ¾Ö´Ï¸ÞÀ̼ÇÀÌ ÀÖ´Ù¸é Å©±â º¯È¯, ȸÀü º¯È¯, À̵¿ º¯È¯¿¡ ´ëÇÑ Çà·ÄÀ» °¡Áö°í Áö¿ª Çà·ÄÀ» ¸¸µé¾î¾ß Çϱ⠶§¹®¿¡ Node¿¡ Áö¿ªÇà·ÄÀ» ÀúÀåÇÏ°í ·»´õ¸µ ÇÒ ¶§¸¶´Ù ¿ùµå Çà·ÄÀ» °è»êÇϵµ·Ï ±¸¼ºÇÏ´Â °ÍÀÌ ¾Ö´Ï¸ÞÀ̼ÇÀ» Àû¿ëÇÒ ¶§ Æí¸®ÇÕ´Ï´Ù. ³ëµåÀÇ Áö¿ª Çà·ÄÀº ÀÌÀüÀÇ ½Ä ¾çº¯¿¡ ºÎ¸ð ³ëµåÀÇ ¿ùµå Çà·ÄÀÇ ¿ªÇà·ÄÀ» °öÇÏ¸é ´ÙÀ½°ú °°ÀÌ ±¸ÇØÁý´Ï´Ù.

 

³ëµåÀÇ Áö¿ª Çà·Ä = ³ëµåÀÇ ¿ùµå Çà·Ä * ºÎ¸ð ³ëµåÀÇ ¿ùµå Çà·ÄÀÇ ¿ªÇà·Ä

 

ºÎ¸ð ³ëµå¿¡ ´ëÇÑ À妽º¸¦ Æ÷ÇÔ ½ÃÄÑ µ¥ÀÌÅͰ¡ ³ª¹« ±¸Á¶(Tree Struct)ÀÇ °èÃþÀû(Hierarchy)À¸·Î ±¸¼º µÇµµ·Ï ´ÙÀ½°ú °°ÀÌ LcGeo ±¸Á¶Ã¼¿¡ ºÎ¸ð ³ëµåÀÇ À妽º¸¦ Ãß°¡ÇÏ°í ¶ÇÇÑ ÀÚ½ÅÀÇ Áö¿ª Çà·Äµµ Ãß°¡ÇÕ´Ï´Ù.

 

struct LcGeo

¡¦

        INT            nPrn;          // Parent Index

        D3DXMATRIX     mtLcl;         // Local Matrix

 

        LcGeo()

¡¦

               nPrn    = -1;                  // ºÎ¸ð°¡ ¾øÀ½

               D3DXMatrixIdentity(&mtLcl);   // Áö¿ªÇà·ÄÀ» ´ÜÀ§ Çà·Ä·Î ¸¸µç´Ù.

        }

¡¦

 

LcMax::SetupGeometry() ÇÔ¼ö¸¦ ¼öÁ¤Çؼ­ ´ÙÀ½°ú °°ÀÌ ºÎ¸ð ³ëµå¿¡ ´ëÇÑ À妽º¸¦ ¼³Á¤ÇÕ´Ï´Ù.

 

// Setup Parent Index

for(n =0; n<m_nGeo; ++n)

{

        LcGeo*  pGeo = &m_pGeo[n];

        INode*  pNode = m_vMaxNode[n];

        INode*  pPrn = pNode->GetParentNode();

 

        // ºÎ¸ðÀÇ ³ëµå¸¦ ã¾Æ À妽º¸¦ ¼³Á¤

        if(pPrn)

        {

               for(i=0; i<m_nGeo; ++i)

               {

                       INode*  pCur = m_vMaxNode[i];

                       if(pCur == pPrn && i != n )

                       {

                              pGeo->nPrn = i;

                              break;

                       }

               }

        }

}

 

¶ÇÇÑ Áö¿ªÇà·Äµµ ´ÙÀ½°ú °°ÀÌ °è»êÇØ¼­ ÀúÀåÇÕ´Ï´Ù.

 

// Setup Local Matrix

for(n =0; n<m_nGeo; ++n)

{

        LcGeo*  pGeo = &m_pGeo[n];

        INode*  pNode = m_vMaxNode[n];

        INode*  pPrnt = pNode->GetParentNode();

 

        Matrix3 tmLocal;

        Matrix3 tmWorld = pNode->GetObjTMAfterWSM(0);

 

        if(!pPrnt)

               tmLocal = tmWorld;

        else

        {

               Matrix3 tmParent= pPrnt->GetObjTMAfterWSM(0);

               tmLocal = tmWorld * Inverse(tmParent);

        }

 

        MaxMatrixToD3D(&pGeo->mtLcl, &tmLocal);

}

 

Inverse() ÇÔ¼ö´Â ¸Æ½º SDK¿¡¼­ Á¦°øÇÏ´Â ¿ªÇà·ÄÀ» ±¸ÇÏ´Â ÇÔ¼öÀÔ´Ï´Ù. MaxMatrixToD3D()´Â ¸Æ½ºÀÇ Çà·ÄÀ» D3D¿¡ ¸Â°Ô ÀÚ¸® ±³È¯À» ÇÏ´Â ÇÔ¼öÀÔ´Ï´Ù. À̰ÍÀº ASE Parsing¿¡¼­µµ ÇßµíÀÌ ¸Æ½ºÀÇ Çà·ÄÀÇ 2,3 ÇàÀ» ±³È¯Çϰí 2, 3¿­ ±³È¯Çϸé D3D¿¡¼­ »ç¿ëÇÏ´Â Çà·Ä·Î ¸¸µé¾î Áý´Ï´Ù.

 

void LcMax::MaxMatrixToD3D(D3DXMATRIX* pDst, Matrix3* pSrc, BOOL bIdentity)

{

        Point3  v3;

        v3 = pSrc->GetRow(0); pDst->_11 = v3.x;      pDst->_12 = v3.z; pDst->_13 = v3.y;

        v3 = pSrc->GetRow(2); pDst->_21 = v3.x;      pDst->_22 = v3.z; pDst->_23 = v3.y;

        v3 = pSrc->GetRow(1); pDst->_31 = v3.x;      pDst->_32 = v3.z; pDst->_33 = v3.y;

        v3 = pSrc->GetRow(3); pDst->_41 = v3.x;      pDst->_42 = v3.z; pDst->_43 = v3.y;

¡¦

}

 

ºÎ¸ð ³ëµåÀÇ À妽º¿Í Áö¿ªÇà·ÄÀ» ÀúÀåÇÒ ¼ö ÀÖµµ·Ï LcMax:: WriteBinary() ÇÔ¼ö¿Í LcMax:: WriteText() ÇÔ¼ö¸¦ ¼öÁ¤ÇÕ´Ï´Ù.

 

void LcMax::WriteBinary()

¡¦

        for(n =0; n<m_nGeo; ++n)

        {

               LcGeo* pGeo = &m_pGeo[n];

¡¦

               fwrite(&pGeo->nPrn,  1, sizeof(INT ), fp);   // Parent Index

               fwrite(&pGeo->mtLcl, 1, sizeof(D3DXMATRIX),fp);      // Local Matrix

        }

 

Àüü ÄÚµå´Â mxp14_transform.zip¸¦ Âü°í Çϱ⠹ٶø´Ï´Ù.

 

Ç÷¯±×Àο¡¼­´Â Áö¿ª Çà·Ä¸¸ °¡Áö°í ÀÖÁö¸¸ Viewer¿¡¼­´Â ¿ùµå Çà·Äµµ °¡Áö°í ÀÖ¾î¾ß ÇÏÀ§ ³ëµå¿¡¼­ °è»êÀÌ µË´Ï´Ù. µû¶ó¼­ ºÎ¸ð À妽º, Áö¿ª Çà·Ä°ú ¿ùµå Çà·ÄÀÌ ÀÖ¾î¾ß ÇÕ´Ï´Ù. ¶ÇÇÑ ¸Å ¹ø ºÎ¸ð ³ëµå¸¦ ã°Ô µÇ¸é ºÒÆíÇϹǷΠÆÄÀÏ¿¡¼­ Àоî¿Ã ¶§ ºÎ¸ð ³ëµå¸¦ ÁöÁ¤ÇÒ ¼ö ÀÖµµ·Ï ºÎ¸ðÀÇ Æ÷ÀÎÅ͸¦ Ãß°¡ÇÕ´Ï´Ù.

 

struct LcGeo

¡¦

        INT                    nPrn;          // Parent Index

LcGeo*                 pPrn;          // Parent Node

        D3DXMATRIX             mtLcl;         // Local Matrix

        D3DXMATRIX             mtWld;         // World Matrix

 

ÆÄÀÏÀ» Àд ÇÔ¼öµµ ¼öÁ¤ÇÕ´Ï´Ù.

 

INT CLcmAcm::LoadMdl(char* sFile)

¡¦

        for(n =0; n<m_nGeo; ++n)

        {

               LcGeo* pGeo = &m_pGeo[n];

¡¦

               fread(&pGeo->nPrn,  1, sizeof(INT ), fp);    // Parent Index

               fread(&pGeo->mtLcl, 1, sizeof(D3DXMATRIX),fp);       // Local Matrix

 

               // ºÎ¸ð ³ëµå ÁöÁ¤

               if(-1 != pGeo->nPrn)

                       pGeo->pPrn = &m_pGeo[pGeo->nPrn];

 

¾Ö´Ï¸ÞÀ̼ÇÀÌ ÀÖ´Ù´Â ÀüÁ¦ÇÏ¿¡ ¸Å ÇÁ·¹ÀÓ ¸¶´Ù Çà·ÄÀ» °»½ÅÇÒ ¼ö ÀÖµµ·Ï ´ÙÀ½°ú °°ÀÌ CLcmAcm::FrameMove() ÇÔ¼ö¸¦ ¼öÁ¤ÇÕ´Ï´Ù. °¢°¢ÀÇ GeometryÀÇ ¿ùµå Çà·ÄÀº ´ÙÀ½°ú °°Àº °ø½ÄÀ» ÀÌ¿ëÇØ¼­ ±¸ÇöÇÕ´Ï´Ù.

 

³ëµåÀÇ ¿ùµå Çà·Ä = ³ëµåÀÇ Áö¿ª Çà·Ä (Local Matrix) * ºÎ¸ð ³ëµåÀÇ ¿ùµå Çà·Ä

 

¸¸¾à ºÎ¸ð ³ëµå°¡ ¾øÀ¸¸é ÀÚ½ÅÀÇ Áö¿ª Çà·ÄÀ» ¿ùµå Çà·Ä·Î ¼³Á¤ÇÕ´Ï´Ù.

 

INT CLcmAcm::FrameMove()

¡¦

        for(i=0; i<m_nGeo; ++i)

        {

               LcGeo*  pCur = &m_pGeo[i];

               LcGeo*  pPrn = pCur->pPrn;

               if(pPrn)

                       pCur->mtWld = pCur->mtLcl * pPrn->mtWld;

               else

                       pCur->mtWld = pCur->mtLcl;

        }

 

Çà·ÄÀÌ Æ÷ÇÔ µÇ¾î ÀÖÀ¸¹Ç·Î °¢°¢ÀÇ Geometry¿¡ ´ëÇØ¼­ ¿ùµå Çà·ÄÀ» ¼³Á¤ÇØ¾ß ÇÕ´Ï´Ù.

 

void CLcmAcm::Render()

¡¦

        for(i=0; i<m_nGeo; ++i)

        {

               LcGeo*  pGeo    = &m_pGeo[i];

¡¦

               m_pDev->SetTransform(D3DTS_WORLD, &pGeo->mtWld);

               m_pDev->DrawIndexedPrimitiveUP(¡¦);

¡¦

        m_pDev->SetTransform(D3DTS_WORLD, &mtI); // ¿ùµå Çà·Ä º¹±Í

 

Àüü ÄÚµå´Â mxp14_viewer2.zip¸¦ ½ÇÇàÇÏ¸é ´ÙÀ½°ú °°Àº È­¸éÀ» º¼ ¼ö ÀÖ½À´Ï´Ù.

 

 

<¿ùµå Çà·ÄÀÌ Àû¿ëµÈ Export µ¥ÀÌÅÍ: max_object2_rigid.zip, mxp14_viewer2.zip>

 

 

5.3 Animation

Á¤Á¡ÀÇ À§Ä¡¿¡ ´ëÇÑ º¯È­¸¦ ½Ã°£ÀÇ ¼ø¼­´ë·Î ¸¸µç °ÍÀÌ ¾Ö´Ï¸ÞÀ̼ÇÀÔ´Ï´Ù. ¾Ö´Ï¸ÞÀ̼ÇÀº Á¤Á¡ÀÇ À§Ä¡ ÀÚü¸¦ º¯È¯ÇÏ´Â ¹æ¹ýÀÌ ÀÖÀ» ¼ö ÀÖ°í, Á¤Á¡¿¡ ¿µÇâÀ» ÁÖ´Â ¿ùµå Çà·Ä¸¸ ½Ã°£¿¡ µû¶ó º¯È¯½ÃŰ°í ³­ ´ÙÀ½¿¡ À̰ÍÀ» ÆÄÀÌÇÁ¶óÀο¡ Àû¿ëÇÏ´Â ¹æ¹ýÀÌ ÀÖÀ» ¼ö ÀÖ½À´Ï´Ù. Á» ´õ ³ªÀº ¹æ¹ýÀº ¹Ì¸® °èÃþ ±¸Á¶¸¦ ¸¸µé¾î ³õ°í ÀÌ °èÃþ ±¸Á¶ÀÇ Çà·ÄÀ» º¯È¯ÇÑ ´ÙÀ½¿¡ Á¤Á¡¿¡ Àû¿ëÇÏ´Â ¹æ¹ýÀÌ ÀÖ½À´Ï´Ù.

3D ¸Æ½º´Â ¿ÀºêÁ§Æ®¿¡ ¾Ö´Ï¸ÞÀ̼ÇÀ» Æí¸®ÇÏ°Ô Àû¿ëÇÒ ¼ö ÀÖ°Ô Bone°ú Biped¸¦ Áö¿øÇÏ¸ç ´ëºÎºÐÀÇ ±×·¡ÇÈ ÀÛ¾÷Àº ÀÌ µÑÀ» ÀÌ¿ëÇØ¼­ ¾Ö´Ï¸ÞÀ̼ÇÀ» ±¸ÇöÇÕ´Ï´Ù.

BoneÀº ±× ¾ð¾î ÀÚü·Î »À´ëÀÌ¸ç ¿©·¯ »À´ë¸¦ °èÃþ ±¸Á¶(Hierarchy) °áÇÕÇÏ°í »ç¿ëÀÚ´Â °áÇÕµÈ BoneÀ» ȸÀü, À̵¿ µîÀ» Àû¿ëÇØ¼­ ¾Ö´Ï¸ÞÀ̼ÇÀ» ±¸ÇöÇÕ´Ï´Ù. ¸Æ½º´Â BoneÀ» Á» ´õ Æí¸®ÇÏ°Ô »ç¿ëÇϰíÀÚ BoneÀ» ƯȭÇÑ Biped¸¦ Áö¿øÇÕ´Ï´Ù.

 

 

<¸Æ½ºÀÇ Bone°ú Biped>

 

BoneÀº »ç¿ëÀÚ°¡ ÀÚÀ¯·Ó°Ô °èÃþ ±¸Á¶¸¦ ¸¸µé ¼ö À־ ¼÷·ÃµÈ ¾Ö´Ï¸ÞÀÌÅÍ(Animator)´Â ÃÖ¼ÒÇÑÀÇ BoneÀ¸·Î ´Ù¾çÇÑ µ¿ÀÛÀ» ¸¸µé¾î ³¾ ¼ö ÀÖ½À´Ï´Ù. Biped´Â ±Ô°ÝÈ­ µÇ¾î ¾Ö´Ï¸ÞÀÌ¼Ç Á¦ÀÛÀÌ Æí¸®Çϰí ÀϰüµÈ ÀÛ¾÷À» À¯µµÇؼ­ °øµ¿ ÀÛ¾÷¿¡ À¯¸®ÇÕ´Ï´Ù. ¾Ö´Ï¸ÞÀ̼ÇÀÌ ¸¹°í º¹ÀâÇÑ Ä³¸¯ÅÍ ¸ðµ¨ÀÇ °æ¿ì Biped¸¦ ±âº»À¸·Î Çϰí ÇÊ¿äÇÏ´Ù¸é BoneÀ» Ãß°¡ ½ÃÄÑ ¾Ö´Ï¸ÞÀ̼ÇÀ» ÀÛ¾÷À» ÇÕ´Ï´Ù. ³ª¹«³ª Ç®°ú °°Àº °üÀýÀÌ °£´ÜÇÑ °æ¿ì¶ó¸é BoneÀ¸·Î ÀÛ¾÷À» ¸¹ÀÌ ÇÕ´Ï´Ù.

 

±×·¡ÇÈ ÀÛ¾÷ÀÚ´Â ¸Æ½º·Î Biped ¶Ç´Â BoneÀ¸·Î ¾Ö´Ï¸ÞÀ̼ÇÀ» ¸¸µì´Ï´Ù. ±×¸®°í ¹Ì¸® ¸¸µé¾î ³õÀº 3D ¸ðµ¨ µ¥ÀÌÅ͸¦ À̵é Biped/Bone¿¡ ¿¬°áÇÏ´Â ¸®±ë(Rigging) ÀÛ¾÷À» ÇÕ´Ï´Ù. ÀÌ ¸®±ë ÀÛ¾÷Àº PHYSIQUE¿Í SKIN µÎ Á¾·ù°¡ ÀÖ½À´Ï´Ù. ÀÛ¾÷ÀÇ ¹æ¹ýÀº Â÷À̰¡ ÀÖÁö¸¸ PHYSIQUE/SKIN ´Â Á¤Á¡¿¡ ¿µÇâÀ» ÁÖ´Â BoneÀ» ¼³Á¤ÇÏ´Â ÀÏÀ̸ç À̰ÍÀº D3DÀÇ ½ºÅ°´× ¾Ö´Ï¸ÞÀÌ¼Ç ±¸ÇöÀ̶ó ÇÒ ¼ö ÀÖ½À´Ï´Ù.

 

¸Æ½º¿¡¼­ÀÇ ÀÛ¾÷ÀÌ Á¤Á¡¿¡ ´ëÇØ¼­ ÇϳªÀÇ Bone¿¡¸¸ ¿µÇâ ¹Þµµ·Ï µÇ¾î ÀÖ´Ù¸é °­Ã¼(Rigid) ¾Ö´Ï¸ÞÀ̼ÇÀ» ¹ÙÅÁÀ¸·Î Ç÷¯±×ÀÎÀ» ±¸¼ºÇØ¾ß Çϰí, ¿©·¯ Bone¿¡ ¿µÇâ ¹ÞÀ¸¸é ½ºÅ°´× ¾Ö´Ï¸ÞÀ̼ÇÀ¸·Î Ç÷¯±×ÀÎÀ» ¸¸µé¾î¾ß ÇÕ´Ï´Ù.

¾Ö´Ï¸ÞÀ̼ǿ¡ ´ëÇÑ Ç÷¯±×ÀÎÀº ±¸ÇöÇϱ⠽¬¿î °­Ã¼ ¾Ö´Ï¸ÞÀ̼ÇÀ» ¸ÕÀú ¸¸µé°í ´ÙÀ½À¸·Î ½ºÅ°´×¿¡ ´ëÇØ¼­ ¸¸µé¾î º¸°Ú½À´Ï´Ù.

 

 

5.3.1 Rigid Body Animation

°­Ã¼ ¾Ö´Ï¸ÞÀ̼Ç(Rigid Body Animation)¿¡ ´ëÇÑ Ç÷¯±×ÀÎ Á¦ÀÛÀº ÀǿܷΠ°£´ÜÇÕ´Ï´Ù. Ç÷¯±×ÀÎ Á¦ÀÛ ¼ø¼­´Â ¸ÕÀú ½Ã°£ Á¤º¸¸¦ ¾ò½À´Ï´Ù. ´ÙÀ½À¸·Î BoneÀÇ °èÃþ ±¸Á¶¿Í ¸Þ½¬¸¦ ÀúÀåÇÏ°í ¸¶Áö¸·¿¡ ½Ã°£¿¡ ´ëÇÑ ¿ùµå Çà·Ä ¶Ç´Â Áö¿ª Çà·ÄÀ» ÃßÃâÇÏ¸é µË´Ï´Ù.

 

¸ÕÀú ½Ã°£ÀÇ Á¤º¸¸¦ ÀúÀåÇϱâ À§ÇØ ´ÙÀ½°ú °°Àº ±¸Á¶Ã¼¸¦ ¸¸µì´Ï´Ù.

 

struct LcHeader

{

        INT            nFrmB;         // Begin Frame

        INT            nFrmE;         // End Frame

        INT            nFrmP;         // Frame Rate(FPS)

        INT            nFrmT;         // Tick Frame

        INT            nGeo;          // Number of Geometry

};

 

ÀÌÀü¿¡´Â Geometry °³¼ö¸¦ ¸â¹ö·Î °¡Á®°¬´Âµ¥ ÇÁ·Î±×·¥ÀÇ Æí¸®¼ºÀ» À§ÇØ LcHeader¿¡ Æ÷ÇÔ½ÃÄ×½À´Ï´Ù.

 

½Ã°£ Á¤º¸´Â ´ÙÀ½°ú °°ÀÌ ±¸Çö ÇÕ´Ï´Ù. ÀÌ ¹æ¹ýÀº ase Ç÷¯±×ÀÎ ¿¹Á¦¿Íµµ ºñ½ÁÇÕ´Ï´Ù.

 

int            iTick = GetTicksPerFrame();

Interval range = m_pI->GetAnimRange();

 

m_Header.nFrmB = range.Start() / iTick;

m_Header.nFrmE = range.End() / iTick;

m_Header.nFrmP = GetFrameRate();

m_Header.nFrmT = iTick;

 

ÇÁ·Î±×·¥À» Æí¸®ÇÏ°Ô ÀÛ¼ºÇϱâ À§ÇØ LcGeo¸¦ ´ÙÀ½°ú °°ÀÌ ¼öÁ¤ÇÕ´Ï´Ù.

 

struct LcGeo

{

        char           sName[32];     // Node Name

        INT            nType;         // 1:Geometry, 2: Bone, 0: Etc

        INode*         pNode;         // Node

        INT            nPrn;          // Parent Index

        D3DXMATRIX     mtLcl;         // Local Matrix

        INT            nFce;          // Number of Face

        INT            nPos;          // Number of Position

        VtxIdx*        pFce;          // Face List

        VtxPos*        pPos;          // Position List

        INT            nAni;          // Number of Animation

        D3DXMATRIX*    pAni;          // Animation Matrix

};

 

ÀÌ ±¸Á¶Ã¼¸¦ ÀÌ¿ëÇØ¼­ ³ëµå¸¦ ¸ðÀ¸°í °èÃþ ±¸Á¶ÀÇ Node¸¦ STLÀ» ÀÌ¿ëÇØ¼­ ¹è¿­·Î ±¸¼ºÇÕ´Ï´Ù. ÀÌ ºÎºÐÀº ÀÌÀü Àå¿¡¼­ ¼³¸íÇßÀ¸¹Ç·Î »ý·«ÇϰڽÀ´Ï´Ù.

¸Æ½º´Â »ç¿ëÀÚ°¡ ¹Ù²ÙÁö ¾Ê´Â ÇÑ Default·Î Bone¿¡ ´ëÇØ¼­ "Bone"À̶ó´Â Ű¿öµå°¡ Biped´Â "Bip" Ű¿öµå°¡ ¿ÀºêÁ§Æ®ÀÇ À̸§¿¡ Àû¿ëµÇ¾î ´ÙÀ½°ú °°ÀÌ BoneÀÎÁö ÆÇ´ÜÇÏ´Â ÇÔ¼ö ¾È¿¡ ±¸Çö ÇÕ´Ï´Ù.

 

void LcMax::SetupIsBone(LcGeo* pGeo)

¡¦

        if( 0 == _strnicmp(pNode->GetName(), "Bone", 4) ||

               0 == _strnicmp(pNode->GetName(), "Bip", 3))

               pGeo->nType = LCX_BONE;

¡¦

 

´ÙÀ½À¸·Î Áö¿ª Çà·Ä, ¸Þ½¬ Á¤º¸¸¦ ÃßÃâÇÏ°í ¸¶Áö¸· ´Ü°è¿¡¼­ ´ÙÀ½°ú °°ÀÌ ¾Ö´Ï¸ÞÀ̼ǿ¡ ´ëÇÑ Çà·ÄÀ» ÃßÃâÇÕ´Ï´Ù.

 

typedef D3DXMATRIX     MATA;

void LcMax::SetupAnimation(LcGeo* pGeo)

¡¦

        nAni = m_Header.nFrmE - m_Header.nFrmB +1;

 

        INode*  pNode = pGeo->pNode;

        INode*  pPrnt = pNode->GetParentNode();

 

        pGeo->nAni     = nAni;

        pGeo->pAni     = new MATA[nAni];

 

        dTime = dTimeB;

        i       = 0;

        for(; dTime<=dTimeE ; dTime += dTick, ++i)

        {

               MATA* pDest = &pGeo->pAni[i];

               Matrix3 tmLocal;

               Matrix3 tmWorld = pNode->GetObjTMAfterWSM(dTime);

 

               if(!pPrnt)

                       tmLocal = tmWorld;

               else

               {

                       Matrix3 tmParent= pPrnt->GetObjTMAfterWSM(dTime);

                       tmLocal = tmWorld * Inverse(tmParent);

               }

 

               MaxMatrixToD3D(pDest, &tmLocal);

        }

 

¾Ö´Ï¸ÞÀ̼ǿ¡ ´ëÇÑ Áö¿ª Çà·ÄÀº ÀÌÀüÀÇ transform ¿¹Á¦Ã³·³ ´ÙÀ½ °ø½ÄÀ» ÀÌ¿ëÇÕ´Ï´Ù.

¾Ö´Ï¸ÞÀÌ¼Ç Áö¿ª Çà·Ä = ³ëµåÀÇ ¾Ö´Ï¸ÞÀÌ¼Ç ¿ùµå Çà·Ä * ºÎ¸ð ¾Ö´Ï¸ÞÀÌ¼Ç ¿ùµå Çà·ÄÀÇ ¿ªÇà·Ä

 

GetObjTMAfterWSM() ÇÔ¼ö´Â ÁÖ¾îÁø ½Ã°£¿¡¼­ Modifier¿¡ ÀÇÇÑ ¿ùµå Çà·ÄÀ» ¹Ýȯ ÇϹǷΠÀ̸¦ ÀÌ¿ëÇØ¼­ °¢ ³ëµåÀÇ ¿ùµå Çà·ÄÀ» ±¸ÇÑ ÈÄ¿¡ °ø½Ä¿¡ Àû¿ëÇØ¼­ ½Ã°£¿¡ ´ëÇÑ Áö¿ª Çà·ÄÀ» ¸¸µé¾î ³À´Ï´Ù.

ÆÄÀÏ¿¡ ÀúÀåÇÒ ¶§´Â ¾Ö´Ï¸ÞÀÌ¼Ç Á¤º¸´Â ¸Þ½¬ Á¤º¸¸¦ ÀúÀåÇÑ ´ÙÀ½¿¡ ÀúÀåÇÕ´Ï´Ù.

 

void LcMax::WriteBinary()

        // Write Geometry

¡¦

        // Write Animation

        for(n =0; n<m_Header.nGeo; ++n)

        {

               LcGeo* pGeo = &m_pGeo[n];

               if(1>pGeo->nAni)

                       continue;

 

               fwrite(pGeo->pAni, pGeo->nAni, sizeof(MATA), fp);    // Animation Matrix

        }

 

Àüü ÄÚµå´Â mxp21_ani_rigid1.zipÀ» Âü°í Çϱ⠹ٶø´Ï´Ù.

 

ÀÌ·¸°Ô ¸¸µç µ¥ÀÌÅ͸¦ °ÔÀÓ¿¡ Àû¿ëÇÏ·Á¸é ¸ÕÀú ¾Ö´Ï¸ÞÀÌ¼Ç Çà·ÄÀÇ À妽º¸¦ ±¸ÇØ¾ß ÇÕ´Ï´Ù. ÀÌ À妽º´Â ½Ã°£À» FrameÀ¸·Î ³ª´©°í ´Ù½Ã Àüü ÇÁ·¹ÀÓÀ¸·Î Modular ¿¬»êÀÚ(%)¸¦ ÀÌ¿ëÇϸé ÃÖ´ë ÇÁ·¹ÀÓÀ» ³ÑÁö ¾Ê°í ¹Ýº¹µÈ ¾Ö´Ï¸ÞÀ̼ÇÀ» ±¸ÇöÇÒ ¼ö ÀÖ½À´Ï´Ù.

 

m_nAni = INT( dTime/m_Header.nFrmP);

m_nAni %= m_Header.nFrmE;

 

Ç÷¯±×ÀÎÀ¸·Î ÃßÃâÇÑ ¾Ö´Ï¸ÞÀÌ¼Ç Çà·ÄÀº ¾Ö´Ï¸ÞÀÌ¼Ç Áö¿ª Çà·ÄÀ̹ǷΠ´ÙÀ½ °ø½Ä°ú °°ÀÌ ¾Ö´Ï¸ÞÀ̼ǿ¡ ´ëÇÑ ¿ùµå Çà·ÄÀ» ±¸ÇÕ´Ï´Ù.

 

³ëµåÀÇ ¾Ö´Ï¸ÞÀÌ¼Ç ¿ùµå Çà·Ä = ³ëµåÀÇ ¾Ö´Ï¸ÞÀÌ¼Ç Áö¿ª Çà·Ä * ºÎ¸ðÀÇ ¾Ö´Ï¸ÞÀÌ¼Ç ¿ùµå Çà·Ä

 

À̰ÍÀº ÀÌÀüÀÇ transform ¿¹Á¦¿Í °ÅÀÇ °°À¸¸ç mxp21_viewer_rigid1.zipÀº ´ÙÀ½°ú °°ÀÌ ÀÌ °ø½ÄÀ» ±¸ÇöÇϰí ÀÖ½À´Ï´Ù.

 

INT CLcmAcm::FrameMove()

¡¦

        m_TimeC = GetTickCount();

        DWORD dTime = m_TimeC - m_TimeB;

 

        m_nAni = INT( dTime/m_Header.nFrmP);

        m_nAni %= m_Header.nFrmE;

 

        for(i=0; i<m_Header.nGeo; ++i)

        {

               LcGeo*  pCur = &m_pGeo[i];

               LcGeo*  pPrn = pCur->pPrn;

               D3DXMatrixIdentity(&pCur->mtWld);

 

               if(pPrn)

               {

                       if(pCur->pAni)

                              pCur->mtWld = pCur->pAni[m_nAni]* pPrn->mtWld;

                       else

                              pCur->mtWld = pCur->mtLcl * pPrn->mtWld;

               }

               else

                       pCur->mtWld = m_mtWld;

        }

 

mxp21_viewer_rigid1.zip¸¦ ½ÇÇàÇÏ¸é ´ÙÀ½°ú °°Àº È­¸éÀ» ¾òÀ» ¼ö ÀÖ½À´Ï´Ù.

 

 

<°­Ã¼ ¾Ö´Ï¸ÞÀ̼Ç: mxp21_viewer_rigid1.zip>

 

 

5.3.2 Skinning Animation Ç÷¯±×ÀÎ

½ºÅ°´× ¾Ö´Ï¸ÞÀ̼ǿ¡ ´ëÇÑ Ç÷¯±×ÀÎ Á¦ÀÛÀº ±ÛÀ» ¾²°í ÀÖ´Â Àúµµ ¸¹Àº ÁÂÀýÀ» °Þ¾ú´ø ºÎºÐÀÔ´Ï´Ù. ´ÙÇàÈ÷µµ Game Programming Gems 2 ±Ç 1.21 Àå "½ºÅ² ÀͽºÆ÷ÅÍ" ºÎºÐ¿¡¼­ Physique¿¡¼­ Á¤Á¡¿¡ ´ëÇÑ BoneÀÇ ºñÁß(Weight)°ú À妽º¸¦ ±¸ÇÏ´Â ¹æ¹ýÀÌ ¼Ò°³µÇ¾î ÀÖ°í, À̰ÍÀ» ¿¬±¸Çؼ­ Physique¿Í SKIN µÎ ºÎºÐ ¸ðµÎ¿¡ ´ëÇÑ Ç÷¯±×ÀÎÀ» ÀÛ¼ºÇÒ ¼ö ÀÖ¾ú½À´Ï´Ù.

 

¸¸¾à PHYSIQUE/SKIN ÀÌ Àû¿ëµÈ Ç÷¯±×ÀÎÀ» Á¦ÀÛÇÑ´Ù¸é Á¦ÀÏ ¸ÕÀú Á¤Á¡ÀÇ À§Ä¡¸¦ ÃßÃâÇÏ´Â ºÎºÐÀ» ´ÙÀ½°ú °°ÀÌ ¼öÁ¤ÇØ¾ß ÇÕ´Ï´Ù.

 

Matrix3 tmWSM = pNode->GetObjTMAfterWSM(0); // ¶Ç´Â tmWSM = pNode->GetObjectTM(0);

¡¦

for (n=0; n<iNvtx; ++n)

{

        Point3 v = tmWSM * pMesh->verts[n];   // º¯È¯µÈ Á¤Á¡À» »ç¿ë

        pGeo->pPos[n].x = v.x;

        pGeo->pPos[n].y = v.z;

        pGeo->pPos[n].z = v.y;

}

 

ÀÌÀüÀÇ °­Ã¼ ¾Ö´Ï¸ÞÀ̼ǿ¡¼­´Â º¯È¯ÇÏÁö ¾ÊÀº Á¤Á¡À» »ç¿ëÇßÀ¸³ª ½ºÅ°´×ÀÌ Àû¿ëµÇ´Â Á¤Á¡Àº ½ÃÀÛ ½Ã°£ (Zero Time)ÀÇ Çà·ÄÀ» Àû¿ëÇØ¼­ »ç¿ëÇÕ´Ï´Ù. À̰ÍÀº ¸®±ë ÀÛ¾÷¿¡ ÀÇÇØ º¯È¯µÈ ¸ðµ¨¸µ µ¥ÀÌÅÍÀÇ Á¤Á¡À» »ç¿ëÇÏ´Â °ÍÀ» ÀǹÌÇÕ´Ï´Ù.

PHYSIQUE/SKIN ¿¡¼­ BoneÀÇ À妽º¿Í ºñÁßÀ» ±¸ÇÏ´Â ¹æ¹ýÀ» °£´ÜÈ÷ ¼³¸íÇϸé ù ¹øÂ°·Î PHYSIQUE/SKIN¿¡ ´ëÇÑ ¼öÁ¤ÀÚ(Modifier) ã°í, ±× ´ÙÀ½À¸·Î ¼öÁ¤ÀÚ¿¡¼­ PHYSIQUE/SKIN °´Ã¼¸¦ ¾ò´Â °ÍÀÔ´Ï´Ù. ¼¼ ¹øÂ°·Î PHYSIQUE/SKIN °´Ã¼¿¡¼­ ¹®¸Æ(Context)¸¦ ¾ò°í ÀÌ ¹®¸Æ¿¡¼­ ¿µÇâ ¹Þ´Â Á¤Á¡ÀÇ ¼ö¸¦ ±¸Çϰí ÀÌ ¼ö¸¸Å­ Loop¸¦ µ¹¸é¼­ ÀÌ ¹®¸Æ¿¡ ¿¬°áµÈ Á¤Á¡À» ¾ò°í ÀÌ Á¤Á¡¿¡ ¿¬°áµÈ ³ëµå¿Í ºñÁßÀ» ±¸ÇÕ´Ï´Ù.

 

¼öÁ¤ÀÚÀÇ ¿ªÇÒÀº °´Ã¼ÀÇ º¯È¯ÀÌ¸ç ¿©·¯ ¼öÁ¤ÀÚµéÀÌ °´Ã¼¿¡ Àû¿ëÀÌ µÇ¾î Àå¸é¿¡ ´ëÇØ¼­ °´Ã¼ÀÇ ÃÖÁ¾ÀûÀÎ °á°ú¹°(¿ÜÇü)À» ¸¸µé¾î³À´Ï´Ù. ÀÌ·¯ÇÑ ÀÌÀ¯·Î ¼öÁ¤Àڵ鿡 ÀÇÇÑ °´Ã¼ÀÇ º¯È¯ °úÁ¤À» °´Ã¼ÀÇ ÆÄÀÌÇÁ¶óÀÎÀ̶ó ºÎ¸£±âµµ ÇÕ´Ï´Ù. °¢°¢ÀÇ ³ëµå´Â ¼öÁ¤Àڵ鿡 ÀÇÇØ º¯È¯µÈ ÃÖÁ¾ °´Ã¼(Derived Object)°¡ ¿¬°áµÇ¾î ÀÖ°í ÀÌ ÃÖÁ¾ °´Ã¼´Â ¸Æ½ºÀÇ ¼öÁ¤ÀÚ ½ºÅà ½Ã½ºÅÛÀÌ Àû¿ëµÈ °á°ú ÀÔ´Ï´Ù.

¿ì¸®´Â ÀÌ ¼öÁ¤ÀÚ ½ºÅÃÀ» Ž»öÇϸ鼭 ´ÙÀ½°ú °°ÀÌ ¼öÁ¤ÀÚ(Modifier)¸¦ ãÀ¸¸é µË´Ï´Ù.

 

void* LcMax::FindModifier(INode *pNode, Class_ID nType)

{

        // ³ëµå¿¡ ¿¬°áµÈ ¿ÀºêÁ§Æ®¸¦ ±¸ÇÑ´Ù.

        Object* ObjectPtr = pNode->GetObjectRef();

 

        if(!ObjectPtr)

               return NULL;

 

        // Derived ¿ÀºêÁ§Æ®¶ó¸é ÀÌ ¿ÀºêÁ§Æ®¿¡¼­ ¼öÁ¤ÀÚ¸¦ ã´Â´Ù.

        while(ObjectPtr && ObjectPtr->SuperClassID() == GEN_DERIVOB_CLASS_ID)

        {

               IDerivedObject *pDerivedObj = (IDerivedObject *)ObjectPtr;

 

               // ¼öÁ¤ÀÚ ½ºÅÃÀ» ÀüºÎ Ž»öÇÑ´Ù.

               int ModStackIndex = 0;

               while(ModStackIndex < pDerivedObj->NumModifiers())

               {

                       // ½ºÅà À妽º¿¡ ´ëÇÑ ¼öÁ¤ÀÚ¸¦ ¾ò´Â´Ù.

                       Modifier* ModifierPtr = pDerivedObj->GetModifier(ModStackIndex);

 

                       //ÀÌ ¼öÁ¤ÀÚÀÇ ¾ÆÀ̵𰡠PHYSIQUE ¶Ç´Â SKINÀÎÁö ºñ±³ÇÑ´Ù.

                       if(nType == ModifierPtr->ClassID())

                              return ModifierPtr;

 

                       // ¼öÁ¤ÀÚ°¡ PHYSIQUE ¶Ç´Â SKINÀÌ ¾Æ´Ï¸é À妽º¸¦ ¿Ã¸°´Ù.

                       ModStackIndex++;

               }

 

               // Derived ¿ÀºêÁ§Æ®¿¡ ¿¬°áµÈ ´Ù¸¥ ¿ÀºêÁ§Æ®¸¦ ¾ò´Â´Ù.

               ObjectPtr = pDerivedObj->GetObjRef();

        }

 

        // ¹ß°ß ¸øÇÔ.

        return NULL;

}

 

Derived °´Ã¼¸¦ ÅëÇØ¼­ ±¸ÇÑ ¼öÁ¤ÀÚ(Modifier) ¾ÈÀÇ ¹®¸Æ(Context)¸¦ ±¸Çϸé BoneÀÇ ¿µÇâµµ¸¦ ±¸ÇÒ ¼ö ÀÖ½À´Ï´Ù. ¹®¸ÆÀ» ±¸ÇÏ´Â ¹æ¹ýÀº ¼öÁ¤ÀÚ¿¡¼­ PHYSIQUE/SKIN °´Ã¼¸¦ ¾ò°í ÀÌ °´Ã¼¿¡¼­ ¹®¸ÆÀ» ´ÙÀ½°ú °°ÀÌ ¾ò½À´Ï´Ù.

 

IPhysiqueExport(¶Ç´Â ISkin)*                  pExport = NULL;

IPhyContextExport(¶Ç´Â ISkinContextData)*    pContext = NULL;

 

pExport = pMod->GetInterface(I_PHYINTERFACE/I_SKIN); // PHYSIQUE/SKIN °´Ã¼

pContext = pExport->GetContextInterface(pNode);              // Context

 

¹®¸ÆÀ» ¾ò°í ³ª¼­ PHYSIQUE¿¡¸¸ ¹®¸Æ¿¡ ´ëÇØ¼­ Rigidº¯°æ°ú ºí·»µù Ȱ¼ºÈ­¸¦ Áö½ÃÇÕ´Ï´Ù.

 

pContext->ConvertToRigid(TRUE);              // Context¿¡ ´ëÇØ¼­ Rigid·Î º¯°æ

pContext->AllowBlending(TRUE);        // Á¤Á¡ Blending Ȱ¼ºÈ­

 

´ÙÀ½À¸·Î Bone¿¡ ¿µÇâ ¹Þ´Â Á¤Á¡ÀÇ ¼ö¸¦ ±¸ÇÕ´Ï´Ù.

 

int nVtx = pContext->GetNumberVertices();    // Bone¿¡ ¿µÇâ ¹Þ´Â Á¤Á¡ÀÇ °³¼ö

 

ÀÌ Á¤Á¡ÀÇ ¼ö´Â ½ÇÁ¦·Î GeometryÀÇ Á¤Á¡ °³¼ö¿Í ÀÏÄ¡ÇÕ´Ï´Ù. ÀÌ °³¼ö¸¸Å­ ´ÙÀ½°ú °°ÀÌ for ¹® ¾È¿¡¼­ ¹®¸Æ¿¡¼­ BoneÀÇ À妽º¿Í ºñÁßÀ» ±¸ÇÕ´Ï´Ù. ÁÖÀÇÇÒ °ÍÀº RIGID_TYPE ÀÌ¸é ºñÁßÀ» 1·Î ÇÏ¸ç ³Ê¹« ÀÛÀº °ªÀÌ¸é ¹«½Ã¸¦ ÇÕ´Ï´Ù.

 

// PHYSIQUE

for(int j=0; j<nVtx; ++j)

{

        IPhyVertexExport* pPhyVtxExpt = pContext->GetVertexInterface(j);

        IPhyBlendedRigidVertex* pPhyBlend = pPhyVtxExpt;

¡¦

        if(RIGID_TYPE == pPhyVtxExpt->GetVertexType())

        {

               INodepBone   = ((IPhyRigidVertex*)pPhyVtxExpt)->GetNode();

               INT     nBone   = FindBoneId(pBone); //º» À妽º

               FLOAT   fWgt    = 1.f;         //RIGID_TYPE´Â Weight=1

               pGeo->pBlnd[j].vB.insert(std::pair<INT, FLOAT>(nBone, fWgt));

               continue;

        }

 

        int numBones = pPhyBlend->GetNumberNodes();

        for(int k = 0; k< numBones; ++k)

        {

               // k¹øÂ°ÀÇ º»À» ã´Â´Ù.

               INodepBone   = pPhyBlend->GetNode(k);

               INT     nBone   = FindBoneId(pBone);

               FLOAT   fWgt    = pPhyBlend->GetWeight(k);

               // °ªÀÌ ÀÛÀ¸¸é ¹«½Ã

               if(fWgt<0.00005f)

                       continue;

               pGeo->pBlnd[j].vB.insert(std::pair<INT, FLOAT>(nBone, fWgt));

        }

}

¡¦

// SKIN

for(int j=0; j<nVtx;  ++j)

{

        int numBones = pContext->GetNumAssignedBones(j);

        for(int k=0; k<numBones; ++k)

        {

               int assignedBone = pContext->GetAssignedBone(j, k);

               if(assignedBone < 0)

                       continue;

 

               INodepBone   = pExport->GetBone(assignedBone);

               INT     nBone   = FindBoneId(pBone);

               FLOAT   fWgt    = pContext->GetBoneWeight(j, k);

               // °ªÀÌ ÀÛÀ¸¸é ¹«½Ã

               if(fWgt<0.00005f)

                       continue;

               pGeo->pBlnd[j].vB.insert(std::pair<INT, FLOAT>(nBone, fWgt));

        }

}

 

PHYSIQUE/SKIN ¿¡ ´ëÇÑ ¾Ö´Ï¸ÞÀÌ¼Ç Çà·ÄÀ» ±¸ÇÏ´Â ¹æ¹ýÀº °­Ã¼ ¾Ö´Ï¸ÞÀ̼ǰú Â÷À̰¡ ÀÖ½À´Ï´Ù. D3D¸¦ ±âÁØÀ¸·Î ¾Ö´Ï¸ÞÀÌ¼Ç Çà·ÄÀº ´ÙÀ½°ú °°ÀÌ °è»ê µË´Ï´Ù.

 

¾Ö´Ï¸ÞÀÌ¼Ç ¿ùµå Çà·Ä = Pivot Çà·ÄÀÇ ¿ªÇà·Ä * ½Ã°£¿¡ ´ëÇÑ ³ëµåÀÇ ¿ùµå Çà·Ä

 

À̰ÍÀ» ±¸ÇöÇÏ·Á¸é ¸ÕÀú ³ëµå¿¡ ´ëÇÑ Pivot Çà·ÄÀÇ ¿ªÇà·ÄÀ» ±¸ÇÕ´Ï´Ù.

 

MATA    mtPivot;

Matrix3 tmPivot = pNode->GetNodeTM(0);

tmPivot.Invert();

MaxMatrixToD3D(&mtPivot, &tmPivot);

 

½Ã°£¿¡ ´ëÇØ¼­ ³ëµåÀÇ GetObjTMAfterWSM() ÇÔ¼ö·Î ½Ã°£¿¡ ´ëÇÑ ³ëµåÀÇ ¿ùµå Çà·ÄÀ» ±¸ÇÏ°í ¾ÕÀÇ °ø½ÄÀ» ´ÙÀ½°ú °°ÀÌ Àû¿ëÇÕ´Ï´Ù.

 

for(n=0, dTime = dTimeB; dTime<=dTimeE ; dTime += dTick, ++n)

{

        MATA* pDest = &pGeo->pAni[n];

 

        Matrix3 tmWorld = pNode->GetObjTMAfterWSM(dTime);

        tmWorld.NoScale();

 

        MATA    mtAni;

        MaxMatrixToD3D(&mtAni, &tmWorld);

        mtAni  = mtPivot * mtAni;

        *pDest = mtAni;

}

 

ÀÌ ¶§ Å©±â º¯È¯ÀÌ Àû¿ëµÇÁö ¾Êµµ·Ï "tmWorld.NoScale();" ±¸¹®À» ²À ³Ö´Â °ÍÀÌ °¡Àå Áß¿äÇÕ´Ï´Ù. ¶ÇÇÑ ¾Ö´Ï¸ÞÀ̼ÇÀº °èÃþ ±¸Á¶¸¦ Àû¿ëÇÏÁö ¾Ê°í °ð ¹Ù·Î ¿ùµå º¯È¯À» ÀÌ¿ëÇϰí ÀÖ´Â °Í ¶ÇÇÑ ÁÖÀÇÇØ¾ß ÇÕ´Ï´Ù.

°èÃþ ±¸Á¶°¡ ¾Æ´Ñ ¿ùµå º¯È¯À» ÀÌ¿ëÇÏ°Ô µÇ¸é Ç÷¯±×Àο¡¼­ ¸¸µç µ¥ÀÌÅ͸¦ °ÔÀÓ¿¡¼­ ¾Ö´Ï¸ÞÀ̼ÇÀ» ±¸ÇöÇÒ ¶§ ´ÙÀ½°ú °°ÀÌ Àû¿ëÇØ¾ß ÇÕ´Ï´Ù.

 

DWORD   m_TimeB;       // Start Time

DWORD   m_TimeC;       // Current Time

INT     m_nAni;        // Animation Index

¡¦

INT CLcmAcm::FrameMove()

¡¦

m_TimeC = GetTickCount();

 

DWORD dTime = m_TimeC - m_TimeB;

 

m_nAni = INT( dTime/m_Header.nFrmP);

m_nAni %= m_Header.nFrmE;

 

// World Çà·Ä ¾÷µ¥ÀÌÆ®

for(n=0; n<m_Header.nGeo; ++n)

{

        LcGeo*  pGeo    = &m_pGeo[n];

 

        MATA    mtAni;

        D3DXMatrixIdentity(&mtAni);

 

        if(pGeo->pAni)

               mtAni = pGeo->pAni[m_nAni];

 

// World Çà·Ä ¼³Á¤

        ¡¦

}

 

À̰ÍÀ¸·Î PHYSIQUE/SKIN¿¡ ´ëÇÑ Á¤Á¡ÀÇ À§Ä¡, Bone À妽º¿Í ºñÁß, ¾Ö´Ï¸ÞÀ̼ǿ¡ ´ëÇÑ Ç÷¯±×Àο¡¼­ Áß¿ëÇÑ ºÎºÐÀ» »ìÆìº¸¾Ò½À´Ï´Ù. Àüü ÄÚµå´Â mxp23_skinning.zip¸¦ Âü°íÇϱ⠹ٶø´Ï´Ù. ´ÙÀ½Àº ÀÌ Ç÷¯±×ÀÎÀ¸·Î ÃßÃâÇÑ µ¥ÀÌÅ͸¦ D3D ¿¡¼­ ½ºÅ°´× ¾Ö´Ï¸ÞÀ̼ÇÀ¸·Î ±¸ÇöÇØº¼ Â÷·ÊÀÔ´Ï´Ù.

 

 

5.3.3 Skinning Animation

½ºÅ°´× ¾Ö´Ï¸ÞÀÌ¼Ç ±¸ÇöÀº ÀÌ¹Ì °íÁ¤ ±â´É ÆÄÀÌÇÁ¶óÀο¡¼­ DirectXÀÇ X-FileÀ» °¡Áö°í ÇØ º»ÀûÀÌ ÀÖ½À´Ï´Ù. ÇϳªÀÇ Á¤Á¡ ¿¡ ¿µÇâÀ» ÁÖ´Â Çà·ÄÀ» , ºñÁßÀ» ¶ó ÇÏ¸é º¯È¯ ÈÄÀÇ Á¤Á¡ À§Ä¡ ´Â ´ÙÀ½°ú °°ÀÌ °è»êÀÌ µÇ°í,

 

 

°ýÈ£ ¾ÈÀÇ Á¡ Àº ¥Ò¹ÛÀ¸·Î »©³»¿Ã ¼ö ÀÖ°í, ¼ö½ÄÀ» Á¤¸®Çϸé

 

 

 

ÀÌ µÇ¸ç  ¸¦ °¢°¢ ¼öÇàÇϰí À̵éÀ» ´õÇÑ ÃÖÁ¾ Çà·ÄÀ» À¸·Î °è»êÇÑ´Ù°í Çß½À´Ï´Ù. ÀÌ ³»¿ëÀ» CPU¿¡ ÀÇÇÑ ¼ÒÇÁÆ®¿þ¾î(Software) ¹æ¹ý, GPU¿¡ ÀÇÇÑ Çϵå¿þ¾î Áö¿ø ¹æ¹ý, ±×¸®°í ½¦ÀÌ´õ¸¦ ÀÌ¿ëÇÑ ¹æ¹ý, 3°¡Áö·Î ³ª´©¾î¼­ Àû¿ëÇØ º¾½Ã´Ù.

 

¸ÕÀú ¼ÒÇÁÆ®¿þ¾îÀûÀÎ ¹æ¹ýÀÔ´Ï´Ù. ¿ì¸®ÀÇ ¸ñÇ¥´Â À» ±¸ÇÏ´Â °ÍÀÔ´Ï´Ù. ´ÙÀ½ÀÇ Äڵ忡¼­ Àº ÀÌÁß for¹® ¾ÈÀÇ mtW º¯¼ö ÀÔ´Ï´Ù.  (mtW)´Â ´©ÀûµÇ¾î¾ß ÇϹǷΠº¯¼ö¸¦ ¼±¾ðÇÏ°í ³ª¼­ memset() ÇÔ¼ö·Î ÀüºÎ 0À¸·Î ÃʱâÈ­ ÇÕ´Ï´Ù.

´ÙÀ½À¸·Î  ¸¦ Àû¿ëÇÏ´Â °ÍÀε¥ À̰Ϳ¡ ÇØ´çÇÏ´Â ºÎºÐÀº ÄÚµåÀÇ "mtT * fW" ÀÔ´Ï´Ù.

ÀÌ·¸°Ô À» ±¸ÇßÀ¸¸é ¸¶Áö¸·À¸·Î  ¸¦ Àû¿ëÇØ¾ß ÇÕ´Ï´Ù. À̰ÍÀº ¿øº» Á¤Á¡Àº ±×´ë·Î µÎ°í ¿øº»À» º¹»çÇÑ Á¤Á¡ÀÇ À§Ä¡¸¦ º¯°æÇÏ´Â D3DXVec3TransformCoord(¡¦); ºÎºÐÀÔ´Ï´Ù.

 

INT CLcmAcm::FrameMove()

¡¦

LcGeo*  pGeo    = &m_pGeo[n];

¡¦

for(j=0; j<pGeo->nBlnd; ++j)

{

        LcmBone*       pBlnd = &pGeo->pBlnd[j];

        INT            iBone = pBlnd->vB.size();

 

        MATA    mtW;

        memset(&mtW, 0, sizeof(mtW));

 

        for(k=0; k<iBone; ++k)

        {

               FLOAT   fW =pBlnd->vB[k].fW;

               INT     nM =pBlnd->vB[k].nB;

 

               MATA    mtT = m_pGeo[nM].mtWld;

               mtW += (mtT * fW);

        }

 

        D3DXVec3TransformCoord(&pGeo->pVxD[j].p, &pGeo->pVtx[j].p, &mtW);

}

 

·»´õ¸µ¿¡¼­´Â ¿ÀºêÁ§Æ® ÀÚüÀÇ ¿ùµå Çà·Äµµ ´ÙÀ½°ú °°ÀÌ Àû¿ëµÇ¾î¾ß ÇÕ´Ï´Ù.

 

void CLcmAcm::Render()

¡¦

VtxPos* pVtx    = NULL;

¡¦

pVtx= pGeo->pVxD;

m_pDev->SetTransform(D3DTS_WORLD, &m_mtWld);

¡¦

m_pDev->DrawIndexedPrimitiveUP(¡¦, pVtx, );

 

Àüü ÄÚµå´Â mxp23_skinning_view1_soft.zipÀ» Âü°í Çϱ⠹ٶø´Ï´Ù.

 

¼ÒÇÁÆ®¿þ¾î ó¸® ¹æ¹ýÀº Çϵå¿þ¾îÀÇ ¼º´É¿¡ »ó°ü¾øÀÌ µ¿ÀÛÇÑ´Ù´Â ÀåÁ¡ÀÌ ÀÖÁö¸¸ Á¤Á¡ÀÇ º¹»çº»À» °¡Áö°í ÀÖ¾î¾ß Çϱ⠶§¹®¿¡ °´Ã¼°¡ ¸¹¾ÆÁö¸é »ç¿ë ¸Þ¸ð¸®°¡ °´Ã¼¿¡ ºñ·ÊÇØ¼­ ´Ã¾î³ª°í, Á¤Á¡ÀÇ °³¼ö°¡ ¸¹¾ÆÁú¼ö·Ï ¿¬»ê ·®µµ Áõ°¡ÇÑ´Ù´Â ´ÜÁ¡ÀÌ ÀÖ½À´Ï´Ù.

 

»õ·Î¿î °´Ã¼°¡ ÀÌÀü °´Ã¼¿Í °°Àº ÇüÅÂÀÇ ¿ÀºêÁ§Æ®ÀÇ °æ¿ì Á¤Á¡À» º¹»çÇÏÁö ¾Ê°í ½ºÅ°´× ¾Ö´Ï¸ÞÀÌ¼Ç Çà·Ä¸¸ ´Ã¸®´Â Çϵå¿þ¾î ó¸® ¹æ¹ýÀº ¾Ö´Ï¸ÞÀÌ¼Ç °»½Å¿¡¼­´Â ½ºÅ°´× ¾Ö´Ï¸ÞÀÌ¼Ç Çà·Ä ¹öÆÛ¿¡ °»½ÅµÈ ¾Ö´Ï¸ÞÀÌ¼Ç Çà·ÄÀ» º¹»çÇϰí, ·»´õ¸µ¿¡¼­´Â À̸¦ ±×·¡ÇÈ ÆÄÀÌÇÁ¶óÀο¡ ¿¬°áÇϱ⸸ ÇÏ¸é µË´Ï´Ù.

¸ÕÀú ½ºÅ°´×ÀÌ GPU¿¡¼­ ó¸®µÉ ¼ö ÀÖµµ·Ï ´ÙÀ½°ú °°Àº ±¸Á¶Ã¼¸¦ ÁغñÇÕ´Ï´Ù. ½ºÅ°´×¿¡ ´ëÇÑ ±¸Á¶Ã¼ ¼³Á¤Àº ÀÌÀüÀÇ °íÁ¤ ±â´É ÆÄÀÌÇÁ¶óÀο¡¼­ÀÇ ½ºÅ°´× ºÎºÐÀ» Âü°í Çϱ⠹ٶø´Ï´Ù.

 

struct VtxBlend

{

        VEC3           p;

        FLOAT          g[3];          // BLEND WEIGHT

        BYTE           m[4];          // MATRIX INDEX

        enumFVF = (D3DFVF_XYZB4 | D3DFVF_LASTBETA_UBYTE4),       };

};

 

´ÙÀ½À¸·Î ±×·¡ÇÈ ÆÄÀÌÇÁ¶óÀο¡ ¼³Á¤ÇÒ Blending Çà·Ä ¹è¿­À» ¼±¾ðÇÕ´Ï´Ù.

 

D3DXMATRIX     m_mtBlnd[LCM_MAX_BLEND];      // Blending Matrix Buffer

 

¾Ö´Ï¸ÞÀÌ¼Ç °»½Å¿¡¼­ ¾ÕÀÇ Çà·Ä ¹è¿­¿¡ ÃÖÁ¾ ¿ùµå Çà·ÄÀÎ "¾Ö´Ï¸ÞÀÌ¼Ç °»½Å Çà·Ä * ÀÚ½ÅÀÇ ¿ùµå Çà·Ä" °ªÀ» º¹»çÇÕ´Ï´Ù.

 

INT CLcmAcm::FrameMove()

¡¦

// World Çà·Ä ¾÷µ¥ÀÌÆ®

        for(n=0; n<m_Header.nGeo; ++n)

        {

               LcGeo*  pGeo    = &m_pGeo[n];

               MATA    mtAni;

               D3DXMatrixIdentity(&mtAni);

 

               if(pGeo->pAni)

                       mtAni = pGeo->pAni[m_nAni];

 

               m_mtBlnd[n] =  mtAni * m_mtWld;

        }

 

·»´õ¸µ¿¡¼­´Â µð¹ÙÀ̽ºÀÇ Software Vertex ProcessingÀ» Ȱ¼ºÈ­ ÇÕ´Ï´Ù. À̰ÍÀº µð¹ÙÀ̽º´Â Mixed ¶Ç´Â Software·Î »ý¼ºµÇ¾î¾ß °¡´ÉÇÕ´Ï´Ù.

´ÙÀ½À¸·Î µð¹ÙÀ̽ºÀÇ ·»´õ¸µ »óÅ¿¡ ´ëÇÑ INDEXEDVERTEXBLENDENABLEÀ» Ȱ¼ºÈ­ Çϰí, VERTEXBLEND¿¡ ÀûÀýÇÑ °ª(D3DVBF_3WEIGHTS)À» ¼³Á¤ÇÕ´Ï´Ù. ¸¶Áö¸·À¸·Î SetTransform() ÇÔ¼ö¸¦ ÀÌ¿ëÇØ¼­ ½ºÅ°´× Çà·Ä ¹è¿­À» Àü´ÞÇÕ´Ï´Ù.

 

void CLcmAcm::Render()

¡¦

for(n=0; n<m_Header.nGeo; ++n)

        {

               LcGeo*  pGeo = &m_pGeo[n];

               m_pDev->SetSoftwareVertexProcessing(TRUE);

               m_pDev->SetRenderState(D3DRS_INDEXEDVERTEXBLENDENABLE, TRUE );

               m_pDev->SetRenderState(D3DRS_VERTEXBLEND, D3DVBF_3WEIGHTS );

 

               for(k=0; k<LCM_MAX_BLEND; ++k)

                       m_pDev->SetTransform( D3DTS_WORLDMATRIX(k), &m_mtBlnd[k] );

 

               m_pDev->DrawIndexedPrimitiveUP(¡¦);

        }

 

Àüü ÄÚµå´Â mxp23_skinning_view2_hard.zipÀ» Âü°í Çϱ⠹ٶø´Ï´Ù.

 

½¦ÀÌ´õ¸¦ ÀÌ¿ëÇÑ ¹æ¹ýÀº ¸¦ Àú¼öÁØ ¶Ç´Â °í¼öÁØ ¾ð¾î(High Level Shading Language)·Î ±¸ÇöÇÏ´Â °ÍÀÔ´Ï´Ù. °í¼öÁØ ¾ð¾î HLSL·Î ÀÛ¼ºÇÒ ¶§ °¡Àå Áß¿äÇÑ ºÎºÐÀº Á¤Á¡ ó¸® ÇÔ¼öÀÇ ÀÔ·Â Àμö¿Í ½Ã¸àƽ Á¤ÀÇ´Â ½ÅÁßÇØ¾ß ÇÕ´Ï´Ù. ´ÙÀ½ ÇÔ¼ö´Â ½ºÅ°´×¿¡ ´ëÇÑ HLSL ÄÚµåÀÔ´Ï´Ù. À妽º¿¡ ´ëÇÑ Àμö Á¤ÀǸ¦ int4·Î ¼³Á¤Çϰí ÀÖÀ½À» ±â¾ïÇϱ⠹ٶø´Ï´Ù.

 

ÀÔ·Â ·¹Áö½ºÅÍ °ªÀº Read OnlyÀ̱⠶§¹®¿¡ °ªÀ» º¯°æÇÒ ¼ö ¾ø½À´Ï´Ù. ÀÌ·± ÀÌÀ¯·Î Wgx º¯¼ö¿¡ ÀÔ·Â ·¹Áö½ºÅÍ °ª(Wgt)À» º¹»çÇϰí À妽º 3¿¡ ´ëÇÑ °ªÀ» ¼³Á¤Çϰí ÀÖ½À´Ï´Ù. °£´ÜÈ÷ for¹®¿¡¼­ ºñÁß°ú Çà·ÄÀ» °ö¼ÀÇÑ ÈÄ ÀÌ °á°ú¸¦ ´©Àû½ÃÄÑ ¸¦ ±¸Çϰí ÀÖ½À´Ï´Ù.

¶ÇÇÑ ÀÇ ¸¶Áö¸· _44 °ªÀÌ 1 º¸´Ù ¸Ö¸® ¶³¾îÁ® ÀÖÀ¸¸é ÀÇ Çà·ÄÀ» ´ÜÀ§Çà·Ä·Î ¸¸µé¾î¾ß ÇÕ´Ï´Ù.

À» ±¸ÇÏ°í ³ª¼­ ÀÌ Çà·Ä¿¡ °´Ã¼ÀÇ ¿ùµå Çà·ÄÀ» °öÇØ¼­ ÃÖÁ¾ ¿ùµå Çà·ÄÀ» ¸¸µç ´ÙÀ½ Á¤Á¡À» ¿ùµå º¯È¯, ºä º¯È¯, Åõ¿µ º¯È¯¿¡ ´ëÇÑ ¿¬»êÀ» ÁøÇàÇÕ´Ï´Ù.

 

float4x4 m_mtBlnd[128]: WORLDMATRIXARRAY;    // Blending Matrix Buffer

 

float4 VtxBlendfloat4 Pos: POSITION

               , float4 Wgt: BLENDWEIGHT

               , int4   Idx: BLENDINDICES ) : POSITION

{

        float4         Pout =0.0f;

        float4x4       mtW = 0.0f;

        float4         Wgx = Wgt;

 

        Wgx[3] = 1.0f - (Wgx[0] + Wgx[1] + Wgx[2]);

 

        // ¥ÒMi * Wi ¿¬»ê

        for(int i=0; i<4; ++i)

               mtW += Wgx[i] * m_mtBlnd[Idx[i]];

 

        // _44 °ªÀÌ 1¿¡¼­ ¸Ö¸® ¶³¾îÁ® ÀÖÀ¸¸é ´ÜÀ§Çà·Ä·Î ¸¸µç´Ù.

        if(mtW._44 <0.001f)

               mtW = float4x4(1,0,0,00,1,0,00,0,1,00,0,0,1);

 

        mtW = mul(mtW, m_mtWld);      // °´Ã¼ÀÇ ¿ùµå Çà·Ä°ú °ö¼À

        Pout = mul(Pos, mtW);         // ¿ùµå º¯È¯

        Pout = mul(Pout, m_mtViw);    // ºä º¯È¯

        Pout = mul(Pout, m_mtPrj);    // Åõ¿µ º¯ÇÑ

 

        return P;

}

 

½¦ÀÌ´õ ÄÚµå´Â mxp23_skinning_view3_shader1.zipÀÇ "data/shader.fx"¸¦ Âü°í Çϱ⠹ٶø´Ï´Ù.

 

·»´õ¸µ¿¡¼­´Â ºä Çà·Ä, Åõ¿µ Çà·Ä, ¿ùµå Çà·Ä, Blending Çà·ÄÀ» ¼³Á¤Çϰí Àå¸éÀ» ¿¬ÃâÇÕ´Ï´Ù. Blending Çà·ÄÀº ÀÌÀüÀÇ Çϵå¿þ¾î 󸮿¡¼­ »ç¿ëÇÑ Çà·Ä ¹è¿­À» ±×´ë·Î »ç¿ë ÇÕ´Ï´Ù.

 

m_pEft->SetMatrix("m_mtViw", &mtViw); // ºä Çà·Ä ¼³Á¤

m_pEft->SetMatrix("m_mtPrj", &mtPrj); // Åõ¿µ Çà·Ä ¼³Á¤

m_pEft->SetMatrix("m_mtWld", &m_mtWld);      // ¿ùµå Çà·Ä ¼³Á¤

m_pEft->SetMatrixArray("m_mtBlnd", m_mtBlnd, LCM_MAX_BLEND); // Blending Çà·Ä ¼³Á¤

¡¦

hr = m_pDev->DrawIndexedPrimitiveUP(¡¦);

 

Àüü ÄÚµå´Â mxp23_skinning_view3_shader1.zipÀ» Âü°íÇϱ⠹ٶø´Ï´Ù.

 

¸¸¾à ½¦ÀÌ´õ ÄÚµå ÀÛ¼º¿¡¼­ ÀÔ·Â ·¹Áö½ºÅÍ(ÀÔ·Â Àμö)ÀÇ ¼³Á¤¿¡ ¾î·Á¿òÀÌ ÀÖÀ¸¸é ºñÁß°ú Çà·ÄÀÇ À妽º¸¦ ÅØ½ºÃ³ ÁÂÇ¥¿¡ Àû¿ëÇØ¼­ ±¸ÇöÇØµµ µË´Ï´Ù. ´ÙÀ½Àº ·»´õ¸µ ¿ÀºêÁ§Æ®°¡ µÎ °³ÀÇ ÅØ½ºÃ³ ÁÂÇ¥¸¦ »ç¿ëÇϰí ÀÖÀ» ¶§ ½ºÅ°´× ±¸Çö ¿¹ÀÔ´Ï´Ù.

 

float4 VtxBlendfloat4 Pos: POSITION

               , float2 Tx0: TEXCOORD0       // ÅØ½ºÃ³ ÁÂÇ¥ 0

               , float2 Tx1: TEXCOORD1       // ÅØ½ºÃ³ ÁÂÇ¥ 1

               , float4 Wgt: TEXCOORD2       // Blending Weight

               , float4 Idx: TEXCOORD3       // Blending Index

 ) : POSITION

{

        float4  Pout =0.0f;

        float4x4 mtW = 0.0f;

 

        // ¥ÒMi * Wi ¿¬»ê

        for(int i=0; i<4; ++i)

               mtW += Wgt[i] * m_mtBlnd[Idx[i]];

¡¦

 

ÅØ½ºÃ³ ÁÂÇ¥¸¦ »ç¿ëÇÏ°Ô µÇ¸é ´ÙÀ½°ú °°ÀÌ Á¤Á¡ ±¸Á¶Ã¼¿Í FVF¸¦ ¼öÁ¤ÇØ¾ß ÇÕ´Ï´Ù.

 

struct VtxBlend

{

        VEC3    p;

        VEC2    t0;     // Texture Coordinate 0

        VEC2    t1;     // Texture Coordinate 1

 

        VEC4    g;      // BLEND WEIGHT

        VEC4    m;      // MATRIX INDEX

        enumFVF = (D3DFVF_XYZ | D3DFVF_TEX4 | \

D3DFVF_TEXCOORDSIZE4(2) | D3DFVF_TEXCOORDSIZE4(3)), };

};

 

Blend Weight¿Í Matrix Index´Â 4°³¸¦ »ç¿ëÇϹǷΠD3DXVECTOR4¸¦ »ç¿ëÇϸç ÀÌ °æ¿ì ÅØ½ºÃ³ ÁÂÇ¥ ½Ã½ºÅÛÀ» D3DFVF_TEXCOORDSIZE4·Î º¯°æÇØ¾ß ÇÕ´Ï´Ù.

ÅØ½ºÃ³ ÁÂÇ¥¸¦ »ç¿ëÇÏ°Ô µÇ¾î Á¤Á¡ÀÇ Å©±â°¡ 16Byte ´õ »ç¿ëÇÏÁö¸¸ °¡Àå ¹«³­ÇÏ°í ¾ÈÀüÇÏ°Ô »ç¿ëÇÒ ¼ö ÀÖ´Â ¹æ¹ýÀÔ´Ï´Ù. mxp23_skinning_view3_shader2.zipÀ» Âü°íÇϱ⠹ٶø´Ï´Ù.

 

  

<½ºÅ°´× ¾Ö´Ï¸ÞÀ̼Ç: Software, Hardware, Shader>

 

 

5.3.4 Interpolation

°ÔÀÓÀ» ½ÇÇàÇÏ´Â °³Àοë ÄÄÇ»ÅÍÀÇ ¼º´ÉÀº Â÷À̰¡ ÀÖÀ¸¹Ç·Î ÇÁ·¹ÀÓ°ú ÇÁ·¹ÀÓ »çÀ̸¦ º¸Á¤Çؼ­ Àå¸éÀ» ¿¬ÃâÇØ¾ß ÇÕ´Ï´Ù. °¡Àå °£´ÜÇÑ º¸Á¤ ¹æ¹ýÀº ¼±Çü º¸°£(Linear Interpolation)À¸·Î ¿ì¸®´Â ASEÀ» ParsingÇÒ ¶§ ÇØºÃ½À´Ï´Ù.

ASE¿¡¼­´Â À§Ä¡, ȸÀü¿¡ »ç¿ø¼ö¸¦ °¡Áö°í ÀÖ´Â »óȲ¿¡¼­ ¼±Çü º¸°£À» ±¸¼ºÇßÀ¸³ª Áö±ÝÀº Çà·Ä·Î ¾Ö´Ï¸ÞÀÌ¼Ç Á¤º¸¸¦ °¡Áö°í À־ ÀÌ Çà·Ä¿¡¼­ À§Ä¡¿Í »ç¿ø¼ö¸¦ ¾ò¾î¼­ ¼±Çüº¸°£ ÇÑ ´ÙÀ½ ´Ù½Ã Çà·Ä·Î ¸¸µé¾î¾ß ÇÕ´Ï´Ù.

 

Çà·Ä¿¡¼­ _41, _42, _43ÀÇ °ªÀº À̵¿¿¡ ´ëÇÑ º¯È¯À¸·Î À§Ä¡¸¦ ³ªÅ¸³À´Ï´Ù. ȸÀüÀÇ °æ¿ì¿¡´Â D3DXQuaternionRotationMatrix()ÇÔ¼ö¸¦ ÀÌ¿ëÇØ¼­ »ç¿ø¼ö¸¦ ±¸ÇÕ´Ï´Ù.

À§Ä¡´Â ´ÙÀ½ÀÇ ¼±Çü º¸°£ °ø½ÄÀ¸·Î ±¸ÇÕ´Ï´Ù.

 

v' = (1 - t) * v1 + t * v2

 

»ç¿ø¼ö´Â D3DXQuaternionSlerp() ÇÔ¼ö¸¦ ÀÌ¿ëÇÕ´Ï´Ù.

 

´ÙÀ½Àº µÎ Çà·Ä°ú ºñÁß t°¡ ÁÖ¾îÁú ¶§ À§Ä¡¿Í ȸÀü¿¡ ´ëÇÑ ¼±Çü º¸°£ÀÔ´Ï´Ù.

 

void CLcmAcm::MatrixLerp(D3DXMATRIX* pOut

, const D3DXMATRIX* m1, const D3DXMATRIX* m2, DOUBLE t)

{

        D3DXQUATERNION q, q1, q2;

        D3DXVECTOR3    v, v1, v2;

 

        D3DXQuaternionRotationMatrix(&q1, m1);               // ȸÀü ÃßÃâ

        D3DXQuaternionRotationMatrix(&q2, m2);

 

        v1 = D3DXVECTOR3(m1->_41, m1->_42, m1->_43); // À§Ä¡ ÃßÃâ

        v2 = D3DXVECTOR3(m2->_41, m2->_42, m2->_43);

 

        v = (1 - t) * v1 + t * v2;                   // À§Ä¡¿¡ ´ëÇÑ ¼±Çü º¸°£

        D3DXQuaternionSlerp(&q, &q1, &q2, t);                // ȸÀüÀÇ ¼±Çü º¸°£

 

        D3DXMatrixRotationQuaternion(pOut, &q);              // ȸÀüÀ» Çà·Ä·Î Àüȯ

        pOut->_41 = v.x; pOut->_42 = v.y; pOut->_43 = v.z; // À§Ä¡ Àû¿ë

}

 

±×·±µ¥ ½Ã°£¿¡ ´ëÇÑ ¾Ö´Ï¸ÞÀÌ¼Ç °£°ÝÀ» Á¼°Ô ¼³Á¤Çϰí Çà·ÄÀ» ÃßÃâÇßÀ¸¸é ¾ÕÀÇ ÄÚµåó·³ °è»êÇÏÁö ¾Ê°í Çà·Ä ÀÚü¸¦ ¼±Çü º¸°£Çصµ µË´Ï´Ù.

 

*pOut = (1 - t) * (*m1) + t * (*m2);

 

À̰ÍÀÌ °¡´ÉÇÑ ÀÌÀ¯´Â ȸÀüÀÇ °æ¿ì º¸°£ÇÏ´Â µÎ »ç¿ø¼öÀÇ °¢µµ°¡ ÀÛÀ¸¸é °¡ µÇ¾î ´ÙÀ½°ú °°ÀÌ È¸ÀüÀÇ »ç¿ø¼ö º¸°£ °ø½ÄÀÌ ¼±Çü º¸°£À¸·Î ¹Ù²î°Ô µÇ±â ¶§¹®¿¡ Çà·ÄÀ» ¼±Çü º¸°£ ÇØµµ µÇ´Â °ÍÀÔ´Ï´Ù.

 

 

mxp24_interpolation.zipÀº Çà·ÄÀ» ¼±Çü º¸°£ÇÒ ¶§¿Í »ç¿ø¼ö¸¦ ºÐ¸®Çؼ­ º¸°£ÇÏ´Â ¿¹ÀÔ´Ï´Ù. ¾Ö´Ï¸ÞÀ̼ÇÀÇ °£°ÝÀÌ Á¼±â ¶§¹®¿¡ ´«¿¡ ¶ç°Ô º¸ÀÌ´Â Â÷ÀÌ´Â ¾ø½À´Ï´Ù.

 

<¾Ö´Ï¸ÞÀÌ¼Ç º¸°£: mxp24_interpolation.zip>

 

 

5.4 ±âŸ

5.4.1 Normal

¸Æ½ºÀÇ ¸ðµç ¸Þ½¬´Â ¹ý¼± º¤ÅÍ(Normal Vector)¸¦ °¡Áö°í ÀÖ½À´Ï´Ù. ¶ÇÇÑ ¹ý¼± º¤ÅÍÀÇ °³¼ö´Â Á¤Á¡ÀÇ ¼ö¿Í ÀÏÄ¡ ÇÕ´Ï´Ù. ¹ý¼± º¤Å͸¦ ÃßÃâÇϱâ À§Çؼ­ ´ÙÀ½°ú °°ÀÌ ¸Þ½¬¿¡°Ô Á¤Á¡ÀÇ ¹ý¼±°ú Face(»ï°¢Çü Æò¸é)¿¡ ´ëÇÑ ¹ý¼± º¤ÅÍ »ý¼ºÀ» ¿äûÇÕ´Ï´Ù.

 

Mesh* pMesh    = &pTri->GetMesh();

¡¦

pMesh->buildNormals();

 

´ÙÀ½À¸·Î ¹ý¼± º¤Å͸¦ ÀúÀåÇÒ °ø°£À» »ý¼ºÇÏ°í ¸Þ½¬ÀÇ getNormal() ÇÔ¼ö¸¦ ÀÌ¿ëÇØ¼­ ¹ý¼± º¤Å͸¦ ¾ò¾î¿Í ÀúÀåÇÕ´Ï´Ù.

 

INT iNvtx = pMesh->getNumVerts();

¡¦

pGeo->pNor = new D3DXVECTOR3[iNvtx];

for (n=0; n<iNvtx; ++n)

{

        Point3 v = Normalize(pMesh->getNormal(n));   // ¹ý¼±º¤ÅÍ ÃßÃâ

        pGeo->pNor[n].x = v.x;

        pGeo->pNor[n].y = v.z; //y <--> z ±³È¯

        pGeo->pNor[n].z = v.y;

}

 

 

5.4.2 Material

Geometry¿¡ Àû¿ëµÈ ÅØ½ºÃ³ ÆÄÀÏ À̸§Àº ¸Æ½ºÀÇ ÀçÁú(Material)¿¡¼­ ã¾Æ¾ß ÇÕ´Ï´Ù. ±×·±µ¥ D3DÀÇ ÀçÁúÀº ÇϳªÀÇ ¸Þ½¬ µ¢¾î¸®(Geometry Object)¿¡ ÇϳªÀÇ ÀçÁúÀÌ Àû¿ëµÇ´Â µ¥ ¹ÝÇØ¼­ ¸Æ½ºÀÇ ÀçÁúÀº ÇϳªÀÇ ¸Þ½¬ ¾È¿¡¼­µµ ¿©·¯ ÀçÁúÀ» »ç¿ëÇϱ⵵ ÇÕ´Ï´Ù. ÀÌ·¯ÇÑ °æ¿ì¿¡´Â »ï°¢Çüµé °¢ ÀçÁú¿¡ µû¶ó ºÐ¸®ÇÏ°í ´Ù½Ã ±¸ÃàÇØ¾ß ÇÏÁö¸¸ À̰ÍÀº ÇÁ·Î±×·¡¸Ó¿¡°Ô ³Ê¹«³ª ¸¹Àº ³ë·Â°ú ½Ã°£À» ¿ä±¸ÇÏ°Ô µÇ¸ç Àß ÇØ°áµÇÁöµµ ¾Ê½À´Ï´Ù. ¿©±â¼­ ¿øÄ¢À» ¼¼¿ì´Â °ÍÀÌ Áß¿äÇѵ¥ ³ªÀÇ ¸Þ½¬¿¡´Â ÇϳªÀÇ ÅØ½ºÃ³¸¸ Àû¿ëÇÏ°í ¿©·¯ ¸Þ½¬°¡ °áÇÕÇÏ´Â °æ¿ì¶ó¸é °¢°¢ÀÇ ¸Þ½¬¸¦ µû·Î ÃßÃâÇÑ ´ÙÀ½ ÇÁ·Î±×·¥¿¡¼­ ¸µÅ©(link)ÇÏ´Â °ÍÀÔ´Ï´Ù. ÀÌ·¸°Ô ÇÏ¸é °ÔÀÓ¿¡ ¿Ã·ÈÀ» ¶§ ¾û¶×ÇÑ ÅØ½ºÃ³°¡ ºÙ°Å³ª ¾È ºÙ´Â ¹®Á¦µéÀ» ¾î´À Á¤µµ ÇØ°áÇÒ ¼ö ÀÖ½À´Ï´Ù.

 

º»°ÝÀûÀ¸·Î ÀçÁú¿¡¼­ ÅØ½ºÃ³ ÆÄÀÏ À̸§À» ±¸ÇØ º¾½Ã´Ù.

INode °´Ã¼¿¡¼­ ¿ì¸®´Â ÀçÁúÀ» ´ÙÀ½°ú °°ÀÌ ¾ò¾î¿Ã ¼ö ÀÖ½À´Ï´Ù.

 

INode*  pNode = m_vMaxNode[i];

Mtl*    pMtrl = pNode->GetMtl();

 

¸Æ½ºÀÇ ÀçÁúÀº INodeó·³ ÇÏÀ§ ÀçÁúÀ» ³ª¹« ±¸Á¶(Tree Structure)·Î °¡Áö°í ÀÖ½À´Ï´Ù. µû¶ó¼­ ÀçÁúÀ» ¾òÀº ´ÙÀ½¿¡ ÇÏÀ§ ÀçÁúÀ» ´ÙÀ½°ú °°ÀÌ ¾ò¾î¾ß ÇÕ´Ï´Ù.

 

int iSub = pMtl->NumSubMtls();

for(int i=0; i<iSub; ++i)

        Mtl* pSub = pMtl->GetSubMtl(i);

 

À̰ÍÀº ³ëµå¸¦ ¸ðÀ» ¶§Ã³·³ Àç±Í È£Ãâ(Recursive Call) ÇÔ¼ö¸¦ ¸¸µé¾î¼­ Àüü ÀçÁúÀ» ¸ð¾Æ¾ß ÇÕ´Ï´Ù. ÀçÁúÀ» ¸ðÀ» ¶§ ¾î´À ³ëµå¿¡¼­ ¾ò¾îÁø ÀçÁúÀÎÁö ´ÙÀ½°ú °°Àº ±¸Á¶Ã¼¸¦ ÀÛ¼ºÇÕ´Ï´Ù.

 

struct LcMtl

{

        INode*  pNode;  // Node

        Mtl*    pMtrl;  // Material

};

 

³ëµå¿Í ÀçÁúÀ» ÀúÀåÇÒ ¼ö ÀÖµµ·Ï ÀÌ ±¸Á¶Ã¼¸¦ ÀÌ¿ëÇØ¼­ ´ÙÀ½°ú °°Àº STLÀÇ º¤ÅÍ ÄÁÅ×À̳ʸ¦ ¸¸µì´Ï´Ù.

 

std::vector<LcMtl>     m_vMaxMtrl;

 

Àç±Í È£Ãâ ÇÔ¼ö ¾È¿¡¼­ ¸ÕÀú ÀÔ·Â ¹ÞÀº ³ëµå¿Í ÀçÁúÀ» ¹­¾î¼­ ÀúÀåÇÕ´Ï´Ù. ´ÙÀ½À¸·Î ÇÏÀ§ ÀçÁúÀ» ¾ò°í ÀÌ ÇÔ¼ö¸¦ ´Ù½Ã È£ÃâÇÕ´Ï´Ù.

 

void LcMax::GatherMaterial(INode* pNode, Mtl* pMtl)

¡¦

        m_vMaxMtrl.push_back(LcMtl(pNode, pMtl));

        int iSub = pMtl->NumSubMtls();

        for(int i=0; i<iSub; ++i)

        {

               Mtl* pSub = pMtl->GetSubMtl(i);

               GatherMaterial(pNode, pSub);

        }

 

ÀÌ·¸°Ô ³ëµå¿¡ ´ëÇÑ ¸ðµç ÀçÁúÀ» ÀúÀåÇß½À´Ï´Ù. ´ÙÀ½À¸·Î ÀçÁú ¾È¿¡¼­ ÅØ½ºÃ³ ÆÄÀÏ À̸§À» °¡Á®¿Í¾ß ÇÕ´Ï´Ù. ¸Æ½ºÀÇ ÀçÁúÀº ¿©·¯ ÅØ½ºÃ³¸¦ °¡Áö°í ÀÖ½À´Ï´Ù. À̵é ÅØ½ºÃ³´Â Á¶¸í È¿°ú¿Í ¹Ý»ç È¿°ú µî¿¡ ´ëÇÑ ¿ªÇÒÀ» ¼öÇàÇÕ´Ï´Ù. ¿ì¸®°¡ °¡Á®¿À·Á´Â ÅØ½ºÃ³´Â Á¶¸í È¿°ú Áß¿¡¼­ Diffuse Map¿¡ ´ëÇÑ ÅØ½ºÃ³À̸ç ÀÌ ¾ÆÀ̵ð´Â " ID_DI" ÀÔ´Ï´Ù.

 

ÀçÁú¿¡¼­ À̸§À» °¡Á®¿À´Â ¹æ¹ýÀº ¸ÕÀú ÀçÁú¿¡¼­ ÇÏÀ§ ÅØ½ºÃ³ÀÇ ¼ýÀÚ¸¦ ¾Ë¾Æ³»°í ÀÌ ¼ýÀÚ¸¸Å­ ¼øÈ¸Çϸ鼭 Texmap °´Ã¼¸¦ ¾ò½À´Ï´Ù. Texmap °´Ã¼¸¦ BitmapTex À¸·Î ij½ºÆÃÇØ¼­ GetMapName() ÇÔ¼ö¸¦ È£ÃâÇϸé À̸§À» °¡Á®¿À°Ô µË´Ï´Ù.

 

INT iSub = pMtrl->NumSubTexmaps();

for( j=0; j<iSub; ++j)

{

        Texmap* subTex = pMtrl->GetSubTexmap(j);

        DumpTexture(pLcMtl, subTex, j);

}

¡¦

void LcMax::DumpTexture(LcMtl* pLcMtrl, Texmap* txm, INT iSubIdx)

¡¦

        // °æ·Î¸¦ Æ÷ÇÔÇÑ ÅØ½ºÃ³ ÆÄÀÏ À̸§À» °¡Á®¿Â´Ù.

        TSTR bitmapFile = ((BitmapTex *)txm)->GetMapName();

¡¦

        // ÇÏÀ§ ÅØ½ºÃ³ °Ë»ç

        INT iSub = txm->NumSubTexmaps();

        for(i=0; i<iSub; ++i)

        {

               Texmap* pSub = txm->GetSubTexmap(i);

               DumpTexture(pLcMtrl, pSub, iSubIdx);

        }

 

°¢ ³ëµå´Â °°Àº ÀçÁúÀ» »ç¿ëÇÒ ¼ö ÀÖ½À´Ï´Ù. µû¶ó¼­ ÅØ½ºÃ³ ÆÄÀÏÀ̸§ÀÌ Áߺ¹ µÉ ¼ö Àִµ¥ STLÀÇ Set ÄÁÅ×À̳ʸ¦ ÀÌ¿ëÇϸé Áߺ¹µÈ À̸§À» Á¦°ÅÇÒ ¼ö ÀÖ½À´Ï´Ù. ³ëµå¿Í ÅØ½ºÃ³ ÆÄÀÏ À̸§ ¿¬°áÀº ±â¼úÀûÀÎ ºÎºÐÀ̹ǷΠmxp25_lcm_skinning_plugin.zip ¿¹Á¦ÀÇ GatherTexture(), SetupTextureIndex(), FindTextureIndex() ÇÔ¼ö µîÀ» Âü°í Çϱ⠹ٶø´Ï´Ù.

 

 

5.4.3 ÅØ½ºÃ³ ÁÂÇ¥

Ç÷¯±×ÀÎÀÇ ¸¶Áö¸·ÀÎ ÅØ½ºÃ³ ÁÂÇ¥ ÃßÃâÀÔ´Ï´Ù. ASE¿¡¼­ "¸Æ½ºÀÇ Á¤Á¡Àº ÅØ½ºÃ³ ÁÂÇ¥¿¡¼­ °øÀ¯ µÉ ¼ö ÀÖ´Ù"¶ó°í ¾ð±ÞÇÑ ÀûÀÌ ÀÖ½À´Ï´Ù. µû¶ó¼­ Á¤Á¡ÀÇ °³¼ö¸¦ ÅØ½ºÃ³ ÁÂÇ¥¸¸Å­ ´Ã·ÁÁÖ¾î¾ß ÇÕ´Ï´Ù. ±×¸®°í ¸Æ½º´Â ÅØ½ºÃ³ ÁÂÇ¥ÀÇ À妽º°¡ ²À 0¿¡¼­ºÎÅÍ ½ÃÀÛÇÏÁö ¾ÊÀ¸¸ç ¶ÇÇÑ Áß°£¿¡ »ç¿ëÇÏÁö ¾Ê´Â À妽ºµµ ÀÖ½À´Ï´Ù. ¿Ïº®¿¡ °¡±î¿î Ç÷¯±×ÀÎÀº ÀÌ·± °Íµµ ó¸®ÇØ¾ß ÇÏÁö¸¸ ¿ª½Ã °£´ÜÇÑ ¹æ¹ýÀº ±×·¡ÇÈ ´ã´çÀÚ¿Í ÇùÀǸ¦ ÇØ¼­ UV Á¤¸®¸¦ ºÎŹÇÏ´Â °ÍÀÌ °¡Àå Çö¸íÇÑ ¹æ¹ýÀÔ´Ï´Ù.

 

UV°¡ Àû¿ëµÈ ¸Þ½¬¿¡¼­ Geometry¸¦ ±¸¼ºÇÏ´Â ¹æ¹ýÀ» Á¤¸®ÇÏ¸é ´ÙÀ½°ú °°½À´Ï´Ù.

 

1. T-face¿¡¼­ UV »ï°¢Çü¿¡ ´ëÇÑ À妽º ¸®½ºÆ®¸¦ ÃßÃâÇÑ´Ù.

2. T-vertex¿¡¼­ UV¸¦ ÃßÃâÇÑ´Ù.

3. T-face¿¡ ´ëÀÀÇÏ´Â À妽º´Â FaceÀ妽º¿Í °°À¸¹Ç·Î À̵éÀ» Çϳª·Î ¹­°í, U, V °ªµµ ¼³Á¤ÇÑ´Ù.

4. »õ·Î¿î Á¤Á¡ÀÇ °³¼ö¸¦ T-vertex °³¼ö¸¸Å­ ¼³Á¤ÇÑ´Ù.

5. Á¤Á¡ÀÇ À§Ä¡, ¹ý¼± º¤ÅÍ, BoneÀÇ À妽º¿Í ºñÁß °ª µîÀ» »õ·Î ¸¸µé°í 3¹ø¿¡¼­ ¹­Àº À妽º µîÀ» Âü°íÇØ¼­ °ªÀ» »õ·Î ¼³Á¤ÇÑ´Ù.

6. ÀÌÀüÀÇ À§Ä¡, ¹ý¼±, Bone¿¡ ´ëÇÑ °ªµéÀ» Áö¿ì°í »õ·Î¿î °ªµé·Î ¼³Á¤ÇÑ´Ù.

 

ÀÌ °úÁ¤Àº mxp25_lcm_skinning_plugin.zipÀÇ LcMax::SetupUV() ÇÔ¼ö¿¡ ±¸ÇöµÇ¾î ÀÖ½À´Ï´Ù. ÁÖ¿ä Äڵ带 ¼³¸íÇÏ¸é ¸ÕÀú ¸Þ½¬¿¡¼­ T-faceÀÇ ¼ýÀÚ¿Í T-vertex(UV) ¼ýÀÚ¸¦ ¾ò´Â ¹æ¹ýÀº ´ÙÀ½°ú °°½À´Ï´Ù.

 

nTfce   = pMesh->getNumFaces();               // T-face¿Í Face¼ýÀÚ´Â °°À½

nTvtt   = pMesh->getNumTVerts();      // T-vertex(UV) Number

 

´ÙÀ½À¸·Î Àӽà ¹öÆÛ¿¡ T-face¿Í T-vertex¸¦ ÀúÀåÇÕ´Ï´Ù.

 

// T-face List ÀúÀå

for(n=0; n<nTfce; ++n)

{

        pNewFce[n]=VtxIdx( pMesh->tvFace[n].t[0]

                       , pMesh->tvFace[n].t[2]

                       , pMesh->tvFace[n].t[1]);

}

 

// T-vertex(UV) ÀúÀå

for(n=0; n<nTvtt; ++n)

{

        UVVert t = pMesh->tVerts[n];

        pTvtt[n].x = t.x;

        pTvtt[n].y = 1.f - t.y;                      // DXÀÇ UV¿¡ ¸Â°Ô ¼öÁ¤

}

 

T-faceÀÇ °æ¿ì Faceó·³ À妽º°¡ 0, 2, 1·Î µÇ¾î¾ß ÇÕ´Ï´Ù. ±×¸®°í UV¿¡¼­ V°ªµµ ASEó·³ "1.0- V" ·Î ¼³Á¤ÇØ¾ß ÇÕ´Ï´Ù.

´ÙÀ½À¸·Î T-face, Face, U, V¸¦ ÀÛ¾÷À» Æí¸®ÇÏ°Ô Çϱâ À§ÇØ ÇϳªÀÇ ¹­À½À» ¸¸µì´Ï´Ù.

 

std::vector<_Tpck >    lsFceVtxUV;

for(; itF != itL; ++itF)

{

        int nT = (*itF).first.n;

        int nV = (*itF).second;

        FLOAT U = pTvtt[nT].x;

        FLOAT V = pTvtt[nT].y;

        lsFceVtxUV.push_back( _Tpck(nT, nV, U, V));

}

 

Face´ë½Å T-face¸¦ À妽º ¸®½ºÆ®·Î Á¤Çϰí Á¤Á¡ÀÇ °³¼ö, ¹ý¼±ÀÇ °³¼ö, Á¤Á¡¿¡ ´ëÇÑ º»ÀÇ ºñÁßÀ» º¯°æÇϰí ÀÌÀü °ª¿¡¼­ ã¾Æ¿Í º¹»çÇÕ´Ï´Ù.

 

INT     nNewVtxSize =  lsFceVtxUV.size();

D3DXVECTOR3* pNewPos = new D3DXVECTOR3[nNewVtxSize]; // new Position List

D3DXVECTOR3* pNewNor = new D3DXVECTOR3[nNewVtxSize]; // new Normal Vector

D3DXVECTOR2* pNewUVW = new D3DXVECTOR2[nNewVtxSize]; // new UVW Vector

¡¦

for(n=0; n<nNewVtxSize; ++n)

{

        INT     G = lsFceVtxUV[n].G;          // Á¤Á¡ÀÇ À妽º

        FLOAT   U = lsFceVtxUV[n].U;

        FLOAT   V = lsFceVtxUV[n].V;

        pNewPos[n] = pOldPos[G];

        pNewNor[n] = pOldNor[G];

        pNewUVW[n].x = U;

        pNewUVW[n].y = V;

}

 

¸¸¾à Á¤Á¡¿¡ BonÀÇ À妽º¿Í ºñÁßÀÌ ÀÖÀ¸¸é ÀÌµé ¶ÇÇÑ Á¶Á¤ÇÕ´Ï´Ù.

 

LcmBoneS*      pNewBon = new LcmBoneS[nNewVtxSize];  // new Bones

¡¦

for(n=0; n<nNewVtxSize; ++n)

{

        int G = lsFceVtxUV[n].G;              // Á¤Á¡ÀÇ À妽º

        LcmBoneS* pBlndS= &pOldBon[G]; // Source

¡¦

        std::map<INT, FLOAT >::iterator       _F = pBlndS->vB.begin();

        std::map<INT, FLOAT >::iterator       _L = pBlndS->vB.end();

        for(; _F != _L; ++_F)

               pNewBon[n].vB.insert( *_F );

}

 

¸¶Áö¸·À¸·Î ÀÌÀü °ªµéÀ» Áö¿ì°í »õ·Î¿î °ªµé·Î º¯°æÇÕ´Ï´Ù.

 

SAFE_DELETE_ARRAY(     pOldFce );

SAFE_DELETE_ARRAY(     pOldPos );

SAFE_DELETE_ARRAY(     pOldNor );

pGeo->pFce     = pNewFce;

pGeo->pPos     = pNewPos;

pGeo->pNor     = pNewNor;

pGeo->pUVW     = pNewUVW;

pGeo->nVtx     = nNewVtxSize;

 

ÆÄÀÏ¿¡ ±â·ÏÇÒ ¶§´Â ÀÌÀüÀÇ ±¸Á¶¸¦ °ÅÀÇ ±×´ë·Î À¯ÁöÇÏ°í ¹ý¼± º¤ÅÍ, ÅØ½ºÃ³ ÆÄÀÏ ¸®½ºÆ®, Á¤Á¡ UV ¸®½ºÆ®¸¦ ¸¶Áö¸·¿¡ ±â·Ï ÇÕ´Ï´Ù. Àüü ÄÚµå´Â mxp25_lcm_skinning_plugin.zipÀ» Âü°í Çϱ⠹ٶø´Ï´Ù.

 

Ç÷¯±×ÀÎÀÌ ¼öÁ¤µÇ¾î ºä¾îµµ ¼öÁ¤ÇØ¾ß ÇÕ´Ï´Ù. ºä¾î¿¡¼­ ¸Þ½¬¿¡ ´ëÇÑ Á¤Á¡ ±¸Á¶Ã¼¸¦ ´ÙÀ½°ú °°ÀÌ ¹ý¼± º¤ÅÍ, ÅØ½ºÃ³ ÁÂÇ¥¸¦ Æ÷ÇÔ½Ã۰í FVFµµ º¯°æÇÕ´Ï´Ù.

 

struct VtxBlend

{

        VEC3           p;

        FLOAT          g[3];          // BLEND WEIGHT

        BYTE           m[4];          // MATRIX Index

 

        VEC3           n;             // Normal Vector

        VEC2           t;             // Texture Coordinate

 

        enumFVF = (D3DFVF_XYZB4 | D3DFVF_LASTBETA_UBYTE4 |\

                                    D3DFVF_NORMAL | D3DFVF_TEX1),   };

};

 

ÆÄÀÏÀ» Àд ºÎºÐ°ú ·»´õ¸µ¿¡¼­ ÅØ½ºÃ³ ¿¬°áÀº ¾î·ÆÁö ¾ÊÀ¸¹Ç·Î ³Ñ¾î°¡°Ú½À´Ï´Ù.

ÅØ½ºÃ³¿Í Á¶¸íÀ» Çȼ¿ ½¦ÀÌ´õ¿¡¼­ ó¸®ÇÒ ¼ö ÀÖµµ·Ï ´ÙÀ½°ú °°Àº ±¸Á¶Ã¼¸¦ ¼±¾ðÇÕ´Ï´Ù.

 

struct SVsOut

{

        float4  Pos: POSITION;

        float2  Tex: TEXCOORD0;        // Á¤Á¡ÀÇ ÅØ½ºÃ³ ÁÂÇ¥

        float3  Nor: TEXCOORD7;        // Á¤Á¡ÀÇ ¹ý¼± º¤ÅÍ

};

 

Á¤Á¡ µ¥ÀÌÅͰ¡ ¹ý¼± º¤ÅÍ, ÅØ½ºÃ³ ÁÂÇ¥¸¦ Æ÷ÇÔÇϰí ÀÖÀ¸¹Ç·Î Á¤Á¡ ó¸® ÇÔ¼öÀÇ ÀÔ·Â Àμö¿¡ ¹ý¼±°ú ÅØ½ºÃ³ ÁÂÇ¥¸¦ Ãß°¡ÇÕ´Ï´Ù.

 

SVsOut VtxBlendfloat4 Pos: POSITION               // Position

                , float4 Wgt: BLENDWEIGHT     // Blending Weight

                , int4   Idx: BLENDINDICES    // Blending Index

                , float3 Nor: NORMAL          // Normal Vector

                , float2 Tex: TEXCOORD0               // Texture Coordinate

               )

{

        SVsOut         Out = (SVsOut)0;

¡¦

        Out.Nor = Nor;

        Out.Tex = Tex;

 

        return Out;

}

 

¹ý¼± º¤ÅÍ¿Í ÅØ½ºÃ³´Â Ưº°È÷ ó¸®ÇØ¾ß ÇÒ ÀÏÀÌ ¾øÀ¸¹Ç·Î ±¸Á¶Ã¼¿¡ º¹»çÇØ¼­ ±×´ë·Î Ãâ·ÂÇÕ´Ï´Ù. Çȼ¿ ½¦ÀÌ´õ ó¸® ÇÔ¼ö¿¡¼­´Â UV ÁÂÇ¥¸¦ ÀÌ¿ëÇØ¼­ ÅØ½ºÃ³¿¡¼­ »ö»óÀ» »ùÇøµ(Sampling) ÇÕ´Ï´Ù.

 

float4 PxlBlend(SVsOut In) : COLOR0

{

        float4 Out = tex2D(smp0, In.Tex);     // Sampling from Texture by Sampler

        return Out;

}

 

Á¶¸íÀº ó¸®ÇÏÁö ¾Ê¾Ò´Âµ¥ ÀÌ ºÎºÐÀº ¿©·¯ºÐµé²²¼­ ä¿öº¸½Ã±â ¹Ù¶ø´Ï´Ù. ´ÙÀ½À¸·Î Å×Å©´Ð¿¡ Çȼ¿ ó¸® ÇÔ¼ö¸¦ ÁöÁ¤ÇÕ´Ï´Ù.

 

technique Tech

¡¦

        pass P1

        {

               VertexShader = compile vs_2_0 VtxBlend();

               PixelShader  = compile ps_2_0 PxlBlend();

        }

 

mxp25_lcm_skinning_viewer.zipÀ» ½ÇÇàÇÏ¸é ´ÙÀ½ ±×¸²Ã³·³ UV°¡ Àû¿ëµÈ È­¸éÀ» º¼ ¼ö ÀÖ½À´Ï´Ù.

 

 

<ÅØ½ºÃ³°¡ Àû¿ëµÈ ½ºÅ°´× ¿¹Á¦: mxp25_lcm_skinning_viewer.zip>

 

 

 







Creative Commons License