天行健 君子当自强而不息

网格模型高级技术(12)

为了方便加载.x文件中的框架和网格模型数据,Direct3D提供了一个ID3DXAllocateHierarchy接口,该接口中有4个纯虚函数:用来创建框架的CreateFrame(),创建网格容器的CreateMeshContainer(),销毁框架的DestroyFrame(),销毁网格容器的DestroyMeshContainer()。应用程序会在相应的时机自动调用这些对应的函数,以构建或者销毁对应的框架或网格模型。

This interface is implemented by the application to allocate or free frame and mesh container objects. Methods on this are called during loading and destroying frame hierarchies.

Method Description
ID3DXAllocateHierarchy::CreateFrame Requests allocation of a frame object.
ID3DXAllocateHierarchy::CreateMeshContainer Requests allocation of a mesh container object.
ID3DXAllocateHierarchy::DestroyFrame Requests deallocation of a frame object.
ID3DXAllocateHierarchy::DestroyMeshContainer Requests deallocation of a mesh container object.

 

ID3DXAllocateHierarchy::CreateFrame

Requests allocation of a frame object.

HRESULT CreateFrame(
LPCSTR Name,
LPD3DXFRAME * ppNewFrame
);

Parameters

Name
[in] Name of the frame to be created.
ppNewFrame
[out, retval] Returns the created frame object.

Return Values

The return values of this method are implemented by an application programmer. In general, if no error occurs, program the method to return D3D_OK. Otherwise, program the method to return an appropriate error message from D3DERR or D3DXERR, as this will cause D3DXLoadMeshHierarchyFromX to fail also, and return the error.

 

ID3DXAllocateHierarchy::CreateMeshContainer

Requests allocation of a mesh container object.

HRESULT CreateMeshContainer(
LPCSTR Name,
CONST D3DXMESHDATA * pMeshData,
CONST D3DXMATERIAL * pMaterials,
CONST D3DXEFFECTINSTANCE * pEffectInstances,
DWORD NumMaterials,
CONST DWORD * pAdjacency,
LPD3DXSKININFO pSkinInfo,
LPD3DXMESHCONTAINER * ppNewMeshContainer
);

Parameters

Name
[in] Name of the mesh.
pMeshData
[in] Pointer to the mesh data structure.
pMaterials
[in] Array of materials used in the mesh.
pEffectInstances
[in] Array of effect instances used in the mesh. 
NumMaterials
[in] Number of materials in the materials array.
pAdjacency
[in] Adjacency array for the mesh.
pSkinInfo
[in] Pointer to the skin mesh object if skin data is found.
ppNewMeshContainer
[out, retval] Returns the created mesh container.

Return Values

The return values of this method are implemented by an application programmer. In general, if no error occurs, program the method to return D3D_OK. Otherwise, program the method to return an appropriate error message from D3DERR or D3DXERR, as this will cause D3DXLoadMeshHierarchyFromX to fail also, and return the error.

 

ID3DXAllocateHierarchy::DestroyFrame

Requests deallocation of a frame object.

HRESULT DestroyFrame(
LPD3DXFRAME pFrameToFree
);

Parameters

pFrameToFree
[in] Pointer to the frame to be deallocated.

Return Values

The return values of this method are implemented by an application programmer. In general, if no error occurs, program the method to return D3D_OK. Otherwise, program the method to return an appropriate error message from D3DERR or D3DXERR, as this will cause D3DXLoadMeshHierarchyFromX to fail also, and return the error.

 

ID3DXAllocateHierarchy::DestroyMeshContainer

Requests deallocation of a mesh container object.

HRESULT DestroyMeshContainer(
LPD3DXMESHCONTAINER pMeshContainerToFree
);

Parameters

pMeshContainerToFree
[in] Pointer to the mesh container object to be deallocated.

Return Values

The return values of this method are implemented by an application programmer. In general, if no error occurs, program the method to return D3D_OK. Otherwise, program the method to return an appropriate error message from D3DERR or D3DXERR, as this will cause D3DXLoadMeshHierarchyFromX to fail also, and return the error.

 

cAllocateHierarchy类继承自ID3DXAllocateHierarchy接口,在cAllocateHierarchy类需要重载这4个纯虚函数以实现动画网格模型数据的加载和释放。

该类的定义如下:

class cAllocateHierarchy : public ID3DXAllocateHierarchy
{
private:
HRESULT AllocateName(LPCSTR name, LPSTR* ret_name);
public:
STDMETHOD(CreateFrame)(LPCSTR name, LPD3DXFRAME* ret_frame);
	STDMETHOD(CreateMeshContainer)(LPCSTR name, 
CONST D3DXMESHDATA* mesh_data,
CONST D3DXMATERIAL* xmaterials,
CONST D3DXEFFECTINSTANCE* effect_instances,
DWORD num_materials,
CONST DWORD* adjacency,
LPD3DXSKININFO skin_info,
LPD3DXMESHCONTAINER* ret_mesh_container);
    STDMETHOD(DestroyFrame)(THIS_ LPD3DXFRAME frame_to_free);
STDMETHOD(DestroyMeshContainer)(THIS_ LPD3DXMESHCONTAINER base_mesh_container);
};
 

函数AllocateFrame()用来为框架生成一个名称:

HRESULT cAllocateHierarchy::AllocateName(LPCSTR name, LPSTR* ret_name)
{
if(name != NULL)
{
UINT length = (UINT)strlen(name) + 1;
		*ret_name = new CHAR[length];
		if(*ret_name == NULL)
return E_OUTOFMEMORY;
		memcpy(*ret_name, name, length * sizeof(CHAR));
}
else
{
*ret_name = NULL;
}
	return S_OK;
}

 

函数CreateFrame()的作用在于生成一个新的扩展框架,并按照指定的参数为该框架命名:

HRESULT cAllocateHierarchy::CreateFrame(LPCSTR name, LPD3DXFRAME* ret_frame)
{
*ret_frame = NULL;
	D3DXFRAME_DERIVED* new_frame = new D3DXFRAME_DERIVED;
	if(new_frame == NULL)
return E_OUTOFMEMORY;
	HRESULT hr = AllocateName(name, &new_frame->Name);
	if(FAILED(hr))
{
delete new_frame;
return hr;
}
	D3DXMatrixIdentity(&new_frame->TransformationMatrix);
D3DXMatrixIdentity(&new_frame->CombinedTransformMatrix);
	new_frame->pMeshContainer   = NULL;
new_frame->pFrameSibling = NULL;
new_frame->pFrameFirstChild = NULL;
	*ret_frame = new_frame;
	return S_OK;
}

 

在一个框架创建好后,需要创建该框架的网格容器,这通过函数CreateMeshContainer()来实现:

HRESULT cAllocateHierarchy::CreateMeshContainer(LPCSTR name, 
CONST D3DXMESHDATA* mesh_data,
CONST D3DXMATERIAL* xmaterials,
CONST D3DXEFFECTINSTANCE* effect_instances,
DWORD num_materials,
CONST DWORD* adjacency,
LPD3DXSKININFO skin_info,
LPD3DXMESHCONTAINER* ret_mesh_container)
{
*ret_mesh_container = NULL;
	if(mesh_data->Type != D3DXMESHTYPE_MESH)
return E_FAIL;
	ID3DXMesh* mesh_ptr = mesh_data->pMesh;
DWORD fvf = mesh_ptr->GetFVF();
	if(fvf == 0)
return E_FAIL;
	// create a mesh container and zero it
	D3DXMESHCONTAINER_DERIVED* new_mesh_container = new D3DXMESHCONTAINER_DERIVED;
	if(new_mesh_container == NULL)
return E_OUTOFMEMORY;
	memset(new_mesh_container, 0, sizeof(D3DXMESHCONTAINER_DERIVED));
	// copy mesh name
	HRESULT hr = AllocateName(name, &new_mesh_container->Name);
	if(FAILED(hr))
{
DestroyMeshContainer(new_mesh_container);
return hr;
}
	IDirect3DDevice9* device;
mesh_ptr->GetDevice(&device);
	new_mesh_container->MeshData.Type = D3DXMESHTYPE_MESH;
	// be sure mesh contain normal
if(!(fvf & D3DFVF_NORMAL))
{
hr = mesh_ptr->CloneMeshFVF(mesh_ptr->GetOptions(), fvf | D3DFVF_NORMAL, device,
&new_mesh_container->MeshData.pMesh);
		if(FAILED(hr))
{
release_com(device);
DestroyMeshContainer(new_mesh_container);
return hr;
}
		mesh_ptr = new_mesh_container->MeshData.pMesh;
D3DXComputeNormals(mesh_ptr, NULL);
}
else
{
new_mesh_container->MeshData.pMesh = mesh_ptr;
mesh_ptr->AddRef(); // !! important, so DestroyMeshContainer() will not crash.
}
	// load materials and textures
	UINT num_faces = mesh_ptr->GetNumFaces();
	new_mesh_container->NumMaterials = max(1, num_materials);
new_mesh_container->pMaterials = new D3DXMATERIAL[new_mesh_container->NumMaterials];
new_mesh_container->ppTextures = new LPDIRECT3DTEXTURE9[new_mesh_container->NumMaterials];
new_mesh_container->pAdjacency = new DWORD[num_faces * 3];
	if((new_mesh_container->pAdjacency == NULL) || (new_mesh_container->pMaterials == NULL) ||
(new_mesh_container->ppTextures == NULL))
{
release_com(device);
DestroyMeshContainer(new_mesh_container);
return E_OUTOFMEMORY;
}
	memcpy(new_mesh_container->pAdjacency, adjacency, sizeof(DWORD) * num_faces * 3);
memset(new_mesh_container->ppTextures, 0, sizeof(LPDIRECT3DTEXTURE9) * new_mesh_container->NumMaterials);
	D3DXMATERIAL* xmaterials_ptr = new_mesh_container->pMaterials;
	if(num_materials > 0)
{
memcpy(xmaterials_ptr, xmaterials, sizeof(D3DXMATERIAL) * num_materials);
xmaterials_ptr->MatD3D.Ambient = xmaterials_ptr->MatD3D.Diffuse;
		for(UINT i = 0; i < num_materials; i++)
{
if(xmaterials_ptr[i].pTextureFilename != NULL)
{
WCHAR w_texture_path[MAX_PATH];
WCHAR w_filename[MAX_PATH];
				RemovePathFromFileName(xmaterials_ptr[i].pTextureFilename, w_filename);
DXUTFindDXSDKMediaFileCch(w_texture_path, MAX_PATH, w_filename);
				if(FAILED( D3DXCreateTextureFromFileW(device, w_texture_path, &new_mesh_container->ppTextures[i]) ))
new_mesh_container->ppTextures[i] = NULL;
}
}
}
else
{
xmaterials_ptr[0].pTextureFilename = NULL;
memset(&xmaterials_ptr[0].MatD3D, 0, sizeof(D3DMATERIAL9));
		xmaterials_ptr[0].MatD3D.Diffuse.r = 0.5f;
xmaterials_ptr[0].MatD3D.Diffuse.r = 0.5f;
xmaterials_ptr[0].MatD3D.Diffuse.b = 0.5f;
xmaterials_ptr[0].MatD3D.Specular = xmaterials_ptr[0].MatD3D.Diffuse;
xmaterials_ptr[0].MatD3D.Ambient = xmaterials_ptr[0].MatD3D.Diffuse;
}
	release_com(device);
	*ret_mesh_container = new_mesh_container;
	return S_OK;
}

在此实现的骨骼动画网格模型中没有涉及到蒙皮信息,所以在CreateMeshContainer()函数中没有处理参数skin_info指向的蒙皮信息。

 

函数DestroyFrame()只有一个参数指向准备释放的框架对象:

HRESULT cAllocateHierarchy::DestroyFrame(LPD3DXFRAME frame_to_free) 
{
SAFE_DELETE_ARRAY(frame_to_free->Name);
SAFE_DELETE(frame_to_free);
	return S_OK;
}

 

函数DestroyMeshContainer()也只有一个参数指向将要释放的网格容器对象:

HRESULT cAllocateHierarchy::DestroyMeshContainer(LPD3DXMESHCONTAINER base_mesh_container)
{
if(base_mesh_container == NULL)
return S_OK;
	D3DXMESHCONTAINER_DERIVED* mesh_container = (D3DXMESHCONTAINER_DERIVED*) base_mesh_container;
	SAFE_DELETE_ARRAY(mesh_container->Name);
SAFE_DELETE_ARRAY(mesh_container->pAdjacency);
SAFE_DELETE_ARRAY(mesh_container->pMaterials);
	if(mesh_container->ppTextures != NULL)
{
for(UINT i = 0; i < mesh_container->NumMaterials; i++)
release_com(mesh_container->ppTextures[i]);
}
	SAFE_DELETE_ARRAY(mesh_container->ppTextures);
	SAFE_RELEASE(mesh_container->MeshData.pMesh);
SAFE_RELEASE(mesh_container->pSkinInfo);
	SAFE_DELETE(mesh_container);
	return S_OK;
}

posted on 2008-06-11 14:56 lovedday 阅读(2140) 评论(3)  编辑 收藏 引用

评论

# re: 网格模型高级技术(12) 2010-04-04 11:58 chuckey

谁写的这种文章,也太无聊了,全就抄了一下.  回复  更多评论   

# re: 网格模型高级技术(12) 2010-07-14 14:52 骡子宝

博主能出来解释一下吗?看得云里雾里的。
FRAME是每个骨骼创建一个FRAME吗?每个FRMAE都创建一个CONTAINER吗?  回复  更多评论   

# re: 网格模型高级技术(12) 2011-05-22 13:04

看看  回复  更多评论   


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理


公告

导航

统计

常用链接

随笔分类(178)

3D游戏编程相关链接

搜索

最新评论