一、UNICODE字符串和MBCS字符串的相互转换:

1.从MBCS到UNICODE的转换

BOOL DXUTMByteToWChar( LPCSTR lpcszStr, LPWSTR lpwszStr, DWORD dwSize )
{
DWORD dwMinSize;
dwMinSize = MultiByteToWideChar (CP_ACP, 0, lpcszStr, -1, NULL, 0);
if(dwSize < dwMinSize)
{
return FALSE;
}
MultiByteToWideChar (CP_ACP, 0, lpcszStr, -1, lpwszStr, dwMinSize);
return TRUE;
}

2.从UNICODE到MBCS的转换

BOOL DXUTWCharToMByte( LPCWSTR lpcwszStr, LPSTR lpszStr, DWORD dwSize )
{
DWORD dwMinSize;
dwMinSize = WideCharToMultiByte(CP_OEMCP,NULL,lpcwszStr,-1,NULL,0,NULL,FALSE);
if(dwSize < dwMinSize)
{
return FALSE;
}
WideCharToMultiByte(CP_OEMCP,NULL,lpcwszStr,-1,lpszStr,dwSize,NULL,FALSE);
return TRUE;
}

二、IDirectXFile系列接口的应用

对于一些需要传递指针的函数(如获取对象名字),在每次调用时候都要手动创建一块内存。为了方便使用可以作一下改进:

1.IDirectXFileObject::GetName的改进(缺点:函数返回的指针不能保存,因为每调用一次都有可能改变静态内存块里面的字符数据)

static WCHAR XGetObjName_nameW[1024];
LPCWSTR XGetObjName( IDirectXFileObject* pObj, bool bReturnUniqueName )//must not save the return value for further use!
{
if(NULL == pObj)
return NULL;

static char XGetObjName_name[512];
static UINT i = 1;// to identify no name obj

ZeroMemory(XGetObjName_name, sizeof(XGetObjName_name));
ZeroMemory(XGetObjName_nameW, sizeof(XGetObjName_nameW));
DWORD len = 0;

if (SUCCEEDED( pObj->GetName(NULL, &len) ))
{
if (len > 0)
{
pObj->GetName(XGetObjName_name, &len);
}
else if(bReturnUniqueName)
{
sprintf_s(XGetObjName_name, "no name: %dth", i++);
}
}
if( DXUTMByteToWChar(XGetObjName_name, XGetObjName_nameW, 1024) )
return XGetObjName_nameW;

return NULL;
}
2.IDirectXFileData::GetType的改进

const GUID* XGetObjType( IDirectXFileData* pData )
{
if(NULL == pData)
return NULL;

const GUID* pGUID = NULL;

if (SUCCEEDED( pData->GetType(&pGUID) ) )
return pGUID;
else
return NULL;
}

3.IDirectXFileData::GetData的改进

void* XGetObjectData(IDirectXFileData *pDataObj, DWORD *pSize)
{
void *TemplateData = NULL;
DWORD TemplateSize = 0;

if(pDataObj == NULL)
return NULL;


HRESULT hr = pDataObj->GetData(NULL,&TemplateSize,(PVOID*)&TemplateData);
if (FAILED(hr))
{
*pSize = 0;
return NULL;
}
if(pSize != NULL)
*pSize = TemplateSize;

return TemplateData;
}

设计类或函数时 ppUserData / ppUserContext 和 参数默认值 的合理使用

很多情况下我们并不清楚函数调用者的具体应用,这时候用一个指针来传递用户数据是是最好的选择,因为指针一可指向任意的一块数据,调用者在需要的时候可以将这个指转化为适当的数据类型。

1.bool CXFileParserBase::Parse( LPCSTR fileName, void** ppUserData = NULL );

2.bool CXFileParserBase::ParseObject( IDirectXFileData* pDataObj, IDirectXFileData* pParentDataObj, DWORD depth, bool bRef, void** ppUserData = NULL);
3.bool CXFileParserBase::ParseChildObjects( IDirectXFileData* pDataObj, DWORD depth, bool bRef, void** ppUserData = NULL);

备注:X*类型的地址同样能转化成void**类型!

如:

void** ppUserDataTem = (void**)(&m_meshInfo.meshes.back());
return CXFileParserBase::ParseChildObjects(pDataObj, depth, bRef, ppUserDataTem);

递归调用的注意事项

在解析XFile时候用到了大量的递归调用(CXFileParserBase::ParseObject会被多次递归调用),在递归调用时最重要的是要理清思路,把握好递归内部函数的返回时机!

字符串数据的获取方法

DWORD* pData = (DWORD*)XGetObjectData(pDataObj);
char* pStr = (char*)(*pData);

在函数内部判断此函数是否被同一个对象调用最好是在内部保存一个静态的对象地址

……

static UINT index = 0;
static DWORD* preMtrlIndexG = NULL;
XFileMeshData* pMD = (XFileMeshData*)ppUserData;
if (preMtrlIndexG != pMD->pMtrlIndexG)
{
index = 0; preMtrlIndexG = pMD->pMtrlIndexG;
}
wstring mtrlName = XGetObjName(pDataObj);//get the name of the material that it referenced
UINT mtrlIndexG = m_meshInfo.GetMtrlIndex(mtrlName);//get the exact material index
pMD->pMtrlIndexG[index++] = mtrlIndexG;// set material global indices

……

如何删除vector中指定元素(符合某种条件的元素)

……

//最后删除空mesh
vector<XFileMeshData>::iterator iTer = m_meshInfo.meshes.begin();
for ( ; iTer != m_meshInfo.meshes.end() ; )
{
if ( iTer->meshName == L"" || NULL == iTer->pMesh || iTer->numSubsets == 0 || 0 == iTer->mtrlIndex.size())
{
iTer = m_meshInfo.meshes.erase(iTer);
m_meshInfo.numMeshes--;
}
else
{
iTer++;
}
}

……

Pandasofts DirectX 导出时注意事项和问题:

Optimize mesh: none (adviced option:)如果选择optimezed选项用CXFileMesh类解析时会导致部分法线错误!
待解决问题:如何导出法线贴图

posted on 2011-09-12 10:07  yaoyao_cn  阅读(413)  评论(0编辑  收藏  举报