#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