游戏开发论坛

 找回密码
 立即注册
搜索
楼主: gosix

最近做的地表

[复制链接]

25

主题

145

帖子

341

积分

中级会员

Rank: 3Rank: 3

积分
341
 楼主| 发表于 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&ltE_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 );
        }
}

25

主题

145

帖子

341

积分

中级会员

Rank: 3Rank: 3

积分
341
 楼主| 发表于 2005-11-16 11:50:00 | 显示全部楼层

Re:最近做的地表


#ifdef PE_MAP_GENERATOR_QUADTREE

// 检查该点是否在视野范围内
PE_BOOL _PEMap_QuadTree_IsView(PE_MapViewParam_T* pViewParam, PE_UINT4 x, PE_UINT4 z, PE_UINT4 nEdgeLength)
{
        // 可见的标准:
        // 1. 4顶点必须有1个点离眼睛的位置小于视野范围
        // 2. 4顶点与眼睛实现所成的角度必须有1个小于视野角度
        PE_MapMeshData_T* pMapMesh=pViewParam->pMapMesh;
        PE_VECTOR3 vEye(*pViewParam->pEye), vLookDir, vLookTmp;

        if( nEdgeLength>5 )
        {
                PE_VECTOR3 vTmp[4];

                // 1. 4顶点必须有1个点离眼睛的位置小于视野范围
                for(PE_UINT4 i=0; i<4; i++)                                                                // 得到四个点的坐标
                {
                        vTmp.x=pMapMesh->x + pMapMesh->fTileSide*( x + ((i%2)-1)*(nEdgeLength-1) );
                        vTmp.y=0.0f;
                        vTmp.z=pMapMesh->z + pMapMesh->fTileSide*( z + ((i>>1)-1)*(nEdgeLength-1) );
                }

                for(i=0; i<4; i++)
                {
                        if( PE_Max( PE_Abs(vEye.x-vTmp.x), PE_Abs(vEye.z-vTmp.z) ) < pViewParam->fDistance )
                                break;
                }

                if( i<4 )
                        return PE_TRUE;

                // 2. 4顶点与眼睛实现所成的角度必须有1个小于视野角度
                vEye.y=0.0f;
                vLookDir=PE_VECTOR3(pViewParam->pLookAt->x, 0.0f, pViewParam->pLookAt->z)-vEye;
                for(i=0; i<4; i++)
                {
                        vLookTmp=vTmp-vEye;
                        if( vLookTmp.DotMul( vLookDir ) >= pViewParam->fViewRadianCos )
                                return PE_TRUE;
                }

        }
        else
        {
                // 对于小的patch,只需要判断中心点就可以了
                PE_VECTOR3 vTmp;
                vTmp.x=pMapMesh->x + pMapMesh->fTileSide*x;
                vTmp.y=0.0f;
                vTmp.z=pMapMesh->z + pMapMesh->fTileSide*z;

                // 距离
                PE_FLOAT fDistance=PE_Max( PE_Abs(vEye.x-vTmp.x), PE_Abs(vEye.z-vTmp.z) );
                if( fDistance >= pViewParam->fDistance )
                {
                        return PE_FALSE;
                }

                // 角度
                vEye.y=0.0f;
                vLookDir=PE_VECTOR3(pViewParam->pLookAt->x, 0.0f, pViewParam->pLookAt->z)-vEye;
                vLookTmp=vTmp-vEye;
                if( vLookTmp.DotMul( vLookDir ) >= pViewParam->fViewRadianCos )
                        return PE_TRUE;

                if( fDistance <= (pViewParam->fDistance/4.0f) )
                        return PE_TRUE;
        }

        return PE_FALSE;
}



//----------------------------------------------------------------
// Name: _GenerateMapMesh_QuadTree()
// Desc: Quad tree方式生成要渲染的地图mesh
//----------------------------------------------------------------
PE_VOID CPEMap::_GenerateMapMesh_QuadTree(PE_MapViewParam_T* pViewParam, PE_UINT4 x, PE_UINT4 z, PE_UINT4 nEdgeLength)
{
        PE_MapMeshData_T* pMapMesh=pViewParam->pMapMesh;

        PE_UINT4 i=x-1+(z-1)*(pMapMesh->nSide-1);

        // Step 1: 检查该点是否在视野范围内
        if( !_PEMap_QuadTree_IsView( pViewParam, x, z, nEdgeLength ) )
        {
                pMapMesh->pDetailRender=0;                        // 该点不需要显示
                return;
        }

        // Step 2: 根据该点离视点的距离确定该点显示级别(3个级别分别对应1,2,3)
        PE_FLOAT fx, fz, fDistance, fDetailLevel;
        fx=pMapMesh->x+pMapMesh->fTileSide*x;
        fz=pMapMesh->z+pMapMesh->fTileSide*z;
        fDistance = PE_Max( PE_Abs( fx - pViewParam->pEye->x ), PE_Abs( fz - pViewParam->pEye->z ) );                // 距离
        fDistance = PE_Max( fDistance, PE_Abs( _GetMapMeshHeight( pMapMesh, x, z ) - pViewParam->pEye->y ) );
        fDetailLevel = 1.0f+fDistance/pMapMesh->fDetailDistance;
        //pMapMesh->pDetailRender = 1+PE_UINT1(fDistance/pMapMesh->fDetailDistance);
        if( nEdgeLength==2 )                                                                        // 如果是最小的(tile)了,判断是否需要额外的细节
        {
                fDetailLevel = fDetailLevel - ((PE_FLOAT)pMapMesh->pDetailLevel)/pMapMesh->nDetailHeight;
                if( fDetailLevel<1.0f )
                        fDetailLevel = 1.0f;
                //PE_UINT1 nLevel=pMapMesh->pDetailLevel/pMapMesh->nDetailHeight;                                // 额外需要增加的细节等级
                //if( pMapMesh->pDetailRender > nLevel )
                //        pMapMesh->pDetailRender -= nLevel;
                //else
                //        pMapMesh->pDetailRender = 1;
        }
        pMapMesh->pDetailRender=(PE_UINT1)fDetailLevel;
        pMapMesh->pDetailRender=PE_Min( 3, pMapMesh->pDetailRender );

        // At last, 细分子patch
        if( nEdgeLength>=3 )
        {
                PE_UINT4 nChildEdgeLength=1+(nEdgeLength>>1);
                PE_UINT4 nChildOffset=(nEdgeLength>>1);
                _GenerateMapMesh_QuadTree( pViewParam, x-nChildOffset, z-nChildOffset, nChildEdgeLength );
                _GenerateMapMesh_QuadTree( pViewParam, x+nChildOffset, z-nChildOffset, nChildEdgeLength );
                _GenerateMapMesh_QuadTree( pViewParam, x-nChildOffset, z+nChildOffset, nChildEdgeLength );
                _GenerateMapMesh_QuadTree( pViewParam, x+nChildOffset, z+nChildOffset, nChildEdgeLength );
        }
}



// nWay
// 3 2 1
// 4 8 0
// 5 6 7
static const PE_INT4 tmp_QuadTree_WayData[18]={ 1,0, 1,-1, 0,-1, -1,-1, -1,0, -1,1, 0,1, 1,1, 0,0 };
//----------------------------------------------------------------
// Name: _QuadTree_Render_AddVertex()
// Desc:
//----------------------------------------------------------------
PE_VOID CPEMap::_QuadTree_Render_AddVertex(PE_MapMeshData_T* pMapMesh, PE_UINT4 x, PE_UINT4 z, PE_UINT4 nEdgeLength, PE_UINT4 nWay)
{
        if( m_nCountMapMeshVertex>=19 )
        {
                DEBUG_MSG( _T("<Error>") );
                return;
        }

        PE_MapVertexData_T* pVertex=m_MapMeshVertex+m_nCountMapMeshVertex;
        m_nCountMapMeshVertex++;

        if( tmp_QuadTree_WayData[nWay<<1] )
        {
                if( tmp_QuadTree_WayData[nWay<<1]>0 )
                        x+=(nEdgeLength-1);
                else
                        x-=(nEdgeLength-1);
        }

        if( tmp_QuadTree_WayData[1+(nWay<<1)] )
        {
                if( tmp_QuadTree_WayData[1+(nWay<<1)]>0 )
                        z+=(nEdgeLength-1);
                else
                        z-=(nEdgeLength-1);
        }

        pVertex->x = pMapMesh->x+pMapMesh->fTileSide*x;
        pVertex->z = pMapMesh->z+pMapMesh->fTileSide*z;
        pVertex->y = _GetMapMeshHeight( pMapMesh, x, z );

        pVertex->diffuse = _GetMapLight( pMapMesh, x, z );

        pVertex->u1 = ((PE_FLOAT)x)/pMapMesh->nSide;
        pVertex->v1 = ((PE_FLOAT)z)/pMapMesh->nSide;

        PE_FLOAT fTmp = 1.0f*( nEdgeLength>>1 );                                        // 第2层纹理的贴图最大值
        pVertex->u2 = fTmp*(1+tmp_QuadTree_WayData[nWay<<1]);
        pVertex->v2 = fTmp*(1+tmp_QuadTree_WayData[1+(nWay<<1)]);
}





// 得到细节索引
inline PE_UINT4 _PEMap_QuadTree_GetDetailIndex(PE_MapMeshData_T* pMapMesh, PE_UINT4 x, PE_UINT4 z)
{
        PE_UINT4 nResult=0;
        if( x>0 && z>0 && x<pMapMesh->nSide && z<pMapMesh->nSide )
        {
                nResult=pMapMesh->pDetailRender[x-1+(z-1)*(pMapMesh->nSide-1)];
        }
        return nResult;
}

// 得到最大的细节值
inline PE_UINT4 _PEMap_QuadTree_MaxDetailLevel(PE_UINT4 a, PE_UINT4 b)
{
        if( a && b )
        {
                return PE_Min( a, b );
        }
        else if( a )
        {
                return a;
        }
        else if( b )
        {
                return b;
        }
        else
                return 0;
}

//----------------------------------------------------------------
// Name: _PEMap_QuadTree_GetEdgeValue()
// Desc: Quad tree方式得到是否需要增面/减面
//                值为0时表示不关心状态,为1时表示需要加面,为2时表示不需要加面
//----------------------------------------------------------------
PE_DWORD _PEMap_QuadTree_GetEdgeValue(PE_MapMeshData_T* pMapMesh, PE_UINT4 x, PE_UINT4 z, PE_UINT4 nEdgeLength)
{
        PE_DWORD dwResult=0;
        PE_UINT4 offset=(nEdgeLength-1)>>1;
        PE_UINT4 nDetailLevel;                        // 细节等级
        //PE_UINT4 nCurDetailLevel=1;

        // right
        nDetailLevel=_PEMap_QuadTree_MaxDetailLevel( _PEMap_QuadTree_GetDetailIndex( pMapMesh, x+3*offset, z-offset ),
                        _PEMap_QuadTree_GetDetailIndex( pMapMesh, x+3*offset, z+offset ) );

        if( nDetailLevel == 1 )
                dwResult |= 0x00000001;

        // top
        nDetailLevel=_PEMap_QuadTree_MaxDetailLevel( _PEMap_QuadTree_GetDetailIndex( pMapMesh, x-offset, z-3*offset ),
                        _PEMap_QuadTree_GetDetailIndex( pMapMesh, x+offset, z-3*offset ) );

        if( nDetailLevel == 1 )
                dwResult |= 0x00000002;

        // left
        nDetailLevel=_PEMap_QuadTree_MaxDetailLevel( _PEMap_QuadTree_GetDetailIndex( pMapMesh, x-3*offset, z-offset ),
                        _PEMap_QuadTree_GetDetailIndex( pMapMesh, x-3*offset, z+offset ) );

        if( nDetailLevel == 1 )
                dwResult |= 0x00000004;

        // bottom
        nDetailLevel=_PEMap_QuadTree_MaxDetailLevel( _PEMap_QuadTree_GetDetailIndex( pMapMesh, x-offset, z+3*offset ),
                        _PEMap_QuadTree_GetDetailIndex( pMapMesh, x+offset, z+3*offset ) );

        if( nDetailLevel == 1 )
                dwResult |= 0x00000008;

        return dwResult;
}





//----------------------------------------------------------------
// Name: _GenerateMapMeshFlag_QuadTree()
// Desc: Quad tree方式生成要渲染的地图mesh标志
//                即: 第2级需要渲染的标志(标记哪个边的中点需要绘制)
//----------------------------------------------------------------
PE_VOID CPEMap::_GenerateMapMeshFlag_QuadTree(PE_MapMeshData_T* pMapMesh)
{
        PE_UINT4 i,j;
        PE_UINT4 nSize=pMapMesh->nSide>>2;
        for(i=0; i<nSize; i++)
        {
                for(j=0; j<nSize; j++)
                {
                        pMapMesh->pDetailRenderFlag[j+i*nSize]=(PE_UINT1)_PEMap_QuadTree_GetEdgeValue( pMapMesh, (j<<2)+2, (i<<2)+2, 3 );
                }
        }
}



//----------------------------------------------------------------
// Name: _GenerateMapMesh_QuadTree()
// Desc: Quad tree方式生成要渲染的地图mesh
//----------------------------------------------------------------
PE_UINT4 CPEMap::_QuadTree_RenderPatch(PE_MapMeshData_T* pMapMesh, PE_UINT4 x, PE_UINT4 z, PE_UINT4 nEdgeLength)
{
        PE_UINT4 nResult=0;
        PE_UINT4 nCount;

        PE_UINT4 i=x-1+(z-1)*(pMapMesh->nSide-1);                                // 索引点
        PE_DWORD dwFlag=0;

        // Step 1: 判断自己是否需要绘制
        if( !pMapMesh->pDetailRender )
                return nResult;

        // Step 2: 绘制子对象
        if( /*( nEdgeLength==3 && pMapMesh->pDetailRender<3 ) || */nEdgeLength>=3 )
        {
                PE_UINT4 nChildEdgeLength=1+(nEdgeLength>>1);
                PE_UINT4 nChildOffset=(nEdgeLength>>1);
                nCount=0;
                if( ( nCount = _QuadTree_RenderPatch( pMapMesh, x-nChildOffset, z-nChildOffset, nChildEdgeLength ) ) )                // Top-left
                        dwFlag |= 0x0001;

                nResult+=nCount;
               
                if( ( nCount = _QuadTree_RenderPatch( pMapMesh, x-nChildOffset, z+nChildOffset, nChildEdgeLength ) ) )                // Bottom-left
                        dwFlag |= 0x0010;
               
                nResult+=nCount;
               
                if( ( nCount = _QuadTree_RenderPatch( pMapMesh, x+nChildOffset, z-nChildOffset, nChildEdgeLength ) ) )                // Top-right
                        dwFlag |= 0x0100;
               
                nResult+=nCount;
               
                if( ( nCount = _QuadTree_RenderPatch( pMapMesh, x+nChildOffset, z+nChildOffset, nChildEdgeLength ) ) )                // Bottom-right
                        dwFlag |= 0x1000;

                nResult+=nCount;               
        }

        // Step 3: 绘制自己
        // 如果是最小的(即tile),判断自己是否需要绘制细节
        if( nEdgeLength==2 )
        {
                // 如果是最低细节,交给上级进行绘制
                if( pMapMesh->pDetailRender>1 )
                        return nResult;

                // 绘制自己本身
                // TODO: 多个细节纹理的处理

                //// 生成顶点
                m_nCountMapMeshVertex=0;
                _QuadTree_Render_AddVertex( pMapMesh, x, z, nEdgeLength, 8 );
                _QuadTree_Render_AddVertex( pMapMesh, x, z, nEdgeLength, 1 );
                _QuadTree_Render_AddVertex( pMapMesh, x, z, nEdgeLength, 3 );
                _QuadTree_Render_AddVertex( pMapMesh, x, z, nEdgeLength, 5 );
                _QuadTree_Render_AddVertex( pMapMesh, x, z, nEdgeLength, 7 );
                _QuadTree_Render_AddVertex( pMapMesh, x, z, nEdgeLength, 1 );
                nCount=m_nCountMapMeshVertex-2;

                // 绘制
                m_pRender->DrawPrimitiveUp( PE_DRAWPT_TRIANGLEFAN, m_MapMeshVertex, nCount, PE_SIZEOF(PE_MapVertexData_T) );
                nResult += nCount;
        }
        else if( nEdgeLength<=5 )
        {
                // 如果已经完全绘制
                if( dwFlag == 0x1111 )
                        return nResult;
               
                PE_DWORD dwFlag2=0;                                                                                                        // 值为0时表示不关心状态,为1时表示需要加面,为2时表示不需要加面
                // 判断是否有需要加面/减面的边
                if( nEdgeLength==3 )
                {
                        //dwFlag2 = _PEMap_QuadTree_GetEdgeValue( pMapMesh, x, z, nEdgeLength );
                        dwFlag2 = pMapMesh->pDetailRenderFlag[ (x>>2)+(z>>2)*(pMapMesh->nSide>>2) ];
                }
                else
                        dwFlag2 = 0x0f;

                // 如果子细节没有进行绘制,交给上级进行绘制
                if( nResult==0 && nEdgeLength==3 )
                {
                        if( !( dwFlag2 & 0x0f ) )
                                return nResult;
                }

                m_nCountMapMeshVertex=0;
                _QuadTree_Render_AddVertex( pMapMesh, x, z, nEdgeLength, 8 );

                // test
                //dwFlag = 0x0000;
                //dwFlag2 = 0x01000101;

                if( !(dwFlag & 0x0100) )                                                                                        // Top-right
                {
                        if( ( dwFlag2 & 0x01 ) || ( dwFlag & 0x1000 ) )
                                _QuadTree_Render_AddVertex( pMapMesh, x, z, nEdgeLength, 0 );

                        _QuadTree_Render_AddVertex( pMapMesh, x, z, nEdgeLength, 1 );
                }

                if( !(dwFlag & 0x0001) )                                                                                        // Top-left
                {
                        if( ( dwFlag2 & 0x02 ) || m_nCountMapMeshVertex < 2 )
                                _QuadTree_Render_AddVertex( pMapMesh, x, z, nEdgeLength, 2 );

                        _QuadTree_Render_AddVertex( pMapMesh, x, z, nEdgeLength, 3 );
                }
                else if( m_nCountMapMeshVertex > 1 )
                {
                        // 截断前面的
                        _QuadTree_Render_AddVertex( pMapMesh, x, z, nEdgeLength, 2 );

                        nCount=m_nCountMapMeshVertex-2;
                        m_pRender->DrawPrimitiveUp( PE_DRAWPT_TRIANGLEFAN, m_MapMeshVertex, nCount, PE_SIZEOF(PE_MapVertexData_T) );
                        nResult += nCount;
                        m_nCountMapMeshVertex=1;
                }

                if( !(dwFlag & 0x0010) )                                                                                        // Bottom-left
                {
                        if( ( dwFlag2 & 0x04 ) || m_nCountMapMeshVertex < 2 )
                                _QuadTree_Render_AddVertex( pMapMesh, x, z, nEdgeLength, 4 );

                        _QuadTree_Render_AddVertex( pMapMesh, x, z, nEdgeLength, 5 );
                }
                else if( m_nCountMapMeshVertex > 1 )
                {
                        // 截断前面的
                        _QuadTree_Render_AddVertex( pMapMesh, x, z, nEdgeLength, 4 );

                        nCount=m_nCountMapMeshVertex-2;
                        m_pRender->DrawPrimitiveUp( PE_DRAWPT_TRIANGLEFAN, m_MapMeshVertex, nCount, PE_SIZEOF(PE_MapVertexData_T) );
                        nResult += nCount;
                        m_nCountMapMeshVertex=1;
                }

                if( !( dwFlag & 0x1000 ) )                                                                                        // Bottom-right
                {
                        if( ( dwFlag2 & 0x08 ) || m_nCountMapMeshVertex < 2 )
                                _QuadTree_Render_AddVertex( pMapMesh, x, z, nEdgeLength, 6 );

                        _QuadTree_Render_AddVertex( pMapMesh, x, z, nEdgeLength, 7 );

                        if( !(dwFlag & 0x0100) )
                        {
                                if( dwFlag2 & 0x01 )
                                        _QuadTree_Render_AddVertex( pMapMesh, x, z, nEdgeLength, 0 );
                                else
                                        _QuadTree_Render_AddVertex( pMapMesh, x, z, nEdgeLength, 1 );
                        }
                        else
                                _QuadTree_Render_AddVertex( pMapMesh, x, z, nEdgeLength, 0 );
                }
                else if( m_nCountMapMeshVertex > 1 )
                {
                        _QuadTree_Render_AddVertex( pMapMesh, x, z, nEdgeLength, 6 );
                }

                if( m_nCountMapMeshVertex > 2 )
                {
                        nCount=m_nCountMapMeshVertex-2;
                        m_pRender->DrawPrimitiveUp( PE_DRAWPT_TRIANGLEFAN, m_MapMeshVertex, nCount, PE_SIZEOF(PE_MapVertexData_T) );
                        nResult += nCount;
                }
        }

        return nResult;
}

#endif

17

主题

258

帖子

264

积分

中级会员

Rank: 3Rank: 3

积分
264
发表于 2005-11-21 15:43:00 | 显示全部楼层

Re:最近做的地表

楼主强人啊!!

35

主题

161

帖子

161

积分

注册会员

Rank: 2

积分
161
发表于 2006-2-23 09:35:00 | 显示全部楼层

Re:最近做的地表

我刚学习terrain,有很多问题想请教楼主,能加我QQ或MSN吗?
QQ:10906864 群:1769475(D3D专门研究)
MSN:happyfirecn@yahoo.com.cn

25

主题

145

帖子

341

积分

中级会员

Rank: 3Rank: 3

积分
341
 楼主| 发表于 2006-2-27 16:04:00 | 显示全部楼层

Re:最近做的地表

有什么问题啊?公司不能上QQ和MSN

15

主题

1268

帖子

1268

积分

金牌会员

Rank: 6Rank: 6

积分
1268
发表于 2006-3-17 11:54:00 | 显示全部楼层

Re:最近做的地表

搂主,我好想你啊,最近在做啥工作?

25

主题

145

帖子

341

积分

中级会员

Rank: 3Rank: 3

积分
341
 楼主| 发表于 2006-3-24 11:51:00 | 显示全部楼层

Re: Re:最近做的地表

Civilian: Re:最近做的地表

搂主,我好想你啊,最近在做啥工作?

呵呵,你哪位啊?居然说记得我。。。
我最近在做一个3d游戏引擎

15

主题

1268

帖子

1268

积分

金牌会员

Rank: 6Rank: 6

积分
1268
发表于 2006-3-24 15:02:00 | 显示全部楼层

Re:最近做的地表

[忘记过去~]列,看qq号萨

25

主题

145

帖子

341

积分

中级会员

Rank: 3Rank: 3

积分
341
 楼主| 发表于 2006-3-29 17:30:00 | 显示全部楼层

Re:最近做的地表

呵呵~~你是女孩子?做游戏么?现在做这行的女孩子是稀有动物啊

15

主题

1268

帖子

1268

积分

金牌会员

Rank: 6Rank: 6

积分
1268
发表于 2006-4-9 09:56:00 | 显示全部楼层

Re:最近做的地表

俺是男的。。。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

作品发布|文章投稿|广告合作|关于本站|游戏开发论坛 ( 闽ICP备17032699号-3 )

GMT+8, 2025-6-6 14:42

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表