ZNode를 맥스로부터 읽어들인 모든 오브젝트들의 최상위 클래스로 두고, 오브젝트를 크게 두가지로 구분한 것이야,
뼈대는 ZBone
메시는 ZMesh
나중에 추가하게 될 스키닝 메시를 생각해서 ZSkinnedMesh 클래스 추가
애니메이션을 위한 ZTrack이라는 클래스도 있는데, 요고는 다음에 구현할거구요
ZNodeMgr 클래스는 ZNode를 관리하는데 사용할 클래스다
실제구현 - ZNodeMgr
제일 먼저 볼 클래스,
이 클래스는 맥스로 만들어진 XML 파일을 읽은 데이터인 ZCParsedData형을 받아 실제 출력 가능한 형태로 변환하는 역할을 한다
대부분 실제적인 데이터 변환은 각각의 ZNode, ZBone, ZMesh등의 클래스에서 이루어지고, ZNodeMgr은 ZObjectInfo와 ZMaterial 등의 전역 데이터만을 읽어들인 뒤에 각각의 ZCMesh 형들을 어떤 클래스의 객체로 생성해야 적합한가에 대한 판단을 한다.
class ZNodeMgr
{
protected:
ZObjectInfo m_info; /// 현재 노드전체에 대한 정보
vector<ZMaterial> m_materials; /// 재질값 배열
vector<ZNode*> m_nodes; /// 노드들
LPDIRECT3DDEVICE9 m_pDev; /// D3D디바이스
D3DXMATRIXA16 m_matTM; /// 자식 노드 전체에 적용될 TM
public:
ZNodeMgr( LPDIRECT3DDEVICE9 pDev, ZCParsedData* pData );
~ZNodeMgr();
/// TM을 얻어온다
D3DXMATRIXA16* GetTM() { &m_matTM; }
/// TM을 셋팅한다
void SetTM( D3DXMATRIXA16* pTM ) { m_matTM = *pTM; }
/// 애니메이션 행렬을 만든다
int Animate( float fFrame );
/// 노드전체를 그린다.
int Draw();
};
vector<ZNode*> m_nodes로 선언된 것이 이제부터 관리하게 될 전체 오브젝트 배열이다.
외부에서 접근할 수 있는 함수는 생성자를 제외하면 SetTM(), GetTM(), Animate(), Draw()의 4가지 함수 뿐이다
그럼 이게 어떻게 구현되었는지 보자
먼저 ZNodeMgr의 생성자를 보자
ZNodeMgr::ZNodeMgr( LPDIRECT3DDEVICE9 pDev, ZCParsedData* pData )
{
int i;
m_pDev = pDev;
D3DXMatrixIdentity( &m_matTM );
// copy info
m_info.nObjectCount = pData->m_info.nObjectCount;
m_info.nSkinType = pData->m_info.nSkinType;
m_info.nMeshCount = pData->m_info.nMeshCount;
m_info.fAnimationStart = pData->m_info.fAnimationStart;
m_info.fAnimationEnd = pData->m_info.fAnimationEnd;
m_info.nKeyType = pData->m_info.nKeyType;
m_info.BoneTable = pData->m_info.BoneTable;
m_info.strObjectNameTable = pData->m_info.strObjectNameTable;
// copy materials
char drive[_MAX_DRIVE];
char dir[_MAX_DIR];
char fname[_MAX_FNAME];
char ext[_MAX_EXT];
string str;
int size = pData->m_materialTable.size();
m_materials.resize( size );
for( i = 0 ; i < size ; i++ )
{
// 재질의 확산광 속성 설정
D3DCOLORVALUE diffuse = { pData->m_materialTable[i].diffuse.r, pData->m_materialTable[i].diffuse.g, pData->m_materialTable[i].diffuse.b, 0 };
m_materials[i].material.Diffuse = diffuse;
// 재질의 환경광 속성 설정
D3DCOLORVALUE ambient = { pData->m_materialTable[i].ambient.r, pData->m_materialTable[i].ambient.g, pData->m_materialTable[i].ambient.b, 0 };
m_materials[i].material.Ambient = ambient;
// 재질의 반사광 속성 설정
D3DCOLORVALUE specular = { pData->m_materialTable[i].specular.r, pData->m_materialTable[i].specular.g, pData->m_materialTable[i].specular.b, 0 };
m_materials[i].material.Specular = specular;
// 재질의 발산광 속성 설정
D3DCOLORVALUE emissive = { pData->m_materialTable[i].emissive.r, pData->m_materialTable[i].emissive.g, pData->m_materialTable[i].emissive.b, 0 };
m_materials[i].material.Emissive = emissive;
// 반사광의 제곱계수
m_materials[i].material.Power = pData->m_materialTable[i].power;
// 불투명도 값
m_materials[i].opacity = pData->m_materialTable[i].opacity;
// 확산맵 텍스처
m_materials[i].pTex[0] = NULL;
_splitpath( pData->m_materialTable[i].strMapDiffuse.c_str(), drive, dir, fname, ext ); str = fname; str += ext;
D3DXCreateTextureFromFile( pDev, str.c_str(), &m_materials[i].pTex[0] );
// 법선맵 텍스처
m_materials[i].pTex[1] = NULL;
_splitpath( pData->m_materialTable[i].strMapBump.c_str(), drive, dir, fname, ext ); str = fname; str += ext;
D3DXCreateTextureFromFile( pDev, str.c_str(), &m_materials[i].pTex[1] );
// 반사맵 텍스처
m_materials[i].pTex[2] = NULL;
_splitpath( pData->m_materialTable[i].strMapSpecular.c_str(), drive, dir, fname, ext ); str = fname; str += ext;
D3DXCreateTextureFromFile( pDev, str.c_str(), &m_materials[i].pTex[2] );
// 그외의 추가적인 텍스처
m_materials[i].pTex[3] = NULL;
_splitpath( pData->m_materialTable[i].strMapDisplace.c_str(), drive, dir, fname, ext ); str = fname; str += ext;
D3DXCreateTextureFromFile( pDev, str.c_str(), &m_materials[i].pTex[3] );
}
// copy meshes
list<ZCMesh*>::iterator it;
ZNode* pNode;
size = pData->m_meshList.size();
// m_nodes.resize( size );
for( i = 0, it = pData->m_meshList.begin() ; it != pData->m_meshList.end() ; i++, it++ )
{
// 부모가 없는 노드는 0번노드를 부모로 한다.
if( (*it)->m_nParentID == -1 )
(*it)->m_nParentID = 0;
// Bone이나 Biped라면 ZBone으로 생성
if( !( (*it)->m_strNodeType.compare( "BoneGeometry" ) ) ||
!( (*it)->m_strNodeType.compare( "Biped_Object" ) ) ||
!( (*it)->m_strNodeType.compare( "Bone" ) ) )
{
pNode = (ZNode*)(new ZBone( pDev, *it ));
}
else // Editable_Mesh라면 ZMesh로 생성
if( !( (*it)->m_strNodeType.compare( "Editable_mesh" ) ) )
{
if( (*it)->m_isSkinned ) // Skin이 있으면 ZSkinnedMesh로 생성
pNode = (ZNode*)(new ZSkinnedMesh( pDev, *it ));
else // Skin이 없으면 ZRigidMesh로 생성
pNode = (ZNode*)(new ZRigidMesh( pDev, *it ));
}
else // 이것도 저것도 아니면 그냥 ZNode로 생성
pNode = new ZNode( pDev, *it );
m_nodes.push_back( pNode );
}
}
'Graphics > DirectX' 카테고리의 다른 글
Direct X - 키 프레임 애니메이션 (0) | 2014.10.09 |
---|---|
Direct X - 계층구조 2 (0) | 2014.09.30 |
Direct X - 스크립트와 XML파서 (0) | 2014.09.05 |
Direct X - 애니메이션 기법 (0) | 2014.09.03 |
Direct X - 균열 방지 (0) | 2014.08.27 |