<?xml version="1.0" encoding="utf-8" ?>
<?xml-stylesheet href="http://rss.egloos.com/style/blog.xsl" type="text/xsl" media="screen"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/">
<channel>
	<title>2009포트폴리오</title>
	<link>http://cswq327.egloos.com</link>
	<description>윤병주 09포폴</description>
	<language>ko</language>
	<pubDate>Mon, 08 Jun 2009 15:52:34 GMT</pubDate>
	<generator>Egloos</generator>
	<image>
		<title>2009포트폴리오</title>
		<url>http://pds11.egloos.com/logo/200905/04/57/b0097657.jpg</url>
		<link>http://cswq327.egloos.com</link>
		<width>80</width>
		<height>60</height>
		<description>윤병주 09포폴</description>
	</image>
  	<item>
		<title><![CDATA[ [포트폴리오를 보시는 분께 드리는 글] ]]> </title>
		<link>http://cswq327.egloos.com/4345217</link>
		<guid>http://cswq327.egloos.com/4345217</guid>
		<description>
			<![CDATA[ 
  <p><strong>이 블로그는 포트폴리오 제출용으로 만든 것이며, 다른 카테고리는 숨겨놓았습니다.<br>동영상으로 올린 모든 포트폴리오는 제가 직접 만든 것입니다.<br>엔진구현을 목표로 어설프게나마 도전한 것입니다.<br>원하시면 소스를 보내드리겠습니다.</strong><br></p>			 ]]> 
		</description>
		<category>2009 포트폴리오</category>

		<comments>http://cswq327.egloos.com/4345217#comments</comments>
		<pubDate>Fri, 08 May 2009 07:13:52 GMT</pubDate>
		<dc:creator>2009포트폴리오</dc:creator>
	</item>
	<item>
		<title><![CDATA[ [wow] 어느 슬픈 술사이야기 02 ]]> </title>
		<link>http://cswq327.egloos.com/4339078</link>
		<guid>http://cswq327.egloos.com/4339078</guid>
		<description>
			<![CDATA[ 
  <div style="text-align:center"><img class="image_mid" border="0" onmouseover="this.style.cursor='pointer'" alt="" src="http://pds11.egloos.com/pds/200905/04/57/b0097657_49fea6191f8d5.jpg" width="500" height="5000" onclick="Control.Modal.openDialog(this, event, 'http://pds11.egloos.com/pds/200905/04/57/b0097657_49fea6191f8d5.jpg');" /></div>			 ]]> 
		</description>
		<category>자료링크</category>

		<comments>http://cswq327.egloos.com/4339078#comments</comments>
		<pubDate>Mon, 04 May 2009 08:24:06 GMT</pubDate>
		<dc:creator>넘버원가드</dc:creator>
	</item>
	<item>
		<title><![CDATA[ [wow] 어느 슬픈 술사이야기 01 ]]> </title>
		<link>http://cswq327.egloos.com/4339072</link>
		<guid>http://cswq327.egloos.com/4339072</guid>
		<description>
			<![CDATA[ 
  <div style="text-align:center"><img class="image_mid" border="0" onmouseover="this.style.cursor='pointer'" alt="" src="http://pds11.egloos.com/pds/200905/04/57/b0097657_49fea5ca5a14e.jpg" width="500" height="4714.28571429" onclick="Control.Modal.openDialog(this, event, 'http://pds11.egloos.com/pds/200905/04/57/b0097657_49fea5ca5a14e.jpg');" /></div>			 ]]> 
		</description>
		<category>자료링크</category>

		<comments>http://cswq327.egloos.com/4339072#comments</comments>
		<pubDate>Mon, 04 May 2009 08:22:47 GMT</pubDate>
		<dc:creator>넘버원가드</dc:creator>
	</item>
	<item>
		<title><![CDATA[ 9. [새로운 시작] ]]> </title>
		<link>http://cswq327.egloos.com/4338979</link>
		<guid>http://cswq327.egloos.com/4338979</guid>
		<description>
			<![CDATA[ 
  스키닝을 구현한 첫날 잠을 이룰 수 없었다.<br>내손으로 직접 정말 오랜시간 알고 싶었던 캐릭터 에니메이션을 구현해서 너무 흥분됐다.<br><br>하지만 이게 끝이 아니다. 이제 캐릭터 에니메이션의 기본을 겨우 한것이었다.<br>아직 할 것이 너무 많다.<br>에니메이션 블랜딩이나 ik체인 도 구현해봐야 하고 가장 중요한 에니메이션 제어도 해야한다.<br>에니메이션 콜백함수를 쓰면 된다 하는데 공부를 다시 시작해야겠다.<br><br>포기하지 않고 끝까지 한 내가 자랑스럽다. <br><br>지금까지의 내용이 틀렸거나 부족하거나 궁금한 점이 있다면 덧글을 달아주세요.<br>제가 아는 것에 한해 최대한 답변을 드리겠습니다.<br><br>			 ]]> 
		</description>
		<category>윤선생 캐릭터교실</category>

		<comments>http://cswq327.egloos.com/4338979#comments</comments>
		<pubDate>Mon, 04 May 2009 07:30:19 GMT</pubDate>
		<dc:creator>넘버원가드</dc:creator>
	</item>
	<item>
		<title><![CDATA[ 8. [Skinning02] ]]> </title>
		<link>http://cswq327.egloos.com/4338966</link>
		<guid>http://cswq327.egloos.com/4338966</guid>
		<description>
			<![CDATA[ 
  <p>#define NUM_WVERTEX 4<br></p><p>struct sSkinData<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;&nbsp;NumWVertexs;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;가중치 개수<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;float&nbsp;Weight[NUM_WVERTEX];&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 가중치<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cFrame* pBone[NUM_WVERTEX];&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 본<br>};<br><br>하나의 Vertex가 가지고 있는 가중치 정보다.<br>최대 4개의 본에 영향을 받고, 각각의 본에 대한 가중치값을 가지고 있다.<br><br>SkinData를 적용시키는 함수를 살펴보자<br><br>void cModel::ApplySkinData()<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;m_pRoot-&gt;ApplySkinData();<br>}<br><br>// 스키닝 데이터 적용<br>void cFrame::ApplySkinData()<br>{<br>&nbsp;int NumSkinData = m_vecSkinList.size();</p><p>&nbsp;</p><p>&nbsp;if(NumSkinData &gt; 0)<br>&nbsp;&nbsp;CalcWeight();</p><p>&nbsp;</p><p>&nbsp;if(m_pChild)<br>&nbsp;&nbsp;m_pChild-&gt;ApplySkinData();</p><p>&nbsp;</p><p>&nbsp;if(m_pNext)<br>&nbsp;&nbsp;m_pNext-&gt;ApplySkinData();</p><p><br>}<br><br>간단하다 이게 전부다. 루트노드로터 자식, 형제노드를 내려가면서 재귀함수를 <br>호출하는 것이다. 다만 이 노드가 SkinData가 있는 Mesh노드일경우에만 한한다.<br>이렇게 되면 쓸데없는 BoneNode들도 일단 트리를 타는 단점이 있지만 옛날 코드라<br>일단 넣어놨다.<br><br>CalWeight()라는 함수의 내부를 보자. <br>지금 이 방식은 Skinning의 세가지 방법. 즉, 소프트웨어적 방식, 메트릭스 팔레트 사용,<br>정점셰이더 방식 중 소프트웨어적 방식을 사용했다.<br><br>&nbsp;D3DXVECTOR3 vPos;<br>&nbsp;D3DXVECTOR3 vTemp;<br></p><p>&nbsp;for(int i = 0; i &lt; NumSkinData; ++i)&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;해당 Mesh 노드의 Vertex개수와 같은 크기<br>&nbsp;{<br><br>&nbsp;&nbsp;vPos = m_pMesh-&gt;m_pDumpMesh-&gt;m_vecPos[i];<br>&nbsp;&nbsp;&nbsp;int NumBlend = m_vecSkinList[i]-&gt;NumWVertexs;<br><br>&nbsp;&nbsp;//&nbsp;영향을 주는&nbsp;Bone의 개수<br>&nbsp;&nbsp;// 개수가 1개라면 가중치는 1.0f&nbsp;이다.</p><p>&nbsp;&nbsp;for(int k = 0; k &lt; NumBlend; ++k)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cFrame* pBone&nbsp;= m_vecSkinList[i]-&gt;pBone[k];&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;float&nbsp; weight&nbsp;= m_vecSkinList[i]-&gt;Weight[k];</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(pBone)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;D3DXVec3TransformCoord(&amp;vTemp, &amp;vPos,&nbsp; &amp;pBone-&gt;m_OffsetTM);&nbsp; --&gt; 1<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;D3DXVec3TransformCoord(&amp;vTemp, &amp;vTemp, &amp;pBone-&gt;m_WorldTM); --&gt; 2</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;globalPosList[i] += (vTemp * weight);&nbsp;&nbsp;&nbsp;--&gt; 3</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;}<br>&nbsp;}<br><br>Vertex를 돌면서 각각의 버텍스에 가중치 계산을 해서 결국 최종 버텍스 위치를 구해주면<br>되는것이다.<br><br>1) Vertex를 Bone의 에니메이션되지 않은 Offset위치로 옮겨주는(살을 뼈에 붙인다는 의미로 보면 되겠다) 개념<br>2) Vertex에 에니메이션 된 최종 WorldTM을 계산해준다. 즉 Bone의 최종 위치로 이동<br>3) 하지만 가중치만큼을 곱해줘 그 본의 가중치 만큼을 곱해줘 그만큼만 영향을 받게 해준다.<br>4) 이것을 가중치개수만큼 반복해 누적시켜 최종 Vertex의 위치를 구해준다.<br><br>구현 당시 꽤 어려웠던 개념이었던 것에 비해 식이 간단하다. 하지만 이해하지 못하고 쓰는 지식은<br>죽은 지식이므로 꼭 확실이 이해하고 쓰는게 좋다.</p>			 ]]> 
		</description>
		<category>윤선생 캐릭터교실</category>

		<comments>http://cswq327.egloos.com/4338966#comments</comments>
		<pubDate>Mon, 04 May 2009 07:23:21 GMT</pubDate>
		<dc:creator>넘버원가드</dc:creator>
	</item>
	<item>
		<title><![CDATA[ 7. [Skinning01] ]]> </title>
		<link>http://cswq327.egloos.com/4338915</link>
		<guid>http://cswq327.egloos.com/4338915</guid>
		<description>
			<![CDATA[ 
  <p>메시 노드의 modifier를 보면 메시가 Skin인지 Physique인지 구별할 수가 있다.<br>Skin, Physique 에 상관없이 일단 이런 정보가 있다면 이 메시를 이루는 버텍스들은<br>가중치를 가지고 있는 버텍스들이라는것을 알 수 있다.<br><br>ASE로 익스포트 하면 이런 Skin이나 Physique은 추출되지 않는다. 따라서 ASE를 <br>수정하면 쉽게 이런 정보들을 추출할 수 있다.<br>(3D Data Export&nbsp;나 인터넷 자료들을 뒤져보면 쉽게 찾을 수 있다.)<br><br>추출된 Skin&nbsp;Data의 예로,&nbsp; 일부분의 예를 든다면<br><br>&nbsp; .<br>&nbsp; .<br>&nbsp; .<br>&nbsp;*NOBLEND 13 "Bip01 Spine1"<br>&nbsp;*NOBLEND 14 "Bip01 Spine1"<br>&nbsp;*NOBLEND 15 "Bip01 Spine1"<br>&nbsp;*BLEND 16 {<br>&nbsp;&nbsp;*NUM_BLEND 3<br>&nbsp;&nbsp;*WEIGHT_NODE 0 0.416667 "Bip01 L Clavicle"<br>&nbsp;&nbsp;*WEIGHT_NODE 1 0.416667 "Bip01 L UpperArm"<br>&nbsp;&nbsp;*WEIGHT_NODE 2 0.166667 "Bip01 Spine1"<br>&nbsp; }<br>&nbsp;*BLEND 17 {<br>&nbsp;&nbsp;*NUM_BLEND 3<br>&nbsp;&nbsp;*WEIGHT_NODE 0 0.416667 "Bip01 L Clavicle"<br>&nbsp;&nbsp;*WEIGHT_NODE 1 0.416667 "Bip01 L UpperArm"<br>&nbsp;&nbsp;*WEIGHT_NODE 2 0.166667 "Bip01 Spine1"<br>&nbsp; }<br>&nbsp;&nbsp;.<br>&nbsp; .<br>&nbsp; .<br><br>vertex 13, 14, 15번은 Bip01 Spine1이란 본에 가중치 1.0f를 받고 있단 뜻이고,<br>vertex17번은 3개의 본에 영향을 받는단 뜻인데,<br>Bip01 L Clavicle이란 본에 0.416667만큼 가중치를 받고<br>Bip01 L UpperArm에 0.416667을,<br>Bip01 Spine1에 0.16667을 받는다는 뜻이다.<br><br>가중치는 보통 최대 4개의 본에 국한되도록 하는것이 나을 것이다.<br>아는 분의 말로는 인간체형을 나타내는것은 보통 가중치를 최대 2만 줘도 가능하다는<br>얘기를 들었다.<br><br>해골책의 망치는 남자는 가중치가 7이상이나 되었는데, 흠... 왜 그랬는지는 지금도<br>이해가 잘 안간다. 아무튼 다 적용시켜줘야지만 제대로 에니메이션이 나왔다.<br><br>이제 코드로 나타내 보자.<br><br></p>			 ]]> 
		</description>
		<category>윤선생 캐릭터교실</category>

		<comments>http://cswq327.egloos.com/4338915#comments</comments>
		<pubDate>Mon, 04 May 2009 07:02:31 GMT</pubDate>
		<dc:creator>넘버원가드</dc:creator>
	</item>
	<item>
		<title><![CDATA[ 6. [Bone Node들의 Animation02] ]]> </title>
		<link>http://cswq327.egloos.com/4338892</link>
		<guid>http://cswq327.egloos.com/4338892</guid>
		<description>
			<![CDATA[ 
  <p>실제 에니메이션 코드를 살펴보자.<br><br>// 에니메이션 TM 계산하기<br>void cTMAnimation::Animate( int time )<br>{<br>&nbsp;if(NULL == m_pFrame) <br>&nbsp;&nbsp;return;</p><p>&nbsp;// 초기 부모 노드와의 상대적인 위치를 나타내는 m_OriginTM 을 얻는다.<br>&nbsp;D3DXMATRIX mat = m_pFrame-&gt;m_OriginTM;<br></p><p>&nbsp;if(m_RotAnim)&nbsp; <br>&nbsp;{<br>&nbsp;&nbsp;D3DXQUATERNION rot = m_RotAnim-&gt;GetSLerpValueByTime(time);</p><p>&nbsp;&nbsp;D3DXMATRIX m;<br>&nbsp;&nbsp;D3DXMatrixRotationQuaternion(&amp;m, &amp;rot);</p><p>&nbsp;&nbsp;mat._11 = m._11,&nbsp;mat._12 = m._12,&nbsp;mat._13 = m._13;&nbsp; <br>&nbsp;&nbsp;mat._21 = m._21,&nbsp;mat._22 = m._22,&nbsp;mat._23 = m._23;<br>&nbsp;&nbsp;mat._31 = m._31,&nbsp;mat._32 = m._32,&nbsp;mat._33 = m._33;<br>&nbsp;}</p><p>&nbsp;if(m_PosAnim)<br>&nbsp;{<br>&nbsp;&nbsp;D3DXVECTOR3 pos = m_PosAnim-&gt;GetLerpValueByTime(time);</p><p>&nbsp;&nbsp;mat._41 = pos.x, <br>&nbsp;&nbsp;mat._42 = pos.y,<br>&nbsp;&nbsp;mat._43 = pos.z;&nbsp;<br>&nbsp;}</p><p>&nbsp;// 에니메이션 된 TM 값을 m_LocalTM 에 저장<br>&nbsp;m_pFrame-&gt;m_LocalTM = mat;<br>}<br><br>해당 에니메이션 트랙이 없을 경우를 위해 AnimationTM에 OriginTM을 일단 넣어준다.<br>Pos트랙이 있을 경우 보간하여 얻은 위치벡터를 AnimationTM의 41,42,43에 넣어준다.<br>Rot트랙이 있을경우도 같은 방법으로 11~33까지 넣어준다.<br><br>왜 행렬의 위의 인자에 넣어주는지는 다들 알 것이다.<br>다만 Pos의 경우는 Lerp보간을, Rot의 경우에는 SLerp 보간을 해주는 차이가 있을 뿐이다.<br><br>해서 우리가 최종적으로 구하는 WorldTM을 구해보면 <br>WordTM = LocalTM(Animation된 LocalTM) * ParentTM <br>이 된다.<br><br>보통 루트는 단위행렬이 곧 월드 행렬이 되므로<br><br>void Animate()<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;D3DXMATRIX m;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;D3DXMatrixIdentity(&amp;m);</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;m_pRoot-&gt;SetupWorldMatrix(&amp;m);<br>}<br><br>이고 내부의 함수를 들어다 보면 재귀호출을 하는 함수인걸 알수 있다.<br><br>void cFrame::SetupWorldMatrix( const D3DXMATRIX* pParentWorldTM )<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;D3DXMatrixMultiply( &amp;m_WorldTM, &amp;m_LocalTM, pParentWorldTM );</p><p>&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;if(m_pChild)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;m_pChild-&gt;SetupWorldMatrix(&amp;m_WorldTM);</p><p>&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;if(m_pNext)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;m_pNext-&gt;SetupWorldMatrix(pParentWorldTM);<br>}<br><br>이렇게 된다. 루트부터 시작해서 자식노드, 형제 노드를 거쳐 모든 BoneNode들의<br>WorldTM이 계산되게 된다.<br><br><br><br></p>			 ]]> 
		</description>
		<category>윤선생 캐릭터교실</category>

		<comments>http://cswq327.egloos.com/4338892#comments</comments>
		<pubDate>Mon, 04 May 2009 06:47:38 GMT</pubDate>
		<dc:creator>넘버원가드</dc:creator>
	</item>
	<item>
		<title><![CDATA[ 5. [Bone Node들의 Animation01] ]]> </title>
		<link>http://cswq327.egloos.com/4338788</link>
		<guid>http://cswq327.egloos.com/4338788</guid>
		<description>
			<![CDATA[ 
  <p>이제 Bone Node들을 에니메이션 시키자.<br>간단하게 에니메이션 시키는 과정을 살펴보자.<br><br>*SCENE {<br>&nbsp;*SCENE_FILENAME "Idle_Russian blue.max"<br>&nbsp;*SCENE_FIRSTFRAME 0<br>&nbsp;*SCENE_LASTFRAME 50<br>&nbsp;*SCENE_FRAMESPEED 30<br>&nbsp;*SCENE_TICKSPERFRAME 160<br>}<br><br>여기서 Max의 프레임과 시간에 대해 함 살펴보자.<br><br>1초에 30프레임 (기본 비디오 프레임 레이트) 1초 4800 tick<br>1프레임은 160tick !!&nbsp; ( &lt;-- 자료를 찾아보니 거의 고정인것 같아 보였다. )<br><br>예를 들어 CONTROL_POS_SAMPLE 480 20.f 1,24f, 3.f 라면<br>이건 몇번째 프레임일까.. 480/160 = 3. 즉 3프레임인걸 알수 있다.<br><br>실제 익스포트 해보면 tick으로 나오는데 이것을 게임에 쓸수 있도록 시간 개념을로<br>바꿔야 한다.<br><br>실제 코드중 일부분이다.<br>pos.time = int((float)GetToken_Int() / (m_TickPerFrame * m_FrameSpeed) * 1000.0f);<br><br>일단 몇 프레임인지 구하고 거기에 1프레임이 실제로 몇 ms인지 나와있으니 그것을 곱하면<br>몇 ms인지 나온다. 거기에 s로 바꾸기 위해 1000.f를 곱하면 실제 s(초)로 바꾸면 된다.<br><br><br>예로 하나의 익스포트된 Bone 노드를 살펴보자.<br>부모 노드 이름이 없는것으로 봐서 이것은 루트본인걸 알아보는 센스를 발휘해보자.<br><br>*GEOM {<br>&nbsp;*NODE_NAME "Bip01"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// 본 이름<br>&nbsp;*NODE_CLASS "Bone"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 이 노드가 Bone 인것을 알려준다.<br>&nbsp;*NODE_TM {<br>&nbsp;&nbsp;*NODE_NAME "Bip01"<br>&nbsp;&nbsp;*TM0 0.1986 -0.9762 -0.0872&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// 실제로 필요한 TM0, TM1, TM2, TM3<br>&nbsp;&nbsp;*TM1 0.9799 0.1994 0.0000&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;*TM2 0.0174 -0.0854 0.9962<br>&nbsp;&nbsp;*TM3 -1.2106 8.1724 92.0071<br>&nbsp;}<br>&nbsp;<br>// 에니메이션 트랙들<br>&nbsp;*TM_ANIMATION {<br>&nbsp;&nbsp;*NODE_NAME "Bip01"<br>&nbsp;&nbsp;*CONTROL_POS_TRACK {<br>&nbsp;&nbsp;&nbsp;*CONTROL_POS_SAMPLE 0&nbsp;-1.2106 8.1724 92.0071<br>&nbsp;&nbsp;&nbsp;*CONTROL_POS_SAMPLE 800&nbsp;-1.6496 9.1877 91.3804<br>&nbsp;&nbsp;&nbsp;*CONTROL_POS_SAMPLE 1600&nbsp;-1.9490 10.0299 90.9083<br>&nbsp;&nbsp;&nbsp;*CONTROL_POS_SAMPLE 2400&nbsp;-1.4094 9.9863 91.3469<br>&nbsp;&nbsp;&nbsp;*CONTROL_POS_SAMPLE 3200&nbsp;-0.6750 8.9717 91.9871<br>&nbsp;&nbsp;&nbsp;*CONTROL_POS_SAMPLE 4000&nbsp;-0.2162 7.3750 91.4795<br>&nbsp;&nbsp;&nbsp;*CONTROL_POS_SAMPLE 4800&nbsp;0.2625 6.1716 90.8651<br>&nbsp;&nbsp;&nbsp;*CONTROL_POS_SAMPLE 5600&nbsp;0.5930 5.8373 90.9230<br>&nbsp;&nbsp;&nbsp;*CONTROL_POS_SAMPLE 6400&nbsp;0.1326 6.4322 91.2873<br>&nbsp;&nbsp;&nbsp;*CONTROL_POS_SAMPLE 7200&nbsp;-0.5390 7.3023 91.6473<br>&nbsp;&nbsp;&nbsp;*CONTROL_POS_SAMPLE 8000&nbsp;-1.2106 8.1724 92.0071<br>&nbsp;&nbsp;}<br>&nbsp;&nbsp;*CONTROL_ROT_TRACK {<br>&nbsp;&nbsp;&nbsp;*CONTROL_ROT_SAMPLE 0&nbsp;-0.0436&nbsp;-0.0533&nbsp;0.9976&nbsp;1.3724<br>&nbsp;&nbsp;&nbsp;*CONTROL_ROT_SAMPLE 800&nbsp;-0.0815&nbsp;0.9827&nbsp;-0.1665&nbsp;0.0173<br>&nbsp;&nbsp;&nbsp;*CONTROL_ROT_SAMPLE 1600&nbsp;0.0283&nbsp;0.9976&nbsp;0.0627&nbsp;0.0155<br>&nbsp;&nbsp;&nbsp;*CONTROL_ROT_SAMPLE 2400&nbsp;0.3843&nbsp;0.4687&nbsp;0.7954&nbsp;0.0229<br>&nbsp;&nbsp;&nbsp;*CONTROL_ROT_SAMPLE 3200&nbsp;0.4186&nbsp;0.2556&nbsp;0.8715&nbsp;0.0317<br>&nbsp;&nbsp;&nbsp;*CONTROL_ROT_SAMPLE 4000&nbsp;0.3680&nbsp;0.3378&nbsp;0.8663&nbsp;0.0168<br>&nbsp;&nbsp;&nbsp;*CONTROL_ROT_SAMPLE 4800&nbsp;-0.5185&nbsp;0.1271&nbsp;-0.8456&nbsp;0.0297<br>&nbsp;&nbsp;&nbsp;*CONTROL_ROT_SAMPLE 5600&nbsp;-0.4866&nbsp;-0.1152&nbsp;-0.8660&nbsp;0.0361<br>&nbsp;&nbsp;&nbsp;*CONTROL_ROT_SAMPLE 6400&nbsp;-0.0742&nbsp;-0.9352&nbsp;-0.3462&nbsp;0.0166<br>&nbsp;&nbsp;&nbsp;*CONTROL_ROT_SAMPLE 7200&nbsp;0.1828&nbsp;-0.9805&nbsp;0.0720&nbsp;0.0208<br>&nbsp;&nbsp;&nbsp;*CONTROL_ROT_SAMPLE 8000&nbsp;0.1828&nbsp;-0.9805&nbsp;0.0720&nbsp;0.0208<br>&nbsp;&nbsp;}<br>&nbsp;}<br>}<br><br>위를 보면 에니메이션 트랙들이 있다. 보통 Scale이 있는 경우는 드문것 같고<br>주로 Pos와 Rotation 관련 트랙들만 있다.<br>그렇다면 이것들을 배열이나 벡터(stl)로 저장해두자. 하지만 stl의 무서움은 속도면에서 경험했기<br>때문에 배열로 저장해두길 권장한다.<br><br>우리가 에니메이션 시키는 방법은 Sampling 방식이다.<br>모든 프레임의 정보를 얻어서 에니메이션 시키는 방법이 정석이겠지만. 이는 저장할 데이터가 너무 많다.<br>그래서 몇 프레임 간격으로 샘플링(?) 즉, 일정 간격마다를 저장해 그 사이는 보간하면 되는 방법이다.<br><br>에니메이션 시킬때 인자로&nbsp;시간을 보낼것인데, 그 시간이&nbsp;어느 프레임의 사이에 얼마만큼의 위치에<br>있느냐를&nbsp;결정해서&nbsp;보간 시키는 것이 핵심이다.&nbsp;<br><br><br><br></p>			 ]]> 
		</description>
		<category>윤선생 캐릭터교실</category>

		<comments>http://cswq327.egloos.com/4338788#comments</comments>
		<pubDate>Mon, 04 May 2009 05:29:40 GMT</pubDate>
		<dc:creator>넘버원가드</dc:creator>
	</item>
	<item>
		<title><![CDATA[ 4. [오브젝트의 코드 표현] ]]> </title>
		<link>http://cswq327.egloos.com/4338670</link>
		<guid>http://cswq327.egloos.com/4338670</guid>
		<description>
			<![CDATA[ 
  <p>// 실제 제 코드<br>// Node 클래스라 하는것이 맞겠지만 xfile에서는 Frame이란 단어를 써서<br>// 그대로 따랐다. 여기서는 그냥 Node == Frame 으로 보면 된다.<br>// 차라리 Bone노드 Mesh노드로 구별해 놓지 않고 enum으로 해놓았기 때문에<br>// 필요없는 변수들이 많이 있지만 공부하는 입장에서는 괜찮은것 같아서<br>// Frame 하나로 통합했다.<br><br>class cFrame<br>{<br>public:<br>&nbsp;<br>&nbsp;// 노드가 Bone인지 Mesh인지를 구별하기 위한 enum변수<br>&nbsp;// 익스포트할때 미리 노드가 Bone인지 Mesh인지를 구별해서<br>&nbsp;// 뽑았기 때문에 구별은 쉽게 되게 해놓았다.</p><p>&nbsp;enum FrameType { TYPE_NONE, TYPE_MESH, TYPE_BONE,};<br>&nbsp;FrameType m_Type;<br><br>&nbsp;// 노드 이름<br>&nbsp;char&nbsp;m_Name[MAX_PATH];<br>&nbsp;// 부모노드의 이름<br>&nbsp;char&nbsp;&nbsp;&nbsp; m_ParentName[MAX_PATH];</p><p><br>&nbsp;// 이 노드가 본루트인지 구별해놓기 위한 bool 변수</p><p>&nbsp;bool&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; m_IsBoneRoot;<br><br>&nbsp;// 익스포터를 ASE를 수정한 것이기 때문에 실제 익스포트되어 나오는 행렬값은<br>&nbsp;// 이미 부모 행렬을 곱한 World행렬이 익스포트되어진다.<br>&nbsp;// 에니메이션 할 경우 오프셋 행렬이 필요하기 때문에 <br>&nbsp;// 부모 행렬의 역행렬을 구해 노드의 Offset행렬을 미리 구해놓는다.</p><p>&nbsp;<br>&nbsp;D3DXMATRIX m_OffsetTM;&nbsp;&nbsp;// nodeTM의 역행렬<br>&nbsp;D3DXMATRIX m_LocalTM;&nbsp;&nbsp;// 부모TM과 상대적인 위치(에니메이션TM계산된거)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //&nbsp;일단 Animation행렬이라고 보면 되겠다.<br>&nbsp;D3DXMATRIX m_WorldTM;&nbsp;&nbsp;// 최종 변환 TM(가변)&nbsp;<br></p><p>&nbsp;cMesh*&nbsp;m_pMesh;&nbsp;&nbsp;&nbsp; // 메시(메시노드가 아닐 경우 NULL이다.)<br></p><p>&nbsp;cFrame* m_pParent;&nbsp;// 부모 프레임&nbsp;포인터<br>&nbsp;cFrame* m_pPrev;<br>&nbsp;cFrame* m_pNext;&nbsp;// 형제 프레임<br>&nbsp;cFrame* m_pChild;&nbsp;// 자식 프레임&nbsp;<br><br>&nbsp;// 마땅한 더미 노드가 없어서 손에서 나가는 마법이나 용에서 나가는 브레스를 위해<br>&nbsp;// 비슷한 위치의 본노드를 찾아야했다.</p><p>&nbsp;bool&nbsp;&nbsp;&nbsp; m_bRightHand;&nbsp;// 이 노드가 오른손 노드인가?<br>&nbsp;bool&nbsp;&nbsp;&nbsp; m_bLeftHand;&nbsp;&nbsp; // 이 노드가 왼손 노드인가?&nbsp;<br>&nbsp;bool&nbsp;&nbsp;&nbsp; m_bHead;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// 이 노드가&nbsp;머리 노드인가?<br></p><p>&nbsp;// 스키닝 정보<br>&nbsp;// 다른 Bone 프레임등의 정보에 접근해야 하기 때문에<br>&nbsp;// cMesh가 아닌 cFrame에 있는 것이 편할거 같다.<br><br>&nbsp;// Skinning 모델일 경우 당연히 Mesh Node에 있는 스킨데이터<br>&nbsp;// 당연히 정점의 개수와 같은 크기가 나와야 할 것이다.</p><p>&nbsp;int m_nNumSkinData;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;sSkinData* m_vecSkinList;<br></p><p>public:<br>&nbsp;cFrame(void);<br>&nbsp;~cFrame(void);</p><p>&nbsp;HRESULT Destroy();<br></p><p>&nbsp;// 각 스킨데이터들이 본 이름만 가지고 있기 때문에 이름으로 본을 찾으면<br>&nbsp;// 부하가 많이 걸린다. 그래서 본 포인터를 연결시켜준다.<br>&nbsp;// 이 프레임이&nbsp;루트 프레임일 경우에&nbsp;쓰는 함수이다.<br>&nbsp;void LinkBoneToSkinData();<br>&nbsp;<br>&nbsp;// 스킨 데이터 적용(가중치 적용)<br>&nbsp;void CalcWeight();<br>&nbsp;void ApplySkinData();<br></p><p>&nbsp;void AttachSibling(cFrame* pFrame);<br>&nbsp;void AttachChild(cFrame* pFrame);</p><p>&nbsp;cFrame* FindRoot();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// 루트 프레임 찾기<br>&nbsp;cFrame* FindFrame(char* strFrameName);&nbsp;// 현재 프레임 밑으로 이름으로 프레임 찾기<br>&nbsp;cFrame* FindLHandFrame();<br>&nbsp;cFrame* FindRHandFrame();<br>&nbsp;cFrame* FindHeadFrame();<br></p><p>&nbsp;void SetupWorldMatrix(const D3DXMATRIX* pParentWorldTM);<br>&nbsp;void Update();<br>&nbsp;void Render();</p><p><br>};<br><br>자 이것이 앞서 본 schematic view에서 본 노드들을 코드화 한 것이다.<br>그렇다면 모델은 무엇만 가지고 있음 되는가 하면<br><br>class cModel<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;protected:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cFrame* m_pRootFrame;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;..........이하 생략 .....<br>};<br><br>그렇다. m_pRootFrame(루트노드)만 가지고 있으면 되는것이다.<br>트리구조로 노드들을 구성해놓았기 때문에 모델은 루트노드의 포인터만<br>가지고 있음 되는 것이다.</p>			 ]]> 
		</description>
		<category>윤선생 캐릭터교실</category>

		<comments>http://cswq327.egloos.com/4338670#comments</comments>
		<pubDate>Mon, 04 May 2009 04:24:33 GMT</pubDate>
		<dc:creator>넘버원가드</dc:creator>
	</item>
	<item>
		<title><![CDATA[ 3. [모델(오브젝트)의 구조] ]]> </title>
		<link>http://cswq327.egloos.com/4338638</link>
		<guid>http://cswq327.egloos.com/4338638</guid>
		<description>
			<![CDATA[ 
  맥스에서 모델이 어떻게 구성되어졌는지 schematic viewer로 살펴보자.<br><div style="text-align:center"><img class="image_mid" border="0" onmouseover="this.style.cursor='pointer'" alt="" src="http://pds11.egloos.com/pds/200905/04/57/b0097657_49fe662c41f16.jpg" width="500" height="312.5" onclick="Control.Modal.openDialog(this, event, 'http://pds11.egloos.com/pds/200905/04/57/b0097657_49fe662c41f16.jpg');" /></div><br>간단하게 보면 Tree구조로 이루어진 Node들의 모임이다.<br>다만 이 Node들이 어떤 정보를 포함하고 있느냐에 따라 구분된다.<br><br>그림을 보면 노드는 크게 Mesh Node와 Bone Node로 나누어져 있다.<br>네개의 파란색 노드들이 Mesh Node이고 하얀색의 노드들이 Bone Node들이다.<br>Bone노드를 보면 부모.자식.형제를 가진 트리구조로 구성되어진 것을 확인할 수 있다.<br><br>Mesh Node는 모델을 이루고 있는 vertex들의 모임이다.<br>위의 경우 전체 몸, 칼2개, 치마 이렇게 4개의 Mesh Node 들이 있다.<br>Mesh Node를 선택하고 Modifier를 보면 Skin인지 Physique 인지, Editable Mesh인지등을<br>알 수 있다.<br><br>Bone Node의 경우 각각의 위치를 나타내고 있는 행렬(Matrix) 정보를 가진 노드이다.<br>에니메이션이라는 것은 결국 이 Bone의&nbsp;행렬이 변하는 것이고, Mesh Node의 각각의 버텍스들이<br>적절한(?) Bone에 붙는 것이라 보면 되겠다.<br><br>이제 이것들을 코드로 나타내보자<br>			 ]]> 
		</description>
		<category>윤선생 캐릭터교실</category>

		<comments>http://cswq327.egloos.com/4338638#comments</comments>
		<pubDate>Mon, 04 May 2009 04:04:59 GMT</pubDate>
		<dc:creator>넘버원가드</dc:creator>
	</item>
</channel>
</rss>
