http://www.cppblog.com/lovedday/archive/2009/12/09/24729.html
http://www.cppblog.com/lovedday/archive/2008/06/11/52868.html
重点:
http://www.cppblog.com/lovedday/archive/2007/07/22/28595.html
http://www.cppblog.com/lovedday/archive/2008/04/22/47819.html 变换
具体是个什么样子原理尚不清楚,暂时放在这里,日后再详细写入
找了好久也没有找到合适的渲染代码,几处资料讲解的不够详细,以至于貌似冲突的样子。猜测下。
D3DMESHCONTAINER A,B,C.....
D3DXFRAME a1,a2,a3,a4,b1,b2.b3,........
虽然D3DXFRAME (框架骨骼) 中包含一个指向D3DMESHCONTAINER(容器)的指针,但貌似其并不是最顶层。A--->B---->C--->......, 也就是说容器作为一层,一个X文件可能形成几个容器结构,然后彼此通过指针串联起来。而每块骨骼都对应着某个容器,因此每个骨骼有一个指向容器的指针。而骨骼本身的层次则通过兄弟骨骼和子骨骼指针指向下去。当然里面也是一样子的。由此就可以解释了一个网格容器(MESH)当中,可能通过D3DXSKININFO 存储了多个骨骼的信息,一个X文件中可能有多个网格容器就是了。模型容器数据在某个数据对象当中,当然了数据对象有各种类型,通过类型可以判断是否为网格容器。
typedef struct _D3DXFRAME{ //骨骼(框架)结构体
LPSTR Name; //骨骼名
D3DXMATRIX TransformationMatrix; //相对于父骨骼坐标系的变换矩阵
LPD3DXMESHCONTAINER pMeshContainer; //网格容器
struct _D3DXFRAME* pFrameSibling; //兄弟骨骼
struct _D3DXFRAME* pFrameFirstChild;//子骨骼
}D3DXFRAME,LPD3DXFRAME;
typedef struct _D3DMESHCONTAINER{ //网格容器结构体
LPSTR Name; //网格容器名
D3DXMESHDATA MeshData; //网格数据
LPD3DMATERIAL pMaterials; //网格材质
LPD3DXEFFECTINSTANCE pEffects; //特效
DWORD NumMatrials; //材质数
DWORD* pAdjacency; //邻接三角形信息
LPD3DXSKININFO pSkininfo; //蒙皮信息
struct _D3DMESHCONTAINER* pNextMeshContainer; //下一个网格容器指针
}D3DMESHCONTAINER, *LPD3DMESHCONTAINER;
struct D3DXFRAME_DERIVED:public D3DXFRAME{ //骨骼(框架)扩展结构体
D3DXMATRIXA16 CombinedTransformationMatrix; //动作变换矩阵
};
struct D3DMESHCONTAINER_DERIVED:public D3DMESHCONTAINER{ //网格容器扩展结构体
LPDIRECT3DTEXTURE9* ppTextures; //纹理数组,如果没有纹理数组则为NULL
LPD3DXMESH pOrigMesh; //原网格
LPD3DXATTRIBUTERANGE pAttributeTable; //属性表
DWORD NumAttributeGroups; //属性组个数
DWORD NumInfl;
LPD3DXBUFFER pBoneCombinationBuf; //骨骼缓冲区
D3DXMATRIX** ppBoneMatrixPtrs; //骨骼矩阵
D3DXMATRIX* pBoneOffsetMatrices; //骨骼权重矩阵
DWORD NumPaletteEntries;
};
//在内存中创建一个Frame(纯虚函数,需要给出具体的实现细节)
virtual HRESULT ID3DXAllocateHierarchy::CreateFrame(
LPCSTR Name, //框架名
LPD3DXFRAME* ppNewFrame //返回创建的Frame对象
)
//创建一个网格容器(纯虚函数,需要给出具体的实现细节)
virtual HRESULT ID3DXAllocateHierarchy::CreateMeshContainer(
LPCSTR Name, //网格容器名
const D3DXMESHDATA* pMeshData, //网格数据
const D3DXMATERIAL* pMaterials, //网格材质
const D3DXEFFECTINSTANCE* pEffectInstances, //效果
DWORD NumMaterials, //材质数目
const DWORD* pAjacency, //邻接三角形信息
LPD3DXSKININFO pSkinInfo, //蒙皮信息
LPD3DXMESHCONTAINER* ppNewMeshContainer //返回创建的网格对象
);
//释放一个帧(纯虚函数,需要给出具体的实现细节)
virtual HRESULT ID3DXAllocateHierarchy::DestroyFrame(
LPD3DXFRAME pFrameToFree
);
//释放网格容器(纯虚函数,需要给出具体的实现细节)
virtual HRESULT ID3DXAllocateHierarchy::DestroyMeshContainer(
LPD3DMESHCONTAINER pMeshContainerToFree
);
//ID3DXAllocateHierarchy接口的扩展类
class CAllocateHierarchy: public ID3DXAllocateHierarchy
{
public:
STDMETHOD(CreateFrame)(THIS_ LPCTSTR Name, LPD3DXFRAME *ppNewFrame);
STDMETHOD(CreateMeshContainer)(THIS_
LPCSTR Name,
CONST D3DXMESHDATA *pMeshData,
CONST D3DXMATERIAL *pMaterials,
CONST D3DXEFFECTINSTANCE *pEffectInstances,
DWORD NumMaterials,
CONST DWORD *pAdjacency,
LPD3DXSKININFO pSkinInfo,
LPD3DXMESHCONTAINER *ppNewMeshContainer);
STDMETHOD(DestroyFrame)(THIS_ LPD3DXFRAME pFrameToFree);
STDMETHOD(DestroyMeshContainer)(THIS_ LPD3DXMESHCONTAINER pMeshContainerBase);
public:
CAllocateHierarchy(CSkinMesh *pSkinMesh) :m_pSkinMesh(pSkinMesh) {}
CSkinMesh* m_pSkinMesh;
};
/*----------------------该类的实现细节(内含4个纯虚函数的实现细节)-------------------------*/
//骨骼名称命名
HRESULT AllocateName( LPCTSTR Name, LPTSTR *pNewName )
{
UINT cbLength;
if (Name != NULL)
{
cbLength = lstrlen(Name) + 1;
*pNewName = new TCHAR[cbLength];
if (*pNewName == NULL)
return E_OUTOFMEMORY;
memcpy(*pNewName, Name, cbLength*sizeof(TCHAR));
}
else
{
*pNewName = NULL;
}
return S_OK;
}
//创建并初始化一个帧并命名
HRESULT CAllocateHierarchy::CreateFrame(LPCTSTR Name, LPD3DXFRAME *ppNewFrame)
{
HRESULT hr = S_OK;
D3DXFRAME_DERIVED *pFrame;
*ppNewFrame = NULL;
pFrame = new D3DXFRAME_DERIVED;
if (pFrame == NULL)
{
hr = E_OUTOFMEMORY;//内存分配不足
goto e_Exit;
}
hr = AllocateName(Name, &pFrame->Name);
if (FAILED(hr))
goto e_Exit;
//初始化帧的数据
D3DXMatrixIdentity(&pFrame->TransformationMatrix);
D3DXMatrixIdentity(&pFrame->CombinedTransformationMatrix);
pFrame->pMeshContainer = NULL;
pFrame->pFrameSibling = NULL;
pFrame->pFrameFirstChild = NULL;
*ppNewFrame = pFrame;//返回初始化帧
pFrame = NULL;
e_Exit:
delete pFrame;
return hr;
}
//创建网格容器
HRESULT CAllocateHierarchy::CreateMeshContainer(
LPCSTR Name, //网格容器名称
CONST D3DXMESHDATA *pMeshData, //传入的网格数据
CONST D3DXMATERIAL *pMaterials, //传入的材质数据
CONST D3DXEFFECTINSTANCE *pEffectInstances, //
DWORD NumMaterials, //传入的材质数量
CONST DWORD *pAdjacency, //传入的邻接三角形面信息
LPD3DXSKININFO pSkinInfo, //传入的蒙皮信息
LPD3DXMESHCONTAINER *ppNewMeshContainer) //获得的网格容器指针
{
HRESULT hr;
D3DXMESHCONTAINER_DERIVED *pMeshContainer = NULL;
UINT NumFaces;
UINT iMaterial;
UINT iBone, cBones;
LPDIRECT3DDEVICE9 pd3dDevice = NULL;
LPD3DXMESH pMesh = NULL;
*ppNewMeshContainer = NULL;
if (pMeshData->Type != D3DXMESHTYPE_MESH) //如果不是网格数据类型
{
hr = E_FAIL;
goto e_Exit;
}
pMesh = pMeshData->pMesh;
if (pMesh->GetFVF() == 0) //取得定点的可变格式,返回0表示不能转换为可变格式
{
hr = E_FAIL;
goto e_Exit;
}
pMeshContainer = new D3DXMESHCONTAINER_DERIVED; //申请内存
if (pMeshContainer == NULL)
{
hr = E_OUTOFMEMORY;
goto e_Exit;
}
memset(pMeshContainer, 0, sizeof(D3DXMESHCONTAINER_DERIVED)); //内存置0
hr = AllocateName(Name, &pMeshContainer->Name); //网格容器命名
if (FAILED(hr))
goto e_Exit;
pMesh->GetDevice(&pd3dDevice); //获得容器设备
NumFaces = pMesh->GetNumFaces(); //获得网格的三角形面数
//如果没有法向量,则添加它们
if (!(pMesh->GetFVF() & D3DFVF_NORMAL))
{
pMeshContainer->MeshData.Type = D3DXMESHTYPE_MESH;
//先复制
hr = pMesh->CloneMeshFVF( pMesh->GetOptions(),
pMesh->GetFVF() | D3DFVF_NORMAL,
pd3dDevice, &pMeshContainer->MeshData.pMesh );
if (FAILED(hr))
goto e_Exit;
pMesh = pMeshContainer->MeshData.pMesh;
//生成法向量
D3DXComputeNormals( pMesh, NULL );
}
else
{
pMeshContainer->MeshData.pMesh = pMesh;
pMeshContainer->MeshData.Type = D3DXMESHTYPE_MESH;
pMesh->AddRef();
}
pMeshContainer->NumMaterials = max(1, NumMaterials);
pMeshContainer->pMaterials = new D3DXMATERIAL[pMeshContainer->NumMaterials];
pMeshContainer->ppTextures = new LPDIRECT3DTEXTURE9[pMeshContainer->NumMaterials];
pMeshContainer->pAdjacency = new DWORD[NumFaces*3];
if ((pMeshContainer->pAdjacency == NULL) || (pMeshContainer->pMaterials == NULL))
{
hr = E_OUTOFMEMORY;
goto e_Exit;
}
memcpy(pMeshContainer->pAdjacency, pAdjacency, sizeof(DWORD) * NumFaces*3);
memset(pMeshContainer->ppTextures, 0, sizeof(LPDIRECT3DTEXTURE9) * pMeshContainer->NumMaterials);
//如果有材质数据,生成纹理对象,并放入扩展后的网格容器中
if (NumMaterials > 0)
{
memcpy(pMeshContainer->pMaterials, pMaterials, sizeof(D3DXMATERIAL) * NumMaterials);
for (iMaterial = 0; iMaterial < NumMaterials; iMaterial++)
{
if (pMeshContainer->pMaterials[iMaterial].pTextureFilename != NULL)
{
TCHAR* strTexturePath=pMeshContainer->pMaterials[iMaterial].pTextureFilename;
if( FAILED( D3DXCreateTextureFromFile( pd3dDevice, strTexturePath,
&pMeshContainer->ppTextures[iMaterial] ) ) )
pMeshContainer->ppTextures[iMaterial] = NULL;
pMeshContainer->pMaterials[iMaterial].pTextureFilename = NULL;
}
}
}
else //没有材质,则添加一个默认值
{
pMeshContainer->pMaterials[0].pTextureFilename = NULL;
memset(&pMeshContainer->pMaterials[0].MatD3D, 0, sizeof(D3DMATERIAL9));
pMeshContainer->pMaterials[0].MatD3D.Diffuse.r = 0.5f;
pMeshContainer->pMaterials[0].MatD3D.Diffuse.g = 0.5f;
pMeshContainer->pMaterials[0].MatD3D.Diffuse.b = 0.5f;
pMeshContainer->pMaterials[0].MatD3D.Specular = pMeshContainer->pMaterials[0].MatD3D.Diffuse;
}
//存在蒙皮信息
if (pSkinInfo != NULL)
{
pMeshContainer->pSkinInfo = pSkinInfo;
pSkinInfo->AddRef();
pMeshContainer->pOrigMesh = pMesh; //备份指针
pMesh->AddRef();
cBones = pSkinInfo->GetNumBones();
pMeshContainer->pBoneOffsetMatrices = new D3DXMATRIX[cBones];
if (pMeshContainer->pBoneOffsetMatrices == NULL)
{
hr = E_OUTOFMEMORY;
goto e_Exit;
}
//取得骨骼的权重矩阵
for (iBone = 0; iBone < cBones; iBone++)
{
pMeshContainer->pBoneOffsetMatrices[iBone] = *
(pMeshContainer->pSkinInfo->GetBoneOffsetMatrix(iBone));
}
//生成蒙皮网格
hr = m_pSkinMesh->GenerateSkinnedMesh(pMeshContainer);
if (FAILED(hr))
goto e_Exit;
}
*ppNewMeshContainer = pMeshContainer;
pMeshContainer = NULL;
e_Exit:
SafeRelease(pd3dDevice);
//释放网格容器
if (pMeshContainer != NULL)
{
DestroyMeshContainer(pMeshContainer);
}
return hr;
}
//释放帧
HRESULT CAllocateHierarchy::DestroyFrame(LPD3DXFRAME pFrameToFree)
{
SafeDeleteArray( pFrameToFree->Name );
SafeDelete( pFrameToFree );
return S_OK;
}
//释放网格容器
HRESULT CAllocateHierarchy::DestroyMeshContainer(LPD3DXMESHCONTAINER pMeshContainerBase)
{
UINT iMaterial;
D3DXMESHCONTAINER_DERIVED *pMeshContainer = (D3DXMESHCONTAINER_DERIVED*)pMeshContainerBase;
SafeDeleteArray( pMeshContainer->Name );
SafeDeleteArray( pMeshContainer->pAdjacency );
SafeDeleteArray( pMeshContainer->pMaterials );
SafeDeleteArray( pMeshContainer->pBoneOffsetMatrices );
//释放所有纹理对象
if (pMeshContainer->ppTextures != NULL)
{
for (iMaterial = 0; iMaterial < pMeshContainer->NumMaterials; iMaterial++)
{
SafeRelease( pMeshContainer->ppTextures[iMaterial] );
}
}
SafeDeleteArray( pMeshContainer->ppTextures );
SafeDeleteArray( pMeshContainer->ppBoneMatrixPtrs );
SafeRelease( pMeshContainer->pBoneCombinationBuf );
SafeRelease( pMeshContainer->MeshData.pMesh );
SafeRelease( pMeshContainer->pSkinInfo );
SafeRelease( pMeshContainer->pOrigMesh );
SafeDelete( pMeshContainer );
return S_OK;
}
//装入骨骼动画
HRESULT WINAPI D3DXLoadMeshHierarchyFromX(
LPCTSTR Filename, //骨骼动画的.x文件名
DWORD MeshOptions, //D3DXMESH_MANAGED等选项
LPDIRECT3DDEVICE pDevice, //关联的3D设备
LPD3DXALLOCATEHIERARCHY pAlloc, //Frame层次对象生成接口
LPD3DXLOADUSERDATA pUserDataLoader, //一般为NULL
LPD3DXFRAME* ppFrameHierarchy, //返回已具有层次结构的根Frame指针
LPD3DXANIMATIONCONTROLLER* ppAnimController //返回相应的动画控制器
);
//生成蒙皮网格
HRESULT ID3DXSkinInfo::ConvertToIndexedBlendedMesh(
LPD3DXMESH pMesh, //传入的原网格
DWORD Options, //当前并未使用
DWORD paletteSize, //骨骼矩阵调用
const DWORD* pAdjacencyIn, //传入的临界三角形信息
LPDWORD pAdjacencyOut, //一般为NULL
DWORD* pFaceRemap, //一般为NULL
LPD3DXBUFFER* ppVertexRemap, //一般为NULL
DWORD* pMaxVertexInfl, //一个顶点可以受到骨骼影响的最大骨骼数
DWORD* pNumBoneCombinations, //骨骼组合属性表中的骨骼数
LPD3DXBUFFER* ppBoneCombinationTable, //骨骼组合属性表
LPD3DMESH* ppMesh
);
//ppBoneCombinationTable(骨骼组合属性表)的元素定义
typedef struct _D3DXBONECOMBINATION{
DWORD AttribId; //子集的属性id
DWORD FaceStart; //起始三角形面
DWORD FaceCount; //子集的三角形面个数
DWORD VertexStart; //起始顶点
DWORD VertexCount; //顶点计数
DWORD* BoneId; //该子集的各个骨骼
}D3DXBONECOMBINATION, *LPD3DXBONECOMBINATION;
//释放骨骼框架
HRESULT D3DXALLOCATEHIERARCHY::D3DXFrameDestroy(
LPD3DXFRAME pFrameRoot, //根帧指针
LPD3DXALLOCATEHIERARCHY pAlloc //创建帧层次结构的接口
);
//调整当前动画的时间点
HRESULT D3DXANIMATIONCONTROLLER::AdvanceTime(
DOUBLE TimeDelta, //动画进行的时间
LPD3DXANIMATIONCALLBACKHANDLER pCallbackHandler //回调处理,可设置为NULL
);