#pragma once /** @file Utility.h @brief 常用全局函数
*	Copyright (c) 2007,第九城市游戏研发中心
*	All rights reserved.
*
*	当前版本:0.1
*	作    者:Shi Yazheng
*	完成日期:2008-01-16
*
*	取代版本:
*	作    者:
*	完成日期:
*
*	注    意:Gamebryo 使用右手坐标系,X坐标正方向为屏幕右方向,Y正方向为屏幕内,Z正方向指向屏幕上方向
*			  所有 2D 测试如没有特别说明均指 XY 平面
*/ #ifndef UTILITY_H #define UTILITY_H #include //add by hemeng 080512 #include //add by hemeng 080512 #include ////add by hemeng 080513 #include #include "NiBoxBV.h" #ifndef CODE_INGAME #include "SceneDesignerConfig.h" #include #include #include "NiCollision.h" #include #include #include "math.h" #include //#ifndef D3D_DEBUG_INFO //#define D3D_DEBUG_INFO //#endif #endif /** *
功能说明:测试一个点是否在AABB内,2D *
可访问性:global *
注 释: * @param point[in] 测试点 * @param bound[in] AABB定义 * @return 无 */ static bool PointLocatedInAABB_2D( const NiPoint3& point, const NiBoxBV& bound ) { float fx = NiAbs( point.x - bound.GetCenter().x ); float fy = NiAbs( point.y - bound.GetCenter().y ); return ( fx <= bound.GetExtent(0) && fy <= bound.GetExtent(1) ); } /** *
功能说明:测试一个点是否在AABB内,3D *
可访问性:global *
注 释: * @param point[in] 测试点 * @param bound[in] AABB定义 * @return 无 */ static bool PointLocatedInAABB_3D( const NiPoint3& point, const NiBoxBV& bound ) { float fx = NiAbs( point.x - bound.GetCenter().x ); float fy = NiAbs( point.x - bound.GetCenter().y ); float fz = NiAbs( point.z - bound.GetCenter().z ); const float* pfExtends = bound.GetExtents(); if (fx>pfExtends[0] || fy>pfExtends[1] || fz>pfExtends[2]) // 使用 || 判断比 && 效率高 { return false; } else { return true; } //return ( fx <= bound.GetExtent(0) && fy <= bound.GetExtent(1) && fz <= bound.GetExtent(2) ); } /** *
功能说明:测试Bounding Sphere 与 AABB 是否相交 *
可访问性:global *
注 释:非精确判断,只判断BS 的AABB 与 AABB 是否相交 * @param bs[in] 被测试的 Bounding Sphere * @param aabb[in] 被测试的 AABB * @return 0 - 不相交, 1 - 部分相交, 2 - bs 完全在 aabb 内 */ static unsigned char BSIntersectAABB_2D( const NiBound& bs, const NiBoxBV& aabb ) { if ( bs.GetCenter().x+bs.GetRadius() < aabb.GetCenter().x-aabb.GetExtent(0) // X 方向 || bs.GetCenter().x-bs.GetRadius() > aabb.GetCenter().x+aabb.GetExtent(0) || bs.GetCenter().y+bs.GetRadius() < aabb.GetCenter().y-aabb.GetExtent(1) // Y 方向 || bs.GetCenter().y-bs.GetRadius() > aabb.GetCenter().y+aabb.GetExtent(1)) { // 某轴上存在A最大坐标小于B最小坐标 return 0; // 不相交 } else if ( bs.GetCenter().x-bs.GetRadius() > aabb.GetCenter().x-aabb.GetExtent(0) && bs.GetCenter().x+bs.GetRadius() < aabb.GetCenter().x+aabb.GetExtent(0) && bs.GetCenter().y-bs.GetRadius() > aabb.GetCenter().y-aabb.GetExtent(1) && bs.GetCenter().y+bs.GetRadius() < aabb.GetCenter().y+aabb.GetExtent(1)) { // 所有轴上A最小大于B最小,A最大小于B最大 return 2; // A 在 B 内 } else { // 部分相交 return 1; } } /** *
功能说明:测试AABB 与 平面的位置关系 *
可访问性:global *
注 释:未测试 * @param bs[in] 被测试的 AABB * @param aabb[in] 被测试的平面 * @return 0 - NO_SIDE, 1 - POSITIVE_SIDE, 2 - NEGATIVE_SIDE */ static int AABBIntersectPlane(const NiBoxBV& aabb, const NiPlane& plane) { float fMinDist = FLT_MAX; float fMaxDist = FLT_MIN; //NiPoint3 kMinVert, kMaxVert; // 找出 aabb 8个顶点中到 plane 带符号距离中最远的与最近的 for (int x=-1; x<=1; x+=2) { for (int y=-1; y<=1; y+=2) { for (int z=-1; z<=1; z+=2) { NiPoint3 vert(aabb.GetCenter().x+aabb.GetExtent(0)*x, aabb.GetCenter().y+aabb.GetExtent(1)*y, aabb.GetCenter().z+aabb.GetExtent(2)*z); float fDist = plane.Distance(vert); if (fDistfMaxDist) { fMaxDist = fMinDist; } if (fMinDist*fMaxDist < 0.0f) { //有两个顶点分别在平面两侧,aabb与平面相交 return NiPlane::NO_SIDE; } } } } // end for if (fMinDist > 0.0f) // 正方向 { return NiPlane::POSITIVE_SIDE; } if (fMaxDist < 0.0f) // 负方向 { return NiPlane::NEGATIVE_SIDE; } return NiPlane::NO_SIDE; } /** *
功能说明:对 kColorA 和 kColorB 按照混合因子 fFactor 进行线性差值 *
可访问性:global *
注 释: * @param kColorA[in] The first-color point value. * @param kColorB[in] The second-color point value. * @param fFactor[in] A value that linearly interpolates between the the kColorA parameter and the kColorB parameter * @return 差值结果 */ static NiColor ColorLerp(const NiColor &kColorA, const NiColor &kColorB, float fFactor) { return (kColorA*fFactor + kColorB*(1.0f-fFactor)); } static int StrFindLast(const char* pszIn, const char c) { int iLen = strlen(pszIn); for (int i=iLen; i>=0; i--) { if (pszIn[i] == c) { return i; } } return -1; } /** add by hemeng 080512 *
功能说明:对输入IDirect3DTexture9进行所选定的压缩 *
可访问性:global *
注 释: * @param IDirect3DSurface9 * pSrcSurface 源贴图指针 * @param D3DFORMAT Format 目标压缩格式 * @return IDirect3DSurface9 * 目标压缩后贴图指针,操作失败则返回NULL */ static IDirect3DSurface9 * CompressSurface(IDirect3DSurface9 *pSrcSurface, D3DFORMAT Format) { IDirect3DSurface9 *pDesSurface = NULL; //声明目标surface IDirect3DTexture9 *pDesTexture = NULL; //声明目标texture用于初始化surface D3DSURFACE_DESC DescSrc; //声明源贴图描述用于初始化目标 HRESULT hr; //错误变量 hr = pSrcSurface->GetDesc( & DescSrc ); if( FAILED(hr)) { ::MessageBox(NULL, "获取Surface描述失败", "纹理压缩", MB_OK); return NULL; } //获取及初始化设备 NiDX9Renderer* pkDX9Renderer = NiDynamicCast(NiDX9Renderer, NiDX9Renderer::GetRenderer()); const LPDIRECT3DDEVICE9 d3dDevice = pkDX9Renderer->GetD3DDevice(); //LPDIRECT3DDEVICE9 d3dDevice = NULL; //Format 为所需设置的压缩格式DXT5为:D3DFMT_DXT5 hr = d3dDevice->CreateTexture( DescSrc.Width, DescSrc.Height, 0, DescSrc.Usage, Format, DescSrc.Pool, &pDesTexture, NULL); if( FAILED( hr ) ) { ::MessageBox(NULL, "创建D3DFMT_DXT5纹理失败", "Textures.exe", MB_OK); return NULL; } hr = pDesTexture->GetSurfaceLevel( 0, &pDesSurface ); if( FAILED( hr ) ) { ::MessageBox(NULL, "创建D3DFMT_DXT5纹理surface失败", "Textures.exe", MB_OK); return NULL; } hr = D3DXLoadSurfaceFromSurface( pDesSurface, NULL, NULL, pSrcSurface, NULL, NULL, D3DX_FILTER_TRIANGLE | D3DX_FILTER_DITHER, 0); if( FAILED( hr ) ) { ::MessageBox(NULL, "复制surface失败","Textures.exe", MB_OK); return NULL; } return pDesSurface; } #ifndef CODE_INGAME static NiFile* TextureFileCreateFunc(const char *pcName, NiFile::OpenMode eMode, unsigned int uiSize) { int iLen = strlen(pcName); char szExtName[5]; char szAppPath[MAX_PATH]; char szFinalPath[MAX_PATH]; ZeroMemory(szAppPath, MAX_PATH*sizeof(char)); NiPath::GetExecutableDirectory(szAppPath, MAX_PATH); szExtName[0] = tolower(pcName[iLen-4]); szExtName[1] = tolower(pcName[iLen-3]); szExtName[2] = tolower(pcName[iLen-2]); szExtName[3] = tolower(pcName[iLen-1]); szExtName[4] = '\0'; if (strcmp(szExtName, ".dds") == 0 || strcmp(szExtName, ".bmp") == 0 || strcmp(szExtName, ".tga") == 0 || strcmp(szExtName, ".png") == 0 || strcmp(szExtName, ".jpg") == 0 || strcmp(szExtName, ".hdr") == 0 ) { if (!NiFile::Access(pcName, eMode)) { vector& texPathList = CSceneDesignerConfig::GetInstance()->GetTexturePathList(); for (unsigned int i=0; iGetTextureManager() ->PrepareTextureForRendering( pkTexture, bChanged, bMipMap, bNonPow2 ); HRESULT hr = D3DXSaveTextureToFile( pszFileName, D3DXIFF_DDS, pD3DTex, NULL ); return ( hr!= E_FAIL ); } static bool SaveTextureToJPG(NiTexture* pkTexture, const char* pszFileName) { if (pkTexture==NULL || pszFileName==NULL) { return false; } bool bChanged = true; bool bMipMap = false; bool bNonPow2 = false; NiDX9Renderer* pRenderer = NiDynamicCast( NiDX9Renderer, NiRenderer::GetRenderer() ); LPDIRECT3DBASETEXTURE9 pD3DTex = pRenderer->GetTextureManager() ->PrepareTextureForRendering( pkTexture, bChanged, bMipMap, bNonPow2 ); HRESULT hr = D3DXSaveTextureToFile( pszFileName, D3DXIFF_JPG, pD3DTex, NULL ); return ( hr!= E_FAIL ); } static void GetVerticesFromGeometry( NiGeometry * pGeometry, NiTransform& kAccuTrans, vector< NiPoint3 >& vPointsLocal, vector< NiPoint3 >& vPointsWorld) { NiTransform kLocalTrans = kAccuTrans * pGeometry->GetLocalTransform(); if (NiIsKindOf(NiParticleSystem, pGeometry) && ((NiParticleSystem*)pGeometry)->GetWorldSpace()) { // 先忽略所有粒子 //NiPoint3 * pVertices = pGeometry->GetVertices(); //if ( !pVertices ) // return; //NiParticleSystem* pPS = ((NiParticleSystem*)pGeometry); ////pPS->GetActiveVertexCount() //for ( UINT nIndex = 0; nIndex < pGeometry->GetVertexCount() ; nIndex ++ ) //{ // if (pVertices[nIndex].x!=0.0f || pVertices[nIndex].y!=0.0f && pVertices[nIndex].z!=0.0f) // { // //vPointsWorld.push_back( pVertices[nIndex] );//kLocalTrans * // } //} } else { NiPoint3 * pVertices = pGeometry->GetVertices(); if ( !pVertices ) return; for ( UINT nIndex = 0; nIndex < pGeometry->GetActiveVertexCount(); nIndex ++ ) { vPointsLocal.push_back( pGeometry->GetWorldTransform() * pVertices[nIndex] );// } } } static void GetVerticesFromNode( NiAVObject * pObj, NiTransform& kAccuTrans, vector< NiPoint3 >& vPointsLocal, vector& vPointsWorld ) { NiTransform kLocalTrans = kAccuTrans * pObj->GetLocalTransform(); if (NiIsKindOf(NiNode, pObj)) { NiNode* pNode = (NiNode*)pObj; for ( UINT nIndex = 0; nIndex < pNode->GetArrayCount(); nIndex ++ ) { NiAVObject * pChild = pNode->GetAt( nIndex ); if ( !pChild ) continue; if ( NiIsKindOf( NiNode, pChild ) ) { GetVerticesFromNode( ( NiNode * ) pChild, kLocalTrans, vPointsLocal, vPointsWorld ); } else if ( NiIsKindOf( NiGeometry, pChild ) && !pChild->GetAppCulled() ) { GetVerticesFromGeometry( ( NiGeometry * )pChild, kLocalTrans, vPointsLocal, vPointsWorld ); } } } else if(NiIsKindOf(NiGeometry, pObj)) { GetVerticesFromGeometry( ( NiGeometry * )pObj, kLocalTrans, vPointsLocal, vPointsWorld ); } } static void CreateAABBByPoints( const vector& vPoints, NiBox& box ) { if (vPoints.size() == 0) { return; } float fMinX, fMaxX, fMinY, fMaxY, fMinZ, fMaxZ; fMinX = fMaxX = vPoints[0].x; fMinY = fMaxY = vPoints[0].y; fMinZ = fMaxZ = vPoints[0].z; NiPoint3 vCenter = vPoints[0]; for ( UINT i = 1; i < vPoints.size(); i++ ) { if (vPoints[i].x < fMinX) fMinX = vPoints[i].x; else if (vPoints[i].x > fMaxX) fMaxX = vPoints[i].x; if (vPoints[i].y < fMinY) fMinY = vPoints[i].y; else if (vPoints[i].y > fMaxY) fMaxY = vPoints[i].y; if (vPoints[i].z < fMinZ) fMinZ = vPoints[i].z; else if (vPoints[i].z > fMaxZ) fMaxZ = vPoints[i].z; } vCenter = 0.5f * ( NiPoint3( fMinX, fMinY, fMinZ ) + NiPoint3( fMaxX, fMaxY, fMaxZ ) ); box.m_afExtent[0] = 0.5f * (fMaxX - fMinX); box.m_afExtent[1] = 0.5f * (fMaxY - fMinY); box.m_afExtent[2] = 0.5f * (fMaxZ - fMinZ); box.m_kCenter = vCenter; } static bool CreateAABBFromNode( NiAVObject * pObj, NiBox& aabb ) { vector< NiPoint3 > vPointsLocal; // 本地空间的顶点 vector< NiPoint3 > vPointsWorld; // 世界坐标的顶点 NiTransform transfrom; transfrom.MakeIdentity(); transfrom.m_Translate = pObj->GetTranslate(); transfrom.m_Rotate = pObj->GetRotate(); float fScale = pObj->GetScale(); pObj->SetTranslate( NiPoint3::ZERO ); pObj->SetRotate( NiMatrix3::IDENTITY ); pObj->SetScale(1.0f); pObj->Update(0.0f); pObj->Update(100.0f); NiTransform kAccuTrans; // 累积的本地变换 kAccuTrans.MakeIdentity(); GetVerticesFromNode( pObj, kAccuTrans, vPointsLocal, vPointsWorld ); NiTransform invTrans; transfrom.Invert(invTrans); for (unsigned int i=0; iSetTranslate( transfrom.m_Translate ); pObj->SetRotate( transfrom.m_Rotate ); pObj->SetScale( fScale ); pObj->Update( 0.0f ); if (vPointsLocal.size() >= 3) { // 如果物件顶点数量足够多,用顶点计算包围盒 CreateAABBByPoints( vPointsLocal, aabb ); for (int i = 0; i<= 2; i++) { aabb.m_afExtent[i] = max(aabb.m_afExtent[i], 1.0f); } } else { // 否则使用物件的包围球计算包围盒 pObj->UpdateNodeBound(); NiBound kBound = pObj->GetWorldBound(); kBound.Update(kBound, invTrans); aabb.m_kCenter = kBound.GetCenter(); for (int i = 0; i<= 2; i++) { aabb.m_afExtent[i] = max(kBound.GetRadius(), 1.0f); } } return true; } /// 根据名称从 NiEntityInterface 中找出 Component static NiEntityComponentInterface* GetComponentFromEntityByName(NiEntityInterface* pkEntity, NiFixedString kComponentName) { for (unsigned int i=0; iGetComponentCount(); i++) { NiEntityComponentInterface* pkComponent = pkEntity->GetComponentAt(i); if (pkComponent->GetName() == kComponentName) { return pkComponent; } } return NULL; } static NiSourceTexturePtr ConvertRenderedTextureToSource(NiRenderedTexture* pkRenderedTex) { if (pkRenderedTex == NULL) { return NULL; } if (!SaveTextureToDDS(pkRenderedTex, "_tmpTex.dds")) { return NULL; } NiSourceTexture::SetDestroyAppDataFlag( false ); NiSourceTexturePtr spSourceTex = NiSourceTexture::Create("_tmpTex.dds"); spSourceTex->SetStatic( false ); NiSourceTexture::SetDestroyAppDataFlag( true ); spSourceTex->LoadPixelDataFromFile(); return spSourceTex; } static void ExtractFileNameFromPath(const char* pszPath, char* pszFileName) { assert(pszPath&&pszFileName); int iLen = strlen(pszPath); const char* pcIter = pszPath + iLen - 1; // 从后向前找到 \ 或者 / 的位置 while(pcIter != pszPath) { if (*pcIter=='\\' || *pcIter=='/') { pcIter++; break; } pcIter--; } strcpy_s(pszFileName, MAX_PATH, pcIter); return; } static float Lerp(float fStart, float fEnd, float fInterpolate) { return fStart + (fEnd-fStart)*fInterpolate; } // 判断某顶点是否在三角形区域内 static bool IsVertexInTriangle(NiPoint3& kP0, NiPoint3& kP1, NiPoint3& kP2, NiPoint3& kVertex) { // 如果某顶点发出的两条边与该顶点与目标顶点构成的边叉乘结果 Z 方向一致.该顶点在三角形外 // P0 { NiPoint3 kL0 = kP1 - kP0; NiPoint3 kL1 = kP2 - kP0; NiPoint3 kL2 = kVertex - kP0; if (kL0.Cross(kL2).z * kL1.Cross(kL2).z > 0) { return false; } } // P1 { NiPoint3 kL0 = kP0 - kP1; NiPoint3 kL1 = kP2 - kP0; NiPoint3 kL2 = kVertex - kP1; if (kL0.Cross(kL2).z * kL1.Cross(kL2).z > 0) { return false; } } // P2 { NiPoint3 kL0 = kP0 - kP2; NiPoint3 kL1 = kP1 - kP2; NiPoint3 kL2 = kVertex - kP2; if (kL0.Cross(kL2).z * kL1.Cross(kL2).z > 0) { return false; } } return true; } // 将 iSrc 的低4位拷贝到 iDest 的低4位 static void CopyLowFourBit(int &iDest, int iSrc) { // 地表属性只能操作 iTerrainProperty 的低 4 位 iDest &= 0xFFFFFFF0; // 低4位全设为 0 iDest |= (iSrc & 0x0000000F); // 拷贝 iProperty 低4位 } // 将 rgb 空间的颜色 转换到 YCbCr 空间 static void RGB2YCrCb(byte r, byte g, byte b, byte& Y, byte& Cr, byte& Cb) { Y = min(255, max(0, (byte)(0.257f*r + 0.504f*g + 0.098f*b + 16))); Cr = min(255, max(0, (byte)(0.439f*r - 0.368f*g - 0.071f*b + 128))); Cb = min(255, max(0, (byte)(-0.148f*r - 0.291f*g + 0.439f*b + 128))); } // YCbCr 空间颜色转换到 RGB 空间 static void YCrCb2RGB(byte Y, byte Cr, byte Cb, byte& r, byte& g, byte& b) { r = min(255, max(0, (byte)(1.164f*(Y-16) + 1.596f*(Cr-128)))); g = min(255, max(0, (byte)(1.164f*(Y-16) - 0.813f*(Cr-128) - 0.392f*(Cb-128)))); b = min(255, max(0, (byte)(1.164f*(Y-16) + 2.017f*(Cb-128)))); } // 将 rgb 空间的颜色 转换到 YCbCr 空间 static void RGB2YUV(byte r, byte g, byte b, int& Y, int& U, int& V) { Y = (byte)(0.299f*r + 0.587f*g + 0.114f * b); U = (byte)(-0.147 * r - 0.289 * g + 0.436 * b); V = (byte)(0.615*r - 0.515*g - 0.100 * b); } // YCbCr 空间颜色转换到 RGB 空间 static void YUV2RGB(int Y, int U, int V, byte& r, byte& g, byte& b) { r = (byte)(Y + 1.14 * V); g = (byte)(Y - 0.39 * U - 0.58 * V); b = (byte)(Y + 2.03 * U); } // RGB 到 LAB 转换 static void RGB2Lab(float R, float G, float B, float& L, float& a, float& b) { static const float BLACK = 20.0f; static const float YELLOW = 70.0f; float X, Y, Z, fX, fY, fZ; // 从 RGB 空间转换到 XYZ 空间 X = 0.412453f*R + 0.357580f*G + 0.180423f*B; Y = 0.212671f*R + 0.715160f*G + 0.072169f*B; Z = 0.019334f*R + 0.119193f*G + 0.950227f*B; X /= (255 * 0.950456f); Y /= 255.0f; Z /= (255 * 1.088754f); if (Y > 0.008856f) { fY = powf(Y, 1.0f/3.0f); L = 116.0f*fY - 16.0f; } else { fY = 7.787f * Y + 16.0f/116.0f; L = 903.3f * Y; } if (X > 0.008856f) { fX = powf(X, 1.0f / 3.0f); } else { fX = 7.787f * X + 16.0f / 116.0f; } if (Z > 0.008856f) { fZ = powf(Z, 1.0f/3.0f); } else { fZ = 7.787f*Z + 16.0f/116.0f; } a = 500.0f * (fX - fY); b = 200.0f * (fY - fZ); if (L < BLACK) { a *= expf((L-BLACK) / (BLACK/4)); b *= expf((L-BLACK) / (BLACK/4)); L = BLACK; } if (b > YELLOW) { b = YELLOW; } } // Lab 到 RGB static void Lab2RGB(float L, float a, float b, float& R, float& G, float& B) { float X, Y, Z, fX, fY, fZ; float RR, GG, BB; fY = powf((L + 16.0f) / 116.0f, 3.0f); if (fY < 0.008856f) { fY = L / 903.3f; } Y = fY; if (fY > 0.008856f) { fY = powf(fY, 1.0f/3.0f); } else { fY = 7.787f * fY + 16.0f/116.0f; } fX = a / 500.0f + fY; if (fX > 0.206893f) { X = powf(fX, 3.0f); } else { X = (fX - 16.0f/116.0f) / 7.787f; } fZ = fY - b/200.0f; if (fZ > 0.206893f) { Z = powf(fZ, 3.0f); } else { Z = (fZ - 16.0f/116.0f) / 7.787f; } X *= (0.950456f * 255); Y *= 255; Z *= (1.088754f * 255); RR = 3.240479f*X - 1.537150f*Y - 0.498535f*Z; GG = -0.969256f*X + 1.875992f*Y + 0.041556f*Z; BB = 0.055648f*X - 0.204043f*Y + 1.057311f*Z; R = (float)(RR<0 ? 0 : RR>255 ? 255 : RR); G = (float)(GG<0 ? 0 : GG>255 ? 255 : GG); B = (float)(BB<0 ? 0 : BB>255 ? 255 : BB); } // 是否存在指定属性 [9/25/2009 hemeng] static bool ExistsExtraData(NiAVObject* pkAVObj, const char* szExtraDataName) { if (pkAVObj == NULL) { return false; } // 判断 extra data 中是否有 zMode10 NiExtraData* pkExtraData = pkAVObj->GetExtraData("UserPropBuffer"); if (pkExtraData != NULL) { NiStringExtraData* pkStrData = NiStaticCast(NiStringExtraData, pkExtraData); if (pkStrData != NULL) { const NiFixedString& strValue = pkStrData->GetValue(); if (strValue.ContainsNoCase(szExtraDataName)) { return true; } } } return false; } //------------------------------------------------------------------------------ static LPDIRECT3DTEXTURE9 ConvertTextureToDDS(LPDIRECT3DTEXTURE9 pSrcTex, D3DFORMAT dxtFormat) { if (pSrcTex == NULL) return NULL; NiDX9Renderer* pkDX9Renderer = NiDynamicCast(NiDX9Renderer, NiRenderer::GetRenderer()); if (pkDX9Renderer == NULL) return false; LPDIRECT3DDEVICE9 pDevice = pkDX9Renderer->GetD3DDevice(); if (pDevice == NULL) return false; bool bResult = true; LPDIRECT3DSURFACE9 pSrcSurface = NULL; LPDIRECT3DTEXTURE9 pDestTex = NULL; LPDIRECT3DSURFACE9 pDestSurface = NULL; D3DSURFACE_DESC desc; pSrcTex->GetLevelDesc(0, &desc); UINT uiWidth = desc.Width; UINT uiHeight = desc.Height; // 创建目标纹理 if (FAILED(D3DXCreateTexture(pDevice, uiWidth, uiHeight, 1, 0, dxtFormat, D3DPOOL_MANAGED, &pDestTex)))// D3DPOOL_DEFAULT { bResult = false; goto theend; } pSrcTex->GetSurfaceLevel(0, &pSrcSurface); pDestTex->GetSurfaceLevel(0, &pDestSurface); if (FAILED(D3DXLoadSurfaceFromSurface(pDestSurface, 0, 0, pSrcSurface, 0, 0, D3DX_DEFAULT, 0))) { bResult = false; goto theend; } theend: SAFE_RELEASE(pSrcSurface); SAFE_RELEASE(pDestSurface); //SAFE_RELEASE(pDestTex); return pDestTex; } // string 与DWORD互转 static DWORD MyStringToDWORD(string str) { DWORD num; stringstream sstr; sstr << str; sstr >> num; sstr.clear(); return num; } #endif #endif