Example #1
0
//Xファイルからの3Dモデルデータをロード  (詳細版、アニメーション制御可能)
HRESULT MeshManager::LoadAnimeMeshFromX(DxAnimeMesh *mesh,const string& fName,const string& path)
{
	//読み込み用アニメーションコントローラ
	LPD3DXANIMATIONCONTROLLER pAnimControllerTmp = NULL;

	string str = path + fName;

	//Xファイルからフレーム階層とアニメーション情報をロード
  if(FAILED(D3DXLoadMeshHierarchyFromX(
		str.c_str(),
		D3DXMESH_MANAGED,
		this->dev,
		this->hierarchy,
		NULL,
		&mesh->pFrameRoot,
		&pAnimControllerTmp)))
	{
		return E_FAIL;
	}

	//ファイル名の設置
	mesh->file_name=fName;

	if(FAILED(LoadAnimeFromX(pAnimControllerTmp,mesh,fName,path)))
	{
		return E_FAIL;
	}
	SAFE_RELEASE(pAnimControllerTmp);
	return S_OK;
}
Example #2
0
bool XEnitity::Load(const std::string FileName)
{
	m_FileName = FileName;

	MeshAllocation* pMeshAlloc = new MeshAllocation;

	HRESULT hr = D3DXLoadMeshHierarchyFromX(m_FileName.c_str(),
		D3DXMESH_MANAGED,
		m_d3ddev, 
		pMeshAlloc,
		NULL,
		&m_pTopFrame,
		&m_pAnimCtrl);

	SAFE_DELETE(pMeshAlloc);

	if(FAILED(hr))	return false;

	m_NumAnimationSets = m_pAnimCtrl->GetNumAnimationSets();

	if(m_pTopFrame)
	{
		SetupBoneMatrices((CUSTOM_FRAME*) m_pTopFrame);

		m_pBoneMatrices = new D3DXMATRIX[m_MaxBones];
		memset(m_pBoneMatrices, 0, sizeof(D3DXMATRIX)*m_MaxBones);
	}

	return true;
}
Example #3
0
//--------------------------------------------------------------------------------------
// This function loads the mesh and LDPRT data.  It also centers and optimizes the 
// mesh for the graphics card's vertex cache.
//--------------------------------------------------------------------------------------
HRESULT LoadLDPRTData( IDirect3DDevice9* pd3dDevice, WCHAR* strFilePrefixIn )
{
    WCHAR str[MAX_PATH];
    WCHAR strFileName[MAX_PATH];
    WCHAR strFilePrefix[MAX_PATH];
    HRESULT hr;

    // Load the mesh with D3DX and get back a ID3DXMesh*.  For this
    // sample we'll ignore the X file's embedded materials since we know 
    // exactly the model we're loading.  See the mesh samples such as
    // "OptimizedMesh" for a more generic mesh loading example.
    swprintf_s( strFilePrefix, MAX_PATH, TEXT( "%s" ), strFilePrefixIn ); strFilePrefix[MAX_PATH - 1] = 0;
    swprintf_s( strFileName, MAX_PATH, TEXT( "%s.x" ), strFilePrefix ); strFileName[MAX_PATH - 1] = 0;
    V_RETURN( DXUTFindDXSDKMediaFileCch( str, MAX_PATH, strFileName ) );

    CAllocateHierarchy Alloc;

    // Delete existing resources
    if( g_pFrameRoot )
    {
        D3DXFrameDestroy( g_pFrameRoot, &Alloc );
        g_pFrameRoot = NULL;
    }

    // Create hierarchy
    V_RETURN( D3DXLoadMeshHierarchyFromX( str, D3DXMESH_MANAGED, pd3dDevice,
                                          &Alloc, NULL, &g_pFrameRoot, &g_pAnimController ) );

    SetupBoneMatrixPointers( g_pFrameRoot, g_pFrameRoot );


    return S_OK;
}
void XSkinnedMesh::LoadModel( const string& fileName )
{
	BoneHierarchyLoader boneHierarchy;

	BoneFrame* frame = nullptr;

	// .x 파일로부터 본 계층 구조를 로드한다.
	auto hr = D3DXLoadMeshHierarchyFromX( fileName.c_str(), D3DXMESH_MANAGED, D3D9_DEVICE, &boneHierarchy, NULL,
										  &frame, &_animation );

	if (FAILED( hr ))
	{
		SAFE_DELETE( frame );
		// assert
	}

	_rootBone = static_cast<Bone*>(frame);

	// bone matrices update
	SetMatrices();

	UpdateMatrices( _rootBone, &_world );

	SetupBoneMatrixPtr( _rootBone );

	// render sphere
	//D3DXCreateSphere( D3D9_DEVICE, 2.0f, 10, 10, &_sphereMesh, NULL );

	//LoadTexture( DEFAULT_TEX );

}
Example #5
0
bool CDexModelXAni::LoadModelFile(const char* filename)
{
	HRESULT hr;

	int64 mseconds = getTime()->GetTotalMillSeconds();
	//从.X文件加载层次框架和动画数据
	hr = D3DXLoadMeshHierarchyFromX(filename, D3DXMESH_MANAGED, DexGameEngine::getEngine()->GetDevice(), 
		m_pAlloc, NULL, &m_pFrameRoot, &m_pAnimController);	  //最后一个参数:动画控制器
	if (FAILED(hr))
		return false;

	//建立各级框架的组合变换矩阵
	SetupBoneMatrixPointers(m_pFrameRoot); 

	int index = 4;
	if(m_pAnimController != NULL)
	{
		m_pAnimController->GetAnimationSet(index, &m_pAnimationSet1);
		m_pAnimController->SetTrackAnimationSet(0, m_pAnimationSet1);
		m_pAnimController->ResetTime();
	}	
	getLog()->BeginLog();
	getLog()->Log(log_ok, "加载animation模型%s成功!用时:%d ms\n",filename, getTime()->GetTotalMillSeconds() - mseconds);
	getLog()->EndLog();
	return true;

}
Example #6
0
bool CXModel::LoadXFile(char *file)
{
   if(!m_device) return false;

   CD3DAllocate alh;

   // Load X mesh from a file.
   if(FAILED(D3DXLoadMeshHierarchyFromX(file, D3DXMESH_MANAGED,
      m_device, &alh, NULL, &m_root, &m_animControl))) return false;

   // Record max number of animation sets in the X model.
   if(m_animControl)
      m_numAnimations = m_animControl->GetMaxNumAnimationSets();

   // Setup Bones.
   if(m_root)
      {
         SetupMatrices((stD3DFrameEx*)m_root, NULL);

         m_boneMatrices = new D3DXMATRIX[m_maxBones];
         ZeroMemory(m_boneMatrices, sizeof(D3DXMATRIX)*m_maxBones);

         D3DXFrameCalculateBoundingSphere(m_root, &m_center,
                                          &m_radius);
      }

   // Set initialize animation.
   SetAnimation(0);

   return true;
}
Example #7
0
bool CXFileEntity::Load(const std::string &filename)
{
	// Create our mesh hierarchy class to control the allocation of memory - only used temporarily
	CMeshHierarchy *memoryAllocator=new CMeshHierarchy;

	// To make it easier to find the textures change the current directory to the one containing the .x file
	// First though remember the current one to put it back afterwards
	std::string currentDirectory=CUtility::GetTheCurrentDirectory();

	std::string xfilePath;
	CUtility::SplitPath(filename,&xfilePath,&m_filename);

	SetCurrentDirectory(xfilePath.c_str());

	// This is the function that does all the .x file loading. We provide a pointer to an instance of our 
	// memory allocator class to handle memory allocationm during the frame and mesh loading
	HRESULT hr = D3DXLoadMeshHierarchyFromX(filename.c_str(), D3DXMESH_MANAGED, m_d3dDevice, 
		memoryAllocator, NULL, &m_frameRoot, &m_animController);

	delete memoryAllocator;
	memoryAllocator=0;

	SetCurrentDirectory(currentDirectory.c_str());
	
	if (FAILED(hr))
		return false; 

	// if the x file contains any animation remember how many sets there are
	if(m_animController)
		m_numAnimationSets = m_animController->GetMaxNumAnimationSets();

	// Bones for skining
	if(m_frameRoot)
	{
		// Set the bones up
		SetupBoneMatrices((D3DXFRAME_EXTENDED*)m_frameRoot, NULL);

		// Create the bone matrices array for use during FrameMove to hold the final transform
		m_boneMatrices  = new D3DXMATRIX[m_maxBones];
		ZeroMemory(m_boneMatrices, sizeof(D3DXMATRIX)*m_maxBones);

		// Calculate the Bounding Sphere for this model (used in CalculateInitialViewMatrix to position camera correctly)
		D3DXFrameCalculateBoundingSphere(m_frameRoot, &m_sphereCentre, &m_sphereRadius);
	}

	m_firstMesh->MeshData.pMesh->GetVertexBuffer(&vb.vb);
	m_firstMesh->MeshData.pMesh->GetIndexBuffer(&ib.ib);

	D3DVERTEXELEMENT9 pDecl[MAX_FVF_DECL_SIZE];
	m_firstMesh->MeshData.pMesh->GetDeclaration(pDecl);
	renderSystem->CreateVertexDeclaration(&pDecl[0],&vb.declaration);
	// Получение данных о количестве вершин, индексов и полигонов
	dwNumVerticies	= m_firstMesh->MeshData.pMesh->GetNumVertices();
	dwNumIndecies	= m_firstMesh->MeshData.pMesh->GetNumFaces()*3;
	dwNumFaces		= m_firstMesh->MeshData.pMesh->GetNumFaces();
	vb.vertexSize = (short)m_firstMesh->MeshData.pMesh->GetNumBytesPerVertex();
	return true;
}
Example #8
0
void SKINNEDMESH::Load(char fileName[], IDirect3DDevice9 *Dev)
{
	m_pDevice = Dev;
	BONE_HIERARCHY boneHierarchy;

	D3DXLoadMeshHierarchyFromX(fileName, D3DXMESH_MANAGED, 
							   m_pDevice, &boneHierarchy,
							   NULL, &m_pRootBone, &m_pAnimControl);

	SetupBoneMatrixPointers((BONE*)m_pRootBone);
}
Example #9
0
void SKINNEDMESH::Load(char fileName[], IDirect3DDevice9 *Dev)
{
	m_pDevice = Dev;

	BONE_HIERARCHY boneHierarchy;

	D3DXLoadMeshHierarchyFromX(fileName, D3DXMESH_MANAGED, m_pDevice, &boneHierarchy,
							   NULL, &m_pRootBone, NULL);

	D3DXMATRIX i;
	UpdateMatrices((BONE*)m_pRootBone, D3DXMatrixIdentity(&i));

	//Create Sphere
	D3DXCreateSphere(m_pDevice, 0.07f, 10, 10, &m_pSphereMesh, NULL);
}
Example #10
0
void SkinnedMesh::Load(char fileName[]) {
    BoneHierarchyLoader boneHierarchy;

    D3DXLoadMeshHierarchyFromX(fileName, D3DXMESH_MANAGED,
                               g_pDevice, &boneHierarchy,
                               NULL, &m_pRootBone, NULL);

    SetupBoneMatrixPointers((Bone*)m_pRootBone);

    //Update all the bones
    D3DXMATRIX i;
    D3DXMatrixIdentity(&i);
    UpdateMatrices((Bone*)m_pRootBone, &i);

    //Create Sphere
    D3DXCreateSphere(g_pDevice, 0.02f, 10, 10, &m_pSphereMesh, NULL);
}
Example #11
0
	/**
	 * @brief メッシュの読み込み
	 *
	 */
	void AnimationManager::loadMeshHierarchyFromX(const acut::TString& meshFilePath)
	{
		try {
			// mesh 読み込み
			V_THROW(D3DXLoadMeshHierarchyFromX(
				meshFilePath.c_str(),
				D3DXMESH_MANAGED,
				DXUTGetD3D9Device(),
				&m_allocateHierarchy,
				NULL,
				reinterpret_cast<LPD3DXFRAME*>(&m_pRootFrame),
				&m_pAnimationController
			));

			// ボーン変換行列へのポインタをセット
			V_THROW(this->setupBoneMatrixPointers(m_pRootFrame));

			// animation controller の trackを全てFALSEにする
			DWORD numTracks = m_pAnimationController->GetMaxNumTracks();
			DEBUG_OUTPUTF("m_pAnimationController->GetMaxNumTracks() : %d\n", numTracks);
			for (DWORD i = 0; i < numTracks; ++i) {
				V_THROW(m_pAnimationController->SetTrackEnable(i, FALSE));
			}

			V_THROW(this->createAnimationSetList());

			try {
				// tyny_4anim.xの場合
				// 0: 手を振る Wave
				// 1: 走る Jog
				// 2: 歩く Walk
				// 3: ふらふらする Loiter
				V_THROW(m_pAnimationController->SetTrackAnimationSet(0, m_animationSetList.at(1)));
				V_THROW(m_pAnimationController->SetTrackEnable(0, TRUE));
			} catch (std::out_of_range& ex) {
				acut::ExceptionHandler::handleException(ex);
				throw acut::Exception(__FILEW__, __LINE__, __FUNCTIONW__);
			}
		} catch (acut::Exception& ex) {
			acut::ExceptionHandler::handleException(ex);
			this->cleanup();
			throw;
		}
	}
Example #12
0
HRESULT	CAnimationModel::InitDeviceObjects(LPDIRECT3DDEVICE9 pd3dDevice)
{
	HRESULT	hr		= S_OK;

	if( NULL == pd3dDevice )
		return	E_INVALIDARG;

	m_pd3dDevice	= pd3dDevice;
	m_pd3dDevice->AddRef();

	//	커스텀 애니메신컨트롤러 를 생성
	m_pAniController	= new CAnimationController;

	//	X파이을 읽어들여 애니메이션 가능한 모델을 만든다.
	if( NULL == m_pXFileName )
		return E_FAIL;

	CAllocateHierarchy	alloc;
	alloc.SetCreationFlag( TRUE );
	alloc.SetDwFrame( 0 );
	alloc.SetDwMeshContainer( 0 );
	alloc.SetFrameVector( &vFrame );
	alloc.SetMeshContainerVector( &vMeshContainer );

	hr = D3DXLoadMeshHierarchyFromX( 
						m_pXFileName
					,	D3DXMESH_MANAGED
					,	m_pd3dDevice
					,	&alloc
					,	NULL
					,	&m_pFrameRoot
					,	&m_pAniController->m_pAniController
					);

	CHECK_FAILED( hr );

	hr = SetupBoneMatrixPointers( m_pFrameRoot );
	CHECK_FAILED( hr );

	m_pAniController->InitDeviceObjects( m_pd3dDevice );

	return hr;
}
Example #13
0
void cSkinnedMesh::Setup( char* szFolder, char* szFile )
{
	std::string sFullPath(szFolder);
	sFullPath += (std::string("/") + std::string(szFile));

	cAllocateHierarchy ah;
	
	ah.SetFolder(szFolder);

	D3DXLoadMeshHierarchyFromX(sFullPath.c_str(),
		D3DXMESH_MANAGED,
		g_pD3DDevice,
		&ah,
		NULL,
		&m_pRoot,
		&m_pAnimController);

	SetupBoneMatrixPtrs((ST_BONE*)m_pRoot);
}
Example #14
0
HRESULT MoonSkinmesh::InitDeviceObjects()
{
	HRESULT hr;

	AllocateHierarchy Alloc(this);
	string strMeshPath = MODEL_DIR("");
	strMeshPath += _strMeshname;
	strMeshPath += "\\";
	strMeshPath += _strMeshname;
	strMeshPath += ".x";
	hr = D3DXLoadMeshHierarchyFromX(strMeshPath.c_str(), D3DXMESH_MANAGED, _pDevice,
								&Alloc, NULL, &_pFrameRoot, &_pAnimController);
	if(FAILED(hr))
		return hr;

	hr = SetupBoneMatrixPointers(_pFrameRoot);
	if(FAILED(hr))
		return hr;

	return S_OK;
}
Example #15
0
INT CLcXSkinSrc::Create(void* p1, void* p2, void*, void* )
{
	HRESULT				hr;
	CLcXSkinAlloc		Alloc(this);

	char* sFile			= NULL;
	
	m_pDevice	= (LPDIRECT3DDEVICE9)p1;
	sFile		= (char*)p2;

	::strcpy(m_sFile, sFile);
	

	WCHAR* wFile = new WCHAR[strlen(m_sFile)+1];
	DXUtil_ConvertAnsiStringToWideCch(wFile, m_sFile, strlen(m_sFile)+1);

	hr = D3DXLoadMeshHierarchyFromX(wFile
								, D3DXMESH_MANAGED
								, m_pDevice
								, &Alloc
								, NULL
								, (LPD3DXFRAME*)&m_pFrameRoot
								, &m_pAC);
	delete[] wFile;

	if (FAILED(hr))
		return hr;
	
	
	hr = FindBones(m_pFrameRoot);
	if (FAILED(hr))
		return hr;
	
	hr = D3DXFrameCalculateBoundingSphere((const D3DXFRAME*)m_pFrameRoot, &m_ObjectCenter, &m_ObjectRadius);
	if (FAILED(hr))
		return hr;
	
	
	return S_OK;
}
Example #16
0
SkinnedMesh::SkinnedMesh(std::string XFilename)
{
    AllocMeshHierarchy allocMeshHierarchy;
    HR(D3DXLoadMeshHierarchyFromX(XFilename.c_str(), D3DXMESH_SYSTEMMEM,
                                  gd3dDevice, &allocMeshHierarchy, 0, /* ignore user data */
                                  &mRoot,	&mAnimCtrl));

    // In this demo we assume that the input .X file contains only one
    // mesh.  So search for that one and only mesh.
    D3DXFRAME* f = findNodeWithMesh(mRoot);
    if( f == 0 ) HR(E_FAIL);
    D3DXMESHCONTAINER* meshContainer = f->pMeshContainer;
    mSkinInfo = meshContainer->pSkinInfo;
    mSkinInfo->AddRef();

    mNumBones = meshContainer->pSkinInfo->GetNumBones();
    mFinalXForms.resize(mNumBones);
    mToRootXFormPtrs.resize(mNumBones, 0);

    buildSkinnedMesh(meshContainer->MeshData.pMesh);
    buildToRootXFormPtrArray();
}
Example #17
0
//-----------------------------------------------------------------------------
// The mesh class constructor.
//-----------------------------------------------------------------------------
Mesh::Mesh( char *name, char *path ) : Resource< Mesh >( name, path )
{
	// Create the list of reference points.
	m_frames = new LinkedList< Frame >;
	m_refPoints = new LinkedList< Frame >;

	// Load the mesh's frame hierarchy.
	AllocateHierarchy ah;
	D3DXLoadMeshHierarchyFromX( GetFilename(), D3DXMESH_MANAGED, Engine::GetInstance()->GetDevice(), &ah, NULL, (D3DXFRAME**)&m_firstFrame, &m_animationController );

	// Disable all the animation tracks initially.
	if( m_animationController != NULL )
		for( unsigned long t = 0; t < m_animationController->GetMaxNumTracks(); ++t )
			m_animationController->SetTrackEnable( t, false );

	// Invalidate the bone transformation matrices array.
	m_boneMatrices = NULL;
	m_totalBoneMatrices = 0;

	// Prepare the frame hierarchy.
	PrepareFrame( m_firstFrame );

	// Allocate memory for the bone matrices.
	m_boneMatrices = new D3DXMATRIX[m_totalBoneMatrices];

	// Create a static (non-animated) version of the mesh.
	m_staticMesh = new MeshContainer;
	ZeroMemory( m_staticMesh, sizeof( MeshContainer ) );

	// Load the mesh.
	ID3DXBuffer *materialBuffer, *adjacencyBuffer;
	D3DXLoadMeshFromX( GetFilename(), D3DXMESH_MANAGED, Engine::GetInstance()->GetDevice(), &adjacencyBuffer, &materialBuffer, NULL, &m_staticMesh->NumMaterials, &m_staticMesh->originalMesh );

	// Optimise the mesh for better rendering performance.
	m_staticMesh->originalMesh->OptimizeInplace( D3DXMESHOPT_COMPACT | D3DXMESHOPT_ATTRSORT | D3DXMESHOPT_VERTEXCACHE, (DWORD*)adjacencyBuffer->GetBufferPointer(), NULL, NULL, NULL );

	// Finished with the adjacency buffer, so destroy it.
	SAFE_RELEASE( adjacencyBuffer );

	// Check if the mesh has any materials.
	if( m_staticMesh->NumMaterials > 0 )
	{
		// Create the array of materials.
		m_staticMesh->materials = new Material*[m_staticMesh->NumMaterials];

		// Get the list of materials from the material buffer.
		D3DXMATERIAL *materials = (D3DXMATERIAL*)materialBuffer->GetBufferPointer();

		// Load each material into the array via the material manager.
		for( unsigned long m = 0; m < m_staticMesh->NumMaterials; m++ )
		{
			// Ensure the material has a texture.
			if( materials[m].pTextureFilename )
			{
				// Get the name of the material's script and load it.
				char *name = new char[strlen( materials[m].pTextureFilename ) + 5];
				sprintf( name, "%s.txt", materials[m].pTextureFilename );
				m_staticMesh->materials[m] = Engine::GetInstance()->GetMaterialManager()->Add( name, GetPath() );
				SAFE_DELETE_ARRAY( name );
			}
			else
				m_staticMesh->materials[m] = NULL;
		}
	}

	// Create the bounding volume around the mesh.
	BoundingVolumeFromMesh( m_staticMesh->originalMesh );

	// Destroy the material buffer.
	SAFE_RELEASE( materialBuffer );

	// Create a vertex array and an array of indices into the vertex array.
	m_vertices = new Vertex[m_staticMesh->originalMesh->GetNumVertices()];
	m_indices = new unsigned short[m_staticMesh->originalMesh->GetNumFaces() * 3];

	// Use the arrays to store a local copy of the static mesh's vertices and
	// indices so that they can be used by the scene manager on the fly.
	Vertex* verticesPtr;
	m_staticMesh->originalMesh->LockVertexBuffer( 0, (void**)&verticesPtr );
	unsigned short *indicesPtr;
	m_staticMesh->originalMesh->LockIndexBuffer( 0, (void**)&indicesPtr );

	memcpy( m_vertices, verticesPtr, VERTEX_FVF_SIZE * m_staticMesh->originalMesh->GetNumVertices() );
	memcpy( m_indices, indicesPtr, sizeof( unsigned short ) * m_staticMesh->originalMesh->GetNumFaces() * 3 );

	m_staticMesh->originalMesh->UnlockVertexBuffer();
	m_staticMesh->originalMesh->UnlockIndexBuffer();
}
Example #18
0
Face::Face(string filename) {
    m_pBaseMesh =  NULL;
    m_pBlinkMesh = NULL;
    m_pFaceTexture = NULL;
    m_pFaceNormalMap = NULL;

    //Face Vertex Format
    D3DVERTEXELEMENT9 faceVertexDecl[] = {
        //1st Stream: Base Mesh
        {0,  0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
        {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL,   0},
        {0, 24, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
        {0, 32, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TANGENT,  0},
        {0, 44, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_BINORMAL, 0},

        //2nd Stream
        {1,  0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 1},
        {1, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL,   1},
        {1, 24, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 1},

        //3rd Stream
        {2,  0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 2},
        {2, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL,   2},
        {2, 24, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 2},

        //4th Stream
        {3,  0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 3},
        {3, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL,   3},
        {3, 24, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 3},

        //5th Stream
        {4,  0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 4},
        {4, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL,   4},
        {4, 24, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 4},

        D3DDECL_END()
    };

    //Create Face Vertex Declaration
    g_pDevice->CreateVertexDeclaration(faceVertexDecl, &m_pFaceVertexDecl);

    //Load Face Meshes
    FaceHierarchyLoader hierarchy;
    D3DXFRAME *root = NULL;
    D3DXLoadMeshHierarchyFromX(filename.c_str(), D3DXMESH_MANAGED,
                               g_pDevice, &hierarchy, NULL, &root, NULL);

    //Extract Face Meshes
    ExtractMeshes(root);

    //Add tangents & binormal to base mesh
    AddTangentBinormal(&m_pBaseMesh);
    //PrintMeshDeclaration(m_pBaseMesh);

    //Destroy temporary hierarchy
    hierarchy.DestroyFrame(root);

    //Load textures
    D3DXCreateTextureFromFile(g_pDevice, "resources/face.jpg", &m_pFaceTexture);
    D3DXCreateTextureFromFile(g_pDevice, "resources/face_normal.tga", &m_pFaceNormalMap);
}
bool SkinnedMesh::Init( std::wstring path )
{
	AllocateHierarchy Alloc;

	DWORD dwShaderFlags = D3DXFX_NOT_CLONEABLE;

#if defined( DEBUG ) || defined( _DEBUG )
	dwShaderFlags |= D3DXSHADER_DEBUG;
#endif

#ifdef DEBUG_VS
	dwShaderFlags |= D3DXSHADER_FORCE_VS_SOFTWARE_NOOPT;
#endif
#ifdef DEBUG_PS
	dwShaderFlags |= D3DXSHADER_FORCE_PS_SOFTWARE_NOOPT;
#endif

	LPDIRECT3DDEVICE9 pD3DDevice = DDRenderer::GetInstance()->GetDevice();

	WCHAR str[MAX_PATH] = L".\\Resources\\3DModel\\SkinnedMesh.fx";

	// shader 파일 읽어서 등록
	if ( FAILED( D3DXCreateEffectFromFile( pD3DDevice, str, NULL, NULL, dwShaderFlags, NULL, &m_pEffect, NULL ) ) )
	{
		assert( false );
		return false;
	}

	// shader 파일 이름 생성
	std::wstring xfilePath = L".\\Resources\\3DModel\\";
	xfilePath.append( path );

	// 메시 불러오기
	// 애니메이션 계층 구조 만들기
	if ( FAILED( D3DXLoadMeshHierarchyFromX( xfilePath.c_str(), D3DXMESH_MANAGED, pD3DDevice, &Alloc, NULL, &m_pFrameRoot, &m_pAnimController ) ) )
	{
		assert( false );
		return false;
	}

	// 조심해!
	// 예제에서는 m_pBoneMatrices를 전역 변수로 사용하므로 
	// AllocateHierarchy에서 할당했으나 이제는 여기서 해준다.
	// 그런데 사이즈는 어떻게 가져오지... 아무튼 지금 애니메이션 안 나오는 문제는 여기 아님
	delete[] m_pBoneMatrices;
	m_pBoneMatrices = new D3DXMATRIXA16[64];
	if ( m_pBoneMatrices == nullptr )
	{
		assert( false );
		return false;
	}

	// 본 매트릭스 생성
	if ( FAILED( SetupBoneMatrixPointers( m_pFrameRoot ) ) )
	{
		assert( false );
		return false;
	}

	if ( FAILED( D3DXFrameCalculateBoundingSphere( m_pFrameRoot, &m_vObjectCenter, &m_fObjectRadius ) ) )
	{
		assert( false );
		return false;
	}

	// Obtain the behavior flags
	D3DDEVICE_CREATION_PARAMETERS cp;
	pD3DDevice->GetCreationParameters( &cp );
	m_dwBehaviorFlags = cp.BehaviorFlags;

	return true;
}