📄 allocatehierarchy.cpp
字号:
// 个性化注释:天兵 zzprogram@126.com
#include "AllocateHierarchy.h"
//-----------------------------------------------------------------------------
// Name: AllocateName()
// Desc: 第2个被调用,只是拷贝字符串函数罢了。没啥大不了,学生们可以略过... ...
//-----------------------------------------------------------------------------
HRESULT AllocateName( LPTSTR *ppDst, LPCTSTR pScr )
{
// 将Name的字符串内容保存到pNewName中去
UINT cbLength;
if (pScr != NULL)
{
cbLength = lstrlen(pScr) + 1;
*ppDst = new TCHAR[cbLength];
if (*ppDst == NULL)
return E_OUTOFMEMORY;
memcpy( *ppDst, pScr, cbLength*sizeof(TCHAR) );
}
else
{
*ppDst = NULL;
}
return S_OK;
}
//-----------------------------------------------------------------------------
// Name: CAllocateHierarchy::CreateFrame()
// Desc: 第1个被调用,Name是根框架的名字,用来创建整个框架层次(由DX系统内部完成)
// 递归遍例每一个框架(Frame),本例中第一个框架名字叫:Object03
// 第二个是个无名字的框架,第3个框架名字叫:Bip01,第4个是无名字框架,第5个叫Bip01_Footsteps ... ...
//-----------------------------------------------------------------------------
// Name参数的值是"Object03",是该模型的根框架
HRESULT CAllocateHierarchy::CreateFrame(LPCTSTR Name, LPD3DXFRAME *ppNewFrame)
{
HRESULT hr = S_OK;
D3DXFRAME_EX *pFrame = NULL;
*ppNewFrame = NULL;
// 第一次进来的时候,pFrame可是根框架,不要小看了它。
pFrame = new D3DXFRAME_EX; // 创建一个扩展的框架(我们自定义的嘛,你没忘吧?),在这里终于用上了...
if (pFrame == NULL) // 分配内存失败? 那就没得玩了~~
{
hr = E_OUTOFMEMORY;
goto e_Exit;
}
// 只拷贝字符串从Name到pFrame->Name中(别看它好象很可怕的样子,其实没什么大不了地,我们第一本书就学过这个了!)
hr = AllocateName( &pFrame->Name, Name );
if (FAILED(hr)) // 哎呀~ 这就是传说中的“goto”~~ 难道真是走投无路了吗??
goto e_Exit;
D3DXMatrixIdentity( &pFrame->TransformationMatrix ); // 单位化当前框架的相对变换矩阵(相对于父框架的变换矩阵)
D3DXMatrixIdentity( &pFrame->CombinedTransformationMatrix ); // 单位化当前框架的变换矩阵(世界变换矩阵)
pFrame->pMeshContainer = NULL; // 初始化网格容器
pFrame->pFrameSibling = NULL; // 初始化兄弟节点
pFrame->pFrameFirstChild = NULL; // 初始化首个子节点
*ppNewFrame = pFrame; // 指向这个刚创建的框架(还热乎的吧? 不信你摸摸)
pFrame = NULL; // pFrame对我们来说,已经没有利用价值了
e_Exit: // 同学们不要学这个人写代码。。。因为此人很黄,很暴力! 你跟他学那就是:很傻,很天真! 啊哈哈哈~~~
//delete pFrame; // 是时候了,我们干掉它(其实没什么用处,看看前面已经执行过:pFrame = NULL;,说明pFrame指向了空,已经没什么好delete的了)
return hr;
}
//-----------------------------------------------------------------------------
// Name: CAllocateHierarchy::CreateMeshContainer()
// Desc:
//-----------------------------------------------------------------------------
#if ((D3D_SDK_VERSION&0xFF)==31) // Directx9.0b
HRESULT CAllocateHierarchy::CreateMeshContainer(
LPCTSTR Name,
LPD3DXMESHDATA pMeshData,
LPD3DXMATERIAL pMaterials,
LPD3DXEFFECTINSTANCE pEffectInstances,
DWORD NumMaterials,
DWORD *pAdjacency,
LPD3DXSKININFO pSkinInfo,
LPD3DXMESHCONTAINER *ppNewMeshContainer)
#else // Direct9.0c
LRESULT CAllocateHierarchy::CreateMeshContainer(
LPCTSTR Name,
CONST D3DXMESHDATA *pMeshData,
CONST D3DXMATERIAL *pMaterials,
CONST D3DXEFFECTINSTANCE *pEffectInstances,
DWORD NumMaterials,
CONST DWORD *pAdjacency,
LPD3DXSKININFO pSkinInfo,
LPD3DXMESHCONTAINER *ppNewMeshContainer)
#endif
{
HRESULT hr; // 你应该这个破玩意儿是干什么的吧?
// 下面用到了我们扩展的自定义结构体(请允许我这么说:)),这个结构扩展了相当多的数据成员,也许你已经忘了。。。
D3DXMESHCONTAINER_EX *pMeshContainer = NULL; // 使用前置空先(这是个好习惯)
UINT NumFaces; // 面数
LPDIRECT3DDEVICE9 pd3dDevice = NULL;
LPD3DXMESH pMesh = NULL; // 这是真正的网格接口
*ppNewMeshContainer = NULL;
// 这个例子不能处理细节度网格模型,一旦被发现(是ID3DXPatchMesh)就全完了!
if (pMeshData->Type != D3DXMESHTYPE_MESH)
{
hr = E_FAIL;
goto e_Exit;
}
// get the pMesh interface pointer out of the mesh data structure
// 终于指到它想要指的了(当然是一个网格模型LPD3DXMESH)
pMesh = pMeshData->pMesh;
// 如果没有灵活顶点格式,即失败!
if (pMesh->GetFVF() == 0)
{
hr = E_FAIL;
goto e_Exit;
}
// new一个扩展的网格容器结构
pMeshContainer = new D3DXMESHCONTAINER_EX;
if (pMeshContainer == NULL)
{
hr = E_OUTOFMEMORY;
goto e_Exit;
}
memset(pMeshContainer, 0, sizeof(D3DXMESHCONTAINER_EX));
// 将名字拷贝过去(刚干了点正事。。。)
hr = AllocateName(&pMeshContainer->Name, Name);
if (FAILED(hr))
goto e_Exit;
pMesh->GetDevice(&pd3dDevice); // 取得设备,保存在pd3dDevice变量中
NumFaces = pMesh->GetNumFaces(); // 取得模型的面数
// 如果mesh中没有法线信息。。。真倒霉~
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干活,必须用它再指向新的网格模型
pMesh = pMeshContainer->MeshData.pMesh;
// 为每个顶点生成法线(这个函数干得可是个累活,想想吧同学们,无数的叉乘在下面的函数中计算)
D3DXComputeNormals( pMesh, NULL );
}
else // 为网格容器增加一个网格引用计数(是为了不想过早释放它吧?因为以后还想用pMeshContainer->MeshData.pMesh来干活呢)
{
pMeshContainer->MeshData.pMesh = pMesh;
pMeshContainer->MeshData.Type = D3DXMESHTYPE_MESH;
pMesh->AddRef();
}
// allocate memory to contain the material information. This sample uses
// the D3D9 materials and texture names instead of the EffectInstance style materials
pMeshContainer->NumMaterials = max(1, NumMaterials); // 取得材质数量,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); // 拷贝内存,pAdjacency同样是上层函数的参数
memset(pMeshContainer->ppTextures, 0, sizeof(LPDIRECT3DTEXTURE9) * pMeshContainer->NumMaterials); // 清空内存(纹理数组的指针)
// 如果有材质,拷贝它们
if (NumMaterials > 0)
{
memcpy(pMeshContainer->pMaterials, pMaterials, sizeof(D3DXMATERIAL) * NumMaterials); // 拷贝材质数组内容到pMeshContainer->pMaterials
for (UINT i=0; i<NumMaterials; i++)
{
if (pMeshContainer->pMaterials[i].pTextureFilename != NULL)
{
// 加载纹理,失败则纹理为NULL
if( FAILED( D3DXCreateTextureFromFile(
pd3dDevice, // 设备
pMeshContainer->pMaterials[i].pTextureFilename, // 纹理文件名
&pMeshContainer->ppTextures[i] ) ) ) // 纹理接口指针
pMeshContainer->ppTextures[i] = NULL; // 加载失败时
// 不要保存一个指向动态内存的指针,加载完就置空
pMeshContainer->pMaterials[i].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 there is skinning information, save off the required data and then setup for HW skinning
// 如果有蒙皮信息,保存蒙皮信息,并且设置硬件蒙皮
if (pSkinInfo != NULL)
{
pMeshContainer->pSkinInfo = pSkinInfo; // 首先保存蒙皮信息
pSkinInfo->AddRef();
pMeshContainer->pOrigMesh = pMesh; // 原始网格模型数据
pMesh->AddRef();
// 需要一个变换顶点的偏移矩阵的数组(将顶点从模型空间变换到骨骼空间),
UINT iNumBone = pSkinInfo->GetNumBones(); // 骨骼数量
pMeshContainer->pBoneOffsetMatrices = new D3DXMATRIX[iNumBone]; // 创建这个偏移矩阵的数组
if (pMeshContainer->pBoneOffsetMatrices == NULL)
{
hr = E_OUTOFMEMORY;
goto e_Exit;
}
// 保存每块骨头的偏移矩阵
for (UINT i=0; i < iNumBone; i++)
{
pMeshContainer->pBoneOffsetMatrices[i] = *(pMeshContainer->pSkinInfo->GetBoneOffsetMatrix(i));
}
// GenerateSkinnedMesh will take the general skinning information and transform it to a HW friendly version
// GenerateSkinnedMesh方法是CSkinMesh类定义的方法,将提供一般的蒙皮信息,并用一个合适版本的HW(硬件)变换它
hr = m_pSkinMesh->GenerateSkinnedMesh( pMeshContainer );
if (FAILED(hr))
goto e_Exit;
}
*ppNewMeshContainer = pMeshContainer;
pMeshContainer = NULL;
e_Exit:
SAFE_RELEASE(pd3dDevice);
// 释放pMeshContainer所分配的内存
if (pMeshContainer != NULL)
{
DestroyMeshContainer(pMeshContainer);
}
return hr;
}
//-----------------------------------------------------------------------------
// Name: CAllocateHierarchy::DestroyFrame()
// Desc: 释放框架分配的内存
//-----------------------------------------------------------------------------
HRESULT CAllocateHierarchy::DestroyFrame( LPD3DXFRAME pFrameToFree )
{
SAFE_DELETE_ARRAY( pFrameToFree->Name );
SAFE_DELETE( pFrameToFree );
return S_OK;
}
//-----------------------------------------------------------------------------
// Name: CAllocateHierarchy::DestroyMeshContainer()
// Desc: 释放网格模型容器分配的内存
//-----------------------------------------------------------------------------
HRESULT CAllocateHierarchy::DestroyMeshContainer(LPD3DXMESHCONTAINER pMeshContainerBase)
{
UINT i;
D3DXMESHCONTAINER_EX *pMeshContainer = (D3DXMESHCONTAINER_EX*)pMeshContainerBase;
SAFE_DELETE_ARRAY( pMeshContainer->Name );
SAFE_DELETE_ARRAY( pMeshContainer->pAdjacency );
SAFE_DELETE_ARRAY( pMeshContainer->pMaterials );
SAFE_DELETE_ARRAY( pMeshContainer->pBoneOffsetMatrices );
// 释放纹理数组
if (pMeshContainer->ppTextures != NULL)
{
for (i = 0; i < pMeshContainer->NumMaterials; i++)
{
SAFE_RELEASE( pMeshContainer->ppTextures[i] );
}
}
SAFE_DELETE_ARRAY( pMeshContainer->ppTextures );
SAFE_DELETE_ARRAY( pMeshContainer->ppBoneMatrixPtrs );
SAFE_RELEASE( pMeshContainer->pBoneCombinationBuf );
SAFE_RELEASE( pMeshContainer->MeshData.pMesh );
SAFE_RELEASE( pMeshContainer->pSkinInfo );
SAFE_RELEASE( pMeshContainer->pOrigMesh );
SAFE_DELETE( pMeshContainer );
return S_OK;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -