|

楼主 |
发表于 2005-11-16 11:50:00
|
显示全部楼层
Re:最近做的地表
//.cpp文件
#include "pe_map.h"
#include "pe_tool.h"
//----------------------------------------------------------------
// Name:
// Desc:
//----------------------------------------------------------------
CPEMap::CPEMap():m_MapMeshDataS(32)
{
m_fDistanceDetail=200.0f;
m_fHeightDetail=0.5f;
m_fViewRadianCos=0.70710677f;
}
//----------------------------------------------------------------
// Name:
// Desc:
//----------------------------------------------------------------
CPEMap::~CPEMap()
{
}
PE_ScriptComBlockDef_T tmp_MapScript[]=
{
{"loadmap", PE_MAPSCRIPT_LOADMAP, 1, 1},
{"", PE_MAPSCRIPT_TOTAL, 0, 0}
};
//----------------------------------------------------------------
// Name: OneTimeInit()
// Desc:
//----------------------------------------------------------------
PE_BOOL CPEMap::OneTimeInit(PE_VOID)
{
// script cmd register
PE_SCRIPTCMD_REGISTER( tmp_MapScript, PE_MAPSCRIPT_TOTAL );
m_pRender=PE_NULL;
return PE_TRUE;
}
//----------------------------------------------------------------
// Name: Update()
// Desc:
//----------------------------------------------------------------
PE_BOOL CPEMap::FrameMove(PE_VOID)
{
// 视野剔除
PE_MapMeshData_T* pMapMesh;
#ifdef PE_MAP_GENERATOR_QUADTREE // 是否使用四叉分割树来对地表处理
PE_MapViewParam_T tMapViewParam;
tMapViewParam.fDistance=m_pEngineParam->fViewDistance;
tMapViewParam.fViewRadianCos=m_fViewRadianCos;
tMapViewParam.pEye = &m_pEngineParam->vEye;
tMapViewParam.pLookAt = &m_pEngineParam->vLookAt;
#endif
for(CPEPoolArray< E_UINT4, PE_MapMeshData_T>::iterator iter=m_MapMeshDataS.begin(); iter!=m_MapMeshDataS.end(); iter++)
{
pMapMesh=iter.getdata( PE_NULL );
if( !pMapMesh->bLoaded )
continue;
#ifdef PE_MAP_GENERATOR_QUADTREE // 是否使用四叉分割数来对地表处理
tMapViewParam.pMapMesh=pMapMesh;
if( !(rand() & 0x3) ) // 加速部分
{
_GenerateMapMesh_QuadTree( &tMapViewParam, pMapMesh->nSide>>1, pMapMesh->nSide>>1, 1+(pMapMesh->nSide>>1) );
_GenerateMapMeshFlag_QuadTree( pMapMesh );
}
#endif
}
return PE_TRUE;
}
//----------------------------------------------------------------
// Name: Render()
// Desc:
//----------------------------------------------------------------
PE_BOOL CPEMap::Render(PE_VOID)
{
if( !m_pRender )
m_pRender=static_cast<IPERender*>( m_pEngineMan->GetEngineObject( PE_EOTT_RENDER ) );
if( !m_pRender )
return PE_TRUE;
PE_MapMeshData_T* pMapMesh;
// 设定第1张颜色纹理为线性过滤
m_pRender->LightEnable( PE_FALSE );
//m_pRender->SetAmbient( 0xffffffff );
m_pRender->SetFilter( 0, PE_FILTER_LINEAR, PE_FILTER_LINEAR, PE_FILTER_LINEAR );
m_pRender->SetFilter( 1, PE_FILTER_LINEAR, PE_FILTER_LINEAR, PE_FILTER_LINEAR );
m_pRender->SetFilter( 2, PE_FILTER_LINEAR, PE_FILTER_LINEAR, PE_FILTER_LINEAR );
m_pRender->SetTextureStageState( 0, PE_TSS_COLOROP, PE_TCOP_MODULATE );
m_pRender->SetTextureStageState( 0, PE_TSS_COLORARG1, PE_TARG_TEXTURE );
m_pRender->SetTextureStageState( 0, PE_TSS_COLORARG2, PE_TARG_DIFFUSE );
m_pRender->SetTextureStageState( 1, PE_TSS_COLOROP, PE_TCOP_ADDSIGNED );
m_pRender->SetTextureStageState( 1, PE_TSS_COLORARG1, PE_TARG_TEXTURE );
m_pRender->SetTextureStageState( 1, PE_TSS_COLORARG2, PE_TARG_CURRENT );
m_pRender->SetFVF( m_pRender->GetFVF( PE_FALSE, PE_TRUE, PE_TRUE, 2 ) );
for(CPEPoolArray<PE_UINT4, PE_MapMeshData_T>::iterator iter=m_MapMeshDataS.begin(); iter!=m_MapMeshDataS.end(); iter++)
{
pMapMesh=iter.getdata( PE_NULL );
if( !pMapMesh->bLoaded )
continue;
m_pRender->SetTexture( 0, pMapMesh->nGroundTexIndex );
m_pRender->SetTexture( 1, pMapMesh->nTexIndex[0] );
#ifdef PE_MAP_GENERATOR_QUADTREE // 是否使用四叉分割树来对地表处理
m_pEngineParam->nNumTriangleRender +=_QuadTree_RenderPatch( pMapMesh, pMapMesh->nSide>>1, pMapMesh->nSide>>1, 1+(pMapMesh->nSide>>1) );
#endif
}
m_pRender->SetTextureStageState( 1, PE_TSS_COLOROP, PE_TCOP_DISABLE );
m_pRender->LightEnable( PE_TRUE );
return PE_TRUE;
}
//----------------------------------------------------------------
// Name: InvalidateDeviceObjects()
// Desc:
//----------------------------------------------------------------
PE_BOOL CPEMap::InvalidateDeviceObjects(PE_VOID)
{
return PE_TRUE;
}
//----------------------------------------------------------------
// Name: RestoreDeviceObjects()
// Desc:
//----------------------------------------------------------------
PE_BOOL CPEMap::RestoreDeviceObjects(PE_VOID)
{
return PE_TRUE;
}
//----------------------------------------------------------------
// Name: FinalCleanup()
// Desc:
//----------------------------------------------------------------
PE_BOOL CPEMap::FinalCleanup(PE_VOID)
{
DelMapMesh();
return PE_TRUE;
}
//----------------------------------------------------------------
// Name: OnEngineMsg()
// Desc:
//----------------------------------------------------------------
PE_UINT CPEMap::OnEngineMsg(PE_UINT4 unCom, PE_UINT4 unParam, PE_PVOID pValue, PE_PVOID pValue2)
{
PE_UINT nResult=0;
IPEScript* pScript=static_cast<IPEScript*>( m_pEngineMan->GetEngineObject( PE_EOTT_SCRIPT ) );
if( !pScript )
return nResult;
PE_INT4 nValue=0;
switch( unCom )
{
case PE_EMTT_WM_SCRIPT:
{
PE_EMTT_WM_SCRIPT_T* pParam=(PE_EMTT_WM_SCRIPT_T*)pValue;
if( unParam == m_nScriptCom[PE_MAPSCRIPT_LOADMAP] )
{
nResult=(PE_UINT)LoadMap( pParam->pValue+pParam->pOffsetValue[0] );
}
}
break;
}
return 0;
}
//----------------------------------------------------------------
// Name: SetParam()
// Desc:
//----------------------------------------------------------------
PE_VOID CPEMap::SetParam(PE_FLOAT fViewRadianCos)
{
m_fViewRadianCos=fViewRadianCos;
}
//----------------------------------------------------------------
// Name: IsNearWater()
// Desc: 判断是否在水面附近(判断是否需要重新绘制)
//----------------------------------------------------------------
PE_BOOL CPEMap::IsNearWater(PE_FLOAT x, PE_FLOAT y, PE_FLOAT z)
{
return PE_FALSE;
}
//----------------------------------------------------------------
// Name: GetWaterWorldMatrix()
// Desc: 得到水面绘制需要的世界矩阵
//----------------------------------------------------------------
PE_MATRIX* CPEMap::GetWaterWorldMatrix(PE_VOID)
{
return PE_NULL;
}
//----------------------------------------------------------------
// Name: BeginRenderWater()
// Desc: 开始水面绘制
//----------------------------------------------------------------
PE_VOID CPEMap::BeginRenderWater(PE_VOID)
{
}
//----------------------------------------------------------------
// Name: EndRenderWater()
// Desc: 结束水面绘制
//----------------------------------------------------------------
PE_VOID CPEMap::EndRenderWater(PE_VOID)
{
}
//----------------------------------------------------------------
// Name: AddBump()
// Desc: 增加物体撞击(比如水花的模拟)
//----------------------------------------------------------------
PE_VOID CPEMap::AddBump(PE_FLOAT x, PE_FLOAT z, PE_FLOAT fSize)
{
}
//----------------------------------------------------------------
// Name: LoadMap()
// Desc:
//----------------------------------------------------------------
PE_BOOL CPEMap: oadMap(PE_CCHAR* pFilename)
{
PE_TCHAR cFilename[PE_STR_LEN];
DXUtil_ConvertAnsiStringToGenericCch( cFilename, pFilename, PE_STR_LEN );
return LoadMap( cFilename );
}
//----------------------------------------------------------------
// Name: LoadMap()
// Desc:
//----------------------------------------------------------------
PE_BOOL CPEMap::LoadMap(PE_CTCHAR* pFilename)
{
m_pRender=static_cast<IPERender*>( m_pEngineMan->GetEngineObject( PE_EOTT_RENDER ) );
if( !m_pRender )
{
m_pEngineMan->DebugLogFile( _T("<Error> Load render partment first") );
return PE_FALSE;
}
return PE_TRUE;
}
//----------------------------------------------------------------
// Name: GetHeight()
// Desc: 得到地表高度
//----------------------------------------------------------------
PE_FLOAT CPEMap::GetHeight(PE_FLOAT x, PE_FLOAT z)
{
PE_FLOAT fResult=0.0f;
PE_MapMeshData_T* pMapMesh;
for(CPEPoolArray<PE_UINT4, PE_MapMeshData_T>::iterator iter=m_MapMeshDataS.begin(); iter!=m_MapMeshDataS.end(); iter++)
{
pMapMesh=iter.getdata( PE_NULL );
if( !pMapMesh->bLoaded )
continue;
// 判断范围是否在
if( _GetMapMeshHeight( pMapMesh, x, z, &fResult ) )
break;
}
return fResult;
}
//----------------------------------------------------------------
// Name: LoadMapMesh()
// Desc:
//----------------------------------------------------------------
PE_UINT4 CPEMap::LoadMapMesh(PE_CTCHAR* pFilename, PE_BOOL bThread/*=PE_FALSE*/)
{
PE_UINT4 i,nResult=0;
static PE_UINT4 nSerial=0;
//PE_MapMeshData_T* pMapMesh=PE_NULL;
PE_TCHAR cSection[PE_STR_LEN]={ _T("set") };
PE_TCHAR cKey[PE_STR_LEN], cValue[PE_STR_LEN];
TCHAR cErrBuffer[PE_STR_LEN];
IPEFileMan* pFileMan=static_cast<IPEFileMan*>(m_pEngineMan->GetEngineObject(PE_EOTT_FILE));
if( !pFileMan )
return 0;
IPERender* pRender=static_cast<IPERender*>(m_pEngineMan->GetEngineObject(PE_EOTT_RENDER));
if( !pRender )
goto e_End;
IPEFileStream* fp=pFileMan->NewFileStream();
if( !fp )
goto e_End;
if( !fp->Open( pFileMan, pFilename ) )
goto e_End;
nSerial++;
PE_MapMeshData_T* pMapMesh=m_MapMeshDataS.allocate( nSerial, nSerial );
if( !pMapMesh )
goto e_End;
nResult=nSerial;
// 读取设定信息
PE_ZEROMEMORY( pMapMesh, PE_SIZEOF(PE_MapMeshData_T) );
pMapMesh->x=PE_Script_GetFloat( fp, cSection, _T("map.x"), 0.0f );
pMapMesh->z=PE_Script_GetFloat( fp, cSection, _T("map.z"), 0.0f );
pMapMesh->nSide=PE_Script_GetInt( fp, cSection, _T("map.side"), 64 );
pMapMesh->fDetailDistance=PE_Script_GetFloat( fp, cSection, _T("map.detaildistance"), 1000.0f );
pMapMesh->nDetailHeight=(PE_UINT1)PE_Script_GetInt( fp, cSection, _T("map.detailheight"), 3 );
pMapMesh->fTileSide=PE_Script_GetFloat( fp, cSection, _T("map.tileside"), 10.0f );
pMapMesh->fHeightScale=PE_Script_GetFloat( fp, cSection, _T("map.scale"), 1.0f );
pMapMesh->nHeightMapSide=PE_Script_GetInt( fp, cSection, _T("heightmap.side"), 64 );
PE_Script_GetString( fp, cSection, _T("heightmap.file"), PE_UNKNOWNFILE, pMapMesh->cHeightFile );
PE_Script_GetString( fp, cSection, _T("texmap.file"), PE_UNKNOWNFILE, pMapMesh->cTexFile );
PE_Script_GetString( fp, cSection, _T("groundtex.file"), PE_UNKNOWNFILE, pMapMesh->cGroundFile );
PE_Script_GetString( fp, cSection, _T("lighttex.file"), PE_UNKNOWNFILE, pMapMesh->cLightFile );
// 装入所需要的纹理
pMapMesh->nNumTex=(PE_UINT4)PE_Script_GetInt( fp, cSection, _T("tex.num"), 0 );
pMapMesh->nNumTex=PE_Min( PE_MAP_TEXMAXNUM, pMapMesh->nNumTex );
if( !pMapMesh->nNumTex )
{
PE_SPRINTF( cErrBuffer, PE_STR_LEN, _T("<Error> MapMesh(%s): no texture included"), pFilename );
m_pEngineMan->DebugLogFile( cErrBuffer );
goto e_End;
}
for(i=0; i<pMapMesh->nNumTex; i++)
{
PE_SPRINTF( cKey, PE_STR_LEN, _T("tex.file%d"), i+1 );
PE_Script_GetString( fp, cSection, cKey, _T("error"), cValue );
pMapMesh->nTexIndex=pRender->LoadFileTex( cValue );
PE_SPRINTF( cKey, PE_STR_LEN, _T("tex.color%d"), i+1 );
pMapMesh->dwTexColor=(PE_DWORD)PE_Script_GetInt( fp, cSection, cKey, 0 );
}
/*if( bThread )
{
}
else*/
{
if( !_LoadMapMesh( pFileMan, pRender, pMapMesh ) )
{
PE_SPRINTF( cErrBuffer, PE_STR_LEN, _T("<Error> MapMesh(%s): Load failed"), pFilename );
m_pEngineMan->DebugLogFile( cErrBuffer );
goto e_End;
}
pMapMesh->bLoaded=PE_TRUE;
}
PE_SAFEDELETE( fp );
return nSerial;
e_End:
if( nResult )
DelMapMesh( nResult );
PE_SAFEDELETE( fp );
return 0;
}
#define TMP_TEXMAP_GETVALUE(a,b) (((a)>=(b))?((a)-(b)) (b)-(a)))
inline PE_DWORD tmp_TexMap_GetColorValue(PE_DWORD dwColor, PE_DWORD dwComp)
{
PE_DWORD dwValue=0, dwResult=0;
dwValue=TMP_TEXMAP_GETVALUE( dwColor & 0xff, dwComp & 0xff );
dwResult=PE_Max( dwValue, dwResult );
dwValue=TMP_TEXMAP_GETVALUE( (dwColor & 0xff00)>>8, (dwComp & 0xff00)>>8 );
dwResult=PE_Max( dwValue, dwResult );
dwValue=TMP_TEXMAP_GETVALUE( (dwColor & 0xff0000)>>16, (dwComp & 0xff0000)>>16 );
dwResult=PE_Max( dwValue, dwResult );
return dwResult;
}
//----------------------------------------------------------------
// Name: _LoadMapMesh()
// Desc: 私有成员,用于线程调用或自身调用
//----------------------------------------------------------------
PE_BOOL CPEMap::_LoadMapMesh(IPEFileMan* pFileMan, IPERender* pRender, PE_MapMeshData_T* pMapMesh)
{
PE_UINT4 i,j,k;
PE_UINT4 width, height, nSize;
PE_DWORD dwValueMin, dwValue;
PE_UINT nTex=0;
// 读取ground tex
pMapMesh->nGroundTexIndex=pRender->LoadFileTex( pMapMesh->cGroundFile );
// 读取高度图
if( !_LoadHeightMap( pFileMan, pMapMesh->cHeightFile, pMapMesh->nHeightMapSide, &pMapMesh->pHeightMapBuffer ) )
goto e_End;
// 读取纹理设定图
nTex=pRender->LoadFileTex( pMapMesh->cTexFile, 0, PE_CTFLAG_POOL_SYSTEM );
if( !nTex )
goto e_End;
pRender->GetParamTex( nTex, &width, &height );
if( width!=height )
goto e_End;
nSize=width*height;
pMapMesh->pTexMapBuffer=PE_NEW PE_UINT1[nSize];
pMapMesh->nTexMapSide=width;
PE_DWORD* pColor=(PE_DWORD*)pRender->LockTex( nTex, 0 );
if( !pColor )
goto e_End;
// 根据颜色值来得到纹理映射数据
for(i=0; i<nSize; i++)
{
dwValueMin=0xff;
k=0; // 记录相差最小的那个
for(j=0; j<pMapMesh->nNumTex; j++)
{
dwValue=tmp_TexMap_GetColorValue( pColor, pMapMesh->dwTexColor[j] );
if( dwValue<dwValueMin )
{
k=j;
dwValueMin=dwValue;
}
}
pMapMesh->pTexMapBuffer=(PE_UINT1)k; // 记录当前点的颜色值
}
pRender->UnlockTex( nTex, 0 );
pRender->Release( nTex );
if( !_LoadMapLightTex( pFileMan, pMapMesh ) )
{
#ifdef _DEBUG
// 创建该文件
_CreateMapLightTex( pFileMan, pMapMesh );
// 再次读取
if( !_LoadMapLightTex( pFileMan, pMapMesh ) )
{
#endif
TCHAR cErrBuffer[PE_STR_LEN];
PE_SPRINTF( cErrBuffer, PE_STR_LEN, _T("<Error> Load Light texture file failed: %s"), pMapMesh->cLightFile );
m_pEngineMan->DebugLogFile( cErrBuffer );
#ifdef _DEBUG
}
#endif
}
#ifdef PE_MAP_GENERATOR_QUADTREE // 是否使用四叉分割树来对地表处理
// 得到地表的各个tile需要增加的精度(通过高度比较方法)
nSize=(pMapMesh->nSide-1)*(pMapMesh->nSide-1);
pMapMesh->pDetailLevel=PE_NEW PE_UINT1[nSize];
pMapMesh->pDetailRender=PE_NEW PE_UINT1[nSize];
pMapMesh->pDetailRenderFlag=PE_NEW PE_UINT1[(pMapMesh->nSide>>2)*(pMapMesh->nSide>>2)];
if( !pMapMesh->pDetailLevel || !pMapMesh->pDetailRender || !pMapMesh->pDetailRenderFlag )
goto e_End;
PE_ZEROMEMORY( pMapMesh->pDetailLevel, PE_SIZEOF(PE_UINT1)*nSize );
PE_ZEROMEMORY( pMapMesh->pDetailRender, PE_SIZEOF(PE_UINT1)*nSize );
PE_UINT4 nEdgeLength=2; // 边长
PE_UINT4 nEdgeOffset; // 偏移值
//PE_UINT4 nChildOffset; // 子节点偏移值
PE_INT4 nHeightCur, nHeightMax; // 高度差
//PE_UINT1 nLocalHeight, nLocalMax;
while( nEdgeLength<=5 )
{
nEdgeOffset = nEdgeLength - 1;
for(i=nEdgeOffset; i<pMapMesh->nSide; i+=(nEdgeLength-1) )
{
for(j=nEdgeOffset; j<pMapMesh->nSide; j+=(nEdgeLength-1) )
{
nHeightMax = 0;
nHeightCur = (PE_INT4)_GetMapMeshTrueHeight( pMapMesh, j, i ) - ( (PE_INT4)_GetMapMeshTrueHeight( pMapMesh, j-nEdgeOffset, i-nEdgeOffset ) +
(PE_INT4)_GetMapMeshTrueHeight( pMapMesh, j+nEdgeOffset, i+nEdgeOffset ) )/2;
nHeightMax = PE_Max( nHeightMax, nHeightCur );
nHeightCur = (PE_INT4)_GetMapMeshTrueHeight( pMapMesh, j, i ) - ( (PE_INT4)_GetMapMeshTrueHeight( pMapMesh, j-nEdgeOffset, i+nEdgeOffset ) +
(PE_INT4)_GetMapMeshTrueHeight( pMapMesh, j+nEdgeOffset, i-nEdgeOffset ) )/2;
nHeightMax = PE_Max( nHeightMax, nHeightCur );
pMapMesh->pDetailLevel[ j-1+(i-1)*(pMapMesh->nSide-1) ]=(PE_UINT1)nHeightMax;
}
}
nEdgeLength = (nEdgeLength<<1)-1;
}
#endif
return PE_TRUE;
e_End:
pRender->Release( nTex );
return PE_FALSE;
}
//----------------------------------------------------------------
// Name: _GetMapTexIndex()
// Desc: 得到map mesh的指定点的细节纹理索引
//----------------------------------------------------------------
PE_UINT4 CPEMap::_GetMapTexIndex(PE_MapMeshData_T* pMapMesh, PE_UINT4 x, PE_UINT4 z)
{
PE_UINT4 nResult=0;
if( !pMapMesh->pTexMapBuffer )
return nResult;
if( x>=pMapMesh->nSide )
x=pMapMesh->nSide-1;
if( z>=pMapMesh->nSide )
z=pMapMesh->nSide-1;
x=x*pMapMesh->nTexMapSide/pMapMesh->nSide;
z=z*pMapMesh->nTexMapSide/pMapMesh->nSide;
nResult=pMapMesh->pTexMapBuffer[x+z*pMapMesh->nTexMapSide];
return nResult;
}
//----------------------------------------------------------------
// Name: _GetMapLight()
// Desc: 得到map mesh的指定点的光照值
//----------------------------------------------------------------
PE_DWORD CPEMap::_GetMapLight(PE_MapMeshData_T* pMapMesh, PE_UINT4 x, PE_UINT4 z)
{
PE_DWORD nResult=0x00ffffff;
if( !pMapMesh->pLightTexBuffer )
return nResult;
if( x>pMapMesh->nSide )
x=pMapMesh->nSide;
if( z>pMapMesh->nSide )
z=pMapMesh->nSide;
nResult=(PE_DWORD)pMapMesh->pLightTexBuffer[x+z*(pMapMesh->nSide+1)];
return nResult;
}
//----------------------------------------------------------------
// Name: _CreateMapLightTex()
// Desc: 创建地表光照纹理
// 文件格式:diffuse的颜色值,即3字节的数据流
//----------------------------------------------------------------
PE_BOOL CPEMap::_CreateMapLightTex(IPEFileMan* pFileMan, PE_MapMeshData_T* pMapMesh)
{
TCHAR cFilename[PE_STR_LEN];
PE_SPRINTF( cFilename, PE_STR_LEN, _T(".\\%s"), pMapMesh->cLightFile );
IPEFileWrite* fp=pFileMan->NewFileWrite();
if( !fp )
return PE_FALSE;
if (!fp->Open( cFilename, PE_TRUE ) )
goto e_End;
// Step 1:先根据坡度(Slope)生成一个光照
PE_UINT4 nOffsetX=1, nOffsetZ=1; // 影子颜色偏移
PE_UINT4 nColorRed=0xff, nColorGreen=0xff, nColorBlue=0xff; // 光的颜色
PE_FLOAT fBrightnessMix=0.2f, fBirghtnessMax=1.0f; // 亮度的范围
PE_FLOAT fSoftness=15.0; // 柔和度
PE_UINT4 i,j;
PE_FLOAT fShade;
PE_UINT1 nColor;
for(i=0; i<=pMapMesh->nSide; i++)
{
for(j=0; j<=pMapMesh->nSide; j++)
{
if( i>=nOffsetZ && j>=nOffsetX )
fShade=1.0f-( _GetMapMeshHeight(pMapMesh, j-nOffsetX, i-nOffsetZ)-_GetMapMeshHeight(pMapMesh, j, i) )/fSoftness/pMapMesh->fHeightScale;
else
fShade=1.0f;
fShade=PE_Max( fBrightnessMix, fShade );
fShade=PE_Min( fBirghtnessMax, fShade );
nColor=PE_UINT1(fShade*nColorRed);
fp->Write( &nColor, 1 );
nColor=PE_UINT1(fShade*nColorGreen);
fp->Write( &nColor, 1 );
nColor=PE_UINT1(fShade*nColorBlue);
fp->Write( &nColor, 1 );
}
}
// TODO: Step 2:再根据其他静态光源来计算得到最终顶点光照颜色值
// at last
fp->Close();
PE_SAFEDELETE( fp );
return PE_TRUE;
e_End:
if( fp )
fp->Close();
PE_SAFEDELETE( fp );
return PE_FALSE;
}
//----------------------------------------------------------------
// Name: _LoadMapLightTex()
// Desc: 读取地表光照纹理
// 文件格式:diffuse的颜色值,即3字节的数据流
//----------------------------------------------------------------
PE_BOOL CPEMap::_LoadMapLightTex(IPEFileMan* pFileMan, PE_MapMeshData_T* pMapMesh)
{
IPEFileStream* fp=pFileMan->NewFileStream();
if( !fp )
return PE_FALSE;
if( !fp->Open( pFileMan, pMapMesh->cLightFile ) )
goto e_End;
// 有多少点就有多少个点对应的diffuse颜色
PE_UINT4 nSize=(pMapMesh->nSide+1)*(pMapMesh->nSide+1);
pMapMesh->pLightTexBuffer=PE_NEW PE_UINT4[nSize];
if( !pMapMesh->pLightTexBuffer )
goto e_End;
PE_UINT1 nR, nG, nB;
for(PE_UINT4 i=0; i<nSize; i++)
{
if( !fp->Read( &nR, 1 ) )
goto e_End;
if( !fp->Read( &nG, 1 ) )
goto e_End;
if( !fp->Read( &nB, 1 ) )
goto e_End;
pMapMesh->pLightTexBuffer=0xff000000 | (nR<<16) | (nG<<8) | nB;
}
PE_SAFEDELETE( fp );
return PE_TRUE;
e_End:
PE_SAFEDELETE_ARRAY( pMapMesh->pLightTexBuffer );
PE_SAFEDELETE( fp );
return PE_FALSE;
}
//----------------------------------------------------------------
// Name: _LoadHeightMap()
// Desc: 读取高度图
//----------------------------------------------------------------
PE_BOOL CPEMap::_LoadHeightMap(IPEFileMan* pFileMan, PE_CTCHAR* pFilename, PE_UINT4 nHeightMapSide, PE_UINT1** ppOutBuffer)
{
IPEFileStream* fp=pFileMan->NewFileStream();
if( !fp )
return PE_FALSE;
if( !fp->Open( pFileMan, pFilename ) )
goto e_End;
PE_UINT4 nSize=nHeightMapSide*nHeightMapSide;
(*ppOutBuffer)=PE_NEW PE_UINT1[nSize];
if( !(*ppOutBuffer) )
{
m_pEngineMan->DebugLogFile( _T("<Error> Out of memory") );
goto e_End;
}
if( !fp->Read( *ppOutBuffer, nSize ) )
{
TCHAR cErrBuffer[PE_STR_LEN];
PE_SPRINTF( cErrBuffer, PE_STR_LEN, _T("<Error> Height map file(%s) with wrong side: %d"), pFilename, nHeightMapSide );
m_pEngineMan->DebugLogFile( cErrBuffer );
PE_SAFEDELETE_ARRAY( *ppOutBuffer );
goto e_End;
}
PE_SAFEDELETE( fp );
return PE_TRUE;
e_End:
PE_SAFEDELETE( fp );
return PE_FALSE;
}
//----------------------------------------------------------------
// Name: _GetMapMeshTrueHeight()
// Desc: 得到map mesh的指定点的高度
//----------------------------------------------------------------
PE_UINT1 CPEMap::_GetMapMeshTrueHeight(PE_MapMeshData_T* pMapMesh, PE_UINT4 x, PE_UINT4 z)
{
PE_UINT1 nResult=0;
if( !pMapMesh->pHeightMapBuffer )
return nResult;
if( x>pMapMesh->nSide )
x=pMapMesh->nSide;
if( z>pMapMesh->nSide )
z=pMapMesh->nSide;
x=x*pMapMesh->nHeightMapSide/pMapMesh->nSide;
z=z*pMapMesh->nHeightMapSide/pMapMesh->nSide;
PE_UINT4 nValueLT = pMapMesh->pHeightMapBuffer[ (x>0?(x-1):0) + (z>0?(z-1):0)*pMapMesh->nHeightMapSide ];
PE_UINT4 nValueRT = pMapMesh->pHeightMapBuffer[ (x<pMapMesh->nHeightMapSide?x:(x-1)) + (z>0?(z-1):0)*pMapMesh->nHeightMapSide ];
PE_UINT4 nValueLB = pMapMesh->pHeightMapBuffer[ (x>0?(x-1):0) + (z<pMapMesh->nHeightMapSide?z:(z-1))*pMapMesh->nHeightMapSide ];
PE_UINT4 nValueRB = pMapMesh->pHeightMapBuffer[ (x<pMapMesh->nHeightMapSide?x:(x-1)) + (z<pMapMesh->nHeightMapSide?z:(z-1))*pMapMesh->nHeightMapSide ];
nResult=PE_UINT1( ( (nValueLT+nValueRT+nValueLB+nValueRB)>>2 ) & 0xff );
return nResult;
}
//----------------------------------------------------------------
// Name: _GetMapMeshHeight()
// Desc: 得到map mesh的指定点的高度
//----------------------------------------------------------------
PE_FLOAT CPEMap::_GetMapMeshHeight(PE_MapMeshData_T* pMapMesh, PE_UINT4 x, PE_UINT4 z)
{
return pMapMesh->fHeightScale*_GetMapMeshTrueHeight( pMapMesh, x, z );
}
//----------------------------------------------------------------
// Name: _GetMapMeshHeight()
// Desc:
//----------------------------------------------------------------
PE_BOOL CPEMap::_GetMapMeshHeight(PE_MapMeshData_T* pMapMesh, PE_FLOAT x, PE_FLOAT z, PE_FLOAT* pOutHeight)
{
x-=pMapMesh->x;
z-=pMapMesh->z;
PE_FLOAT fSide=pMapMesh->fTileSide*pMapMesh->nSide;
if( x<0.0f || z<0.0f || x>fSide || z>fSide )
return PE_FALSE;
PE_UINT4 nx = PE_UINT4( x/pMapMesh->fTileSide ); // 落点
PE_UINT4 nz = PE_UINT4( z/pMapMesh->fTileSide );
PE_FLOAT fx = x/pMapMesh->fTileSide - nx; // 距离落点的偏移(0.0~1.0f)
PE_FLOAT fz = z/pMapMesh->fTileSide - nz;
PE_FLOAT fHeightLeft = _GetMapMeshHeight( pMapMesh, nx, nz )*(1.0f-fz) + _GetMapMeshHeight( pMapMesh, nx, nz+1 )*fz;
PE_FLOAT fHeightRight = _GetMapMeshHeight( pMapMesh, nx+1, nz )*(1.0f-fz) + _GetMapMeshHeight( pMapMesh, nx+1, nz+1 )*fz;
*pOutHeight = fHeightLeft*(1.0f-fx) + fHeightRight*fx;
return PE_TRUE;
}
//----------------------------------------------------------------
// Name: DelMapMesh()
// Desc:
//----------------------------------------------------------------
PE_VOID CPEMap: elMapMesh(PE_VOID)
{
IPERender* pRender=static_cast<IPERender*>(m_pEngineMan->GetEngineObject(PE_EOTT_RENDER));
PE_MapMeshData_T* pMapMesh;
for(CPEPoolArray<PE_UINT4, PE_MapMeshData_T>::iterator iter=m_MapMeshDataS.begin(); iter!=m_MapMeshDataS.end(); iter++)
{
pMapMesh=iter.getdata(PE_NULL);
pMapMesh->clear( pRender );
}
m_MapMeshDataS.clear();
}
//----------------------------------------------------------------
// Name: DelMapMesh()
// Desc:
//----------------------------------------------------------------
PE_VOID CPEMap::DelMapMesh(PE_UINT4 nIndex)
{
IPERender* pRender=static_cast<IPERender*>(m_pEngineMan->GetEngineObject(PE_EOTT_RENDER));
PE_MapMeshData_T* pMapMesh=m_MapMeshDataS.get_data( nIndex, nIndex );
if( pMapMesh )
{
pMapMesh->clear( pRender );
m_MapMeshDataS.del_data( nIndex, nIndex );
}
}
|
|