四叉树平面剔除
来源:互联网 发布:软件推广下载 编辑:程序博客网 时间:2024/04/29 18:25
四叉树平面剔除文档
首是这是做平面剔除,当然,如果是空间中的场景管理那就得用八叉树了,四叉树剔除主要的原理如下:
如下图,
首先构造四叉树,对整个需要剔除的区域首先分成四等分( 用粗实线分开 ),即为该节点的四个子节点( 左下子节点,右下子节点,左下子节点,右上子节点等 ),然后再对四个子节点再分成四等分,依此下去,一直分到足够细为止,
第二步,将判断图元在那个子节点中,比如面1,先检测它可以被四叉树的根节点(整个图)的任一子节点全部包含,如果是则继续判断是否能被其包括面1的那个子节点的任一子节点包含,如果不是则被该节点包含,如果是则依次下去,直到叶子节点,则面1就属于该叶子节点,如果不是则被该节点包含.面1是被根节点的右上子节点的右上子节点包含.
第三步:视锥剔除:对检测根结果是否在视区内,如果在,则渲染属于根节点的所有图元,下面的话则渲染面3,然后再检测其四个子节点是否可见,因为左上和左下两个子节点完成不可见则直接跳过,因为其左下节点可见,则渲染属于左下子节点的所有图元,再检测左下子节点的四个子节点,有两个子节点可见渲染属于它的所有图元,依此下去,其渲染有3个图元:面3,面2和面1.当然,如果能将图元分散成属于每个子节点就更好,不用可见一点点却要将整个图元全部渲染.
线1 线2 面1 面2 面3
根据以下的思想的代码如下:
四叉树类如下:
class CQuadTree
{
public:
CQuadTree(void);
public:
~CQuadTree(void);
CQuadTree( enumAttribute attribute );
enumVisible Frustum2D( );
// 渲染所有的图元
void RenderAllPrimitive( IDirect3DDevice9* pd3dDevice, CCameraPerspective * pCurCamera , float fElapsedTime, D3DVIEWPORT9 * pVP, int nAcross, int nErect );
// 四个子节点
CQuadTree *pLeftDownChild;
CQuadTree *pRightDownChild;
CQuadTree *pLeftUpChild;
CQuadTree *pRightUpChild;
// 该四叉树的基本范围中最小点
D3DXVECTOR2 m_Min;
// 该四叉树的基本范围中最大点
D3DXVECTOR2 m_Max;
// 对图元进行的判断,判断该图元是否在四叉树的某个子节点内
bool IsIn( long ID, enumPrimitive primitivetype, D3DXVECTOR2 min, D3DXVECTOR2 max );
// 构造四叉树
bool SubDivide( D3DXVECTOR2 min, D3DXVECTOR2 max, int levelsize );
// 点图元
std::vector< long > m_vecPoint;
// 线图元
std::vector< long > m_vecLine;
// 面图元
std::vector< long > m_vecArea;
// 属性类型
enumAttribute attributetype;
// 渲染四叉树
void RenderQuadTree( bool bFrustum, IDirect3DDevice9* pd3dDevice, CCameraPerspective * pCurCamera , float fElapsedTime, D3DVIEWPORT9 * pVP, int nAcross, int nErect );
};
第一步:
bool CQuadTree::SubDivide( D3DXVECTOR2 min, D3DXVECTOR2 max, int levelsize )
{
// 该子节点的区域赋值
m_Min = min;
m_Max = max;
// 是否不能再分,如果不能再分则返回
if( m_Max.x - m_Min.x <= ::MuseREGetTerrain()->GetWidth() / GRIDNUM || levelsize <= 1)
{
return false;
}
// 得到用于子节点的七个点(两个已知),求去求知的五个
// 下面的中间
D3DXVECTOR2 DownMid = D3DXVECTOR2( min.x + ::MuseREGetTerrain()->GetWidth() * ( levelsize / 2) /GRIDNUM, min.y );
// 中间的左面
D3DXVECTOR2 MidLeft = D3DXVECTOR2( min.x, min.y + ::MuseREGetTerrain()->GetWidth() * ( levelsize / 2) /GRIDNUM );
// 中心
D3DXVECTOR2 center = D3DXVECTOR2( min.x + ::MuseREGetTerrain()->GetWidth() * ( levelsize / 2) /GRIDNUM,
min.y + ::MuseREGetTerrain()->GetWidth() * ( levelsize / 2) /GRIDNUM );
// 中间的右面
D3DXVECTOR2 MidRight = D3DXVECTOR2( m_Max.x, min.y + ::MuseREGetTerrain()->GetWidth() * ( levelsize / 2) /GRIDNUM );
// 上面的中间
D3DXVECTOR2 UpMid = D3DXVECTOR2( min.x + ::MuseREGetTerrain()->GetWidth() * ( levelsize / 2) /GRIDNUM, m_Max.y);
// 分左下子节点
pLeftDownChild = new CQuadTree( attributetype );
pLeftDownChild->SubDivide( m_Min, center, levelsize / 2 );
// 分右下子节点
pRightDownChild = new CQuadTree( attributetype );
pRightDownChild->SubDivide( DownMid, MidRight, levelsize / 2 );
// 分左上子节点
pLeftUpChild = new CQuadTree( attributetype );
pLeftUpChild->SubDivide( MidLeft, UpMid, levelsize / 2 );
// 分右上子节点
pRightUpChild = new CQuadTree( attributetype );
pRightUpChild->SubDivide( center, m_Max, levelsize / 2);
return true;
}
第二步,对所有图元做判断.
// 检测当前的图元是否在节点中
bool CQuadTree::IsIn(long ID, enumPrimitive primitivetype, D3DXVECTOR2 min, D3DXVECTOR2 max )
{
// 是否包含该项图元
if( min.x > m_Min.x && max.x < m_Max.x && min.y > m_Min.y && max.y < m_Max.y )
{
bool bResultLD;
bool bResultRD;
bool bResultLU;
bool bResultRU;
// 判断该节点是否是叶子节点
if( pLeftDownChild != NULL || pRightDownChild != NULL || pLeftUpChild != NULL || pRightUpChild != NULL )
{
// 是否包含在该子节点中
bResultLD = pLeftDownChild->IsIn( ID, primitivetype, min, max ) ;
if( bResultLD )
return true;
bResultRD = pRightDownChild->IsIn(ID, primitivetype, min, max );
if( bResultRD )
return true;
bResultLU = pLeftUpChild->IsIn( ID, primitivetype, min, max );
if( bResultLU )
return true;
bResultRU = pRightUpChild->IsIn( ID, primitivetype, min, max );
if( bResultRU )
return true;
}
// 如果不属性任一一个子节点加在该节点中
switch( primitivetype )
{
case POINTTYPE:
m_vecPoint.push_back( ID );
break;
case LINETYPE:
m_vecLine.push_back( ID );
break;
case AREATYPE:
m_vecArea.push_back( ID );
break;
default:
break;
}
return true;
}
return false;
}
第三步,渲染四叉树:
void CQuadTree::RenderQuadTree( bool bFrustum, IDirect3DDevice9* pd3dDevice, CCameraPerspective * pCurCamera , float fElapsedTime, D3DVIEWPORT9 * pVP, int nAcross, int nErect )
{
// 默认是完全可见
enumVisible visible = TOTALSIGHT;
// 视锥剔除
if( bFrustum )
visible = Frustum2D();
// 如果不是完全不可见
if( visible != TOTALSIGHTLESS )
{
// 渲染所有的图元
RenderAllPrimitive( pd3dDevice, pCurCamera , fElapsedTime, pVP, nAcross, nErect );
// 如果是叶子节点
if( pLeftDownChild == NULL || pRightDownChild == NULL || pLeftUpChild == NULL || pRightUpChild == NULL )
{
return;
}
// 全部可见或该结点的父节点全部可见,bFrustum为false时,不用再做锥除,因为其父节点已经完全可见
if( !bFrustum || visible == TOTALSIGHT )
{
// 渲染所有的子节点且不用再做D的视锥剔除
pLeftDownChild->RenderQuadTree( false, pd3dDevice, pCurCamera , fElapsedTime, pVP, nAcross, nErect );
pRightDownChild->RenderQuadTree( false, pd3dDevice, pCurCamera , fElapsedTime, pVP, nAcross, nErect );
pLeftUpChild->RenderQuadTree( false, pd3dDevice, pCurCamera , fElapsedTime, pVP , nAcross, nErect);
pRightUpChild->RenderQuadTree( false, pd3dDevice, pCurCamera , fElapsedTime, pVP, nAcross, nErect);
//
}
else
{
// 部分可见
if( visible == PARTILYSIGHT )
{
// 渲染所有的子节点且要做D的视锥剔除
pLeftDownChild->RenderQuadTree( true, pd3dDevice, pCurCamera , fElapsedTime, pVP, nAcross, nErect );
pRightDownChild->RenderQuadTree( true, pd3dDevice, pCurCamera , fElapsedTime, pVP, nAcross, nErect );
pLeftUpChild->RenderQuadTree( true , pd3dDevice, pCurCamera , fElapsedTime, pVP, nAcross, nErect);
pRightUpChild->RenderQuadTree( true, pd3dDevice, pCurCamera , fElapsedTime, pVP, nAcross, nErect);
}
}
}
}
- 四叉树平面剔除
- 四叉树-2D平面的渲染剔除、碰撞次数优化
- 剔除
- 平面
- 四叉树和八叉树剔除Quadtree and Octree Culling Alternative
- 剔除bug
- 剔除session
- 剔除字符
- 剔除同类产品
- 引擎技术研究之场景管理------四叉树与视椎剔除技术
- 引擎技术研究之场景管理------四叉树与视椎剔除技术
- Excel 剔除重復數據
- 多边形的正反面,剔除
- 多边形背面剔除
- 视锥剔除优化
- 剔除行末回车
- Speedtree 剔除优化原理
- 连续票号剔除算法
- 伤心透了
- DateTime.Tostring()的用法
- freepbx模块开发 FreePbx API:modules
- [转 张晓辉]在实施数据仓储过程中应避免的11个错误
- JUnit4新特征
- 四叉树平面剔除
- oracle job的奇怪问题(已解决,个人分析是大小写转换的缘故)
- oracle积累
- 来自QQ,搞笑的东西
- ROR学习笔记(一)
- 找工作
- 简介 Google 开放式 WebServices 查询接口
- SOA技术圈子会后感
- 关于WebBrowser2控件API函数说明