bspnode.cpp
来自「BSP地形系统和光照贴图的技术详解」· C++ 代码 · 共 575 行
CPP
575 行
// BspNode.cpp: implementation of the CBspNode class.
//
//////////////////////////////////////////////////////////////////////
//#include "d3dfont.h"
#include "BspNode.h"
CFrustum::~CFrustum()
{
}
CFrustum::CFrustum()
{
ZeroMemory( m_vtx, sizeof( m_vtx[0] ) * 8 );
ZeroMemory( m_plane, sizeof( m_plane[0] ) * 6 );
}
BOOL CFrustum::Make( D3DXMATRIX* pmatViewProj )
{
int i;
D3DXMATRIX matInv;
// projected的整个画面
m_vtx[0].x = -1.0f; m_vtx[0].y = -1.0f; m_vtx[0].z = -1.0f;
m_vtx[1].x = 1.0f; m_vtx[1].y = -1.0f; m_vtx[1].z = -1.0f;
m_vtx[2].x = 1.0f; m_vtx[2].y = -1.0f; m_vtx[2].z = 1.0f;
m_vtx[3].x = -1.0f; m_vtx[3].y = -1.0f; m_vtx[3].z = 1.0f;
m_vtx[4].x = -1.0f; m_vtx[4].y = 1.0f; m_vtx[4].z = -1.0f;
m_vtx[5].x = 1.0f; m_vtx[5].y = 1.0f; m_vtx[5].z = -1.0f;
m_vtx[6].x = 1.0f; m_vtx[6].y = 1.0f; m_vtx[6].z = 1.0f;
m_vtx[7].x = -1.0f; m_vtx[7].y = 1.0f; m_vtx[7].z = 1.0f;
D3DXMatrixInverse(&matInv, NULL, pmatViewProj );
// 将view * proj的逆矩阵与 vtx相乘,出现 world坐标
for( i = 0; i < 8; i++ )
D3DXVec3TransformCoord( &m_vtx[i], &m_vtx[i], &matInv );
// 通过得到的 world坐标制作 frustum plane
D3DXPlaneFromPoints(&m_plane[0], m_vtx+4, m_vtx+7, m_vtx+6); // up plane
D3DXPlaneFromPoints(&m_plane[1], m_vtx , m_vtx+1, m_vtx+2); // bottom plane
D3DXPlaneFromPoints(&m_plane[2], m_vtx , m_vtx+4, m_vtx+5); // near plane
D3DXPlaneFromPoints(&m_plane[3], m_vtx+2, m_vtx+6, m_vtx+7); // far plane
D3DXPlaneFromPoints(&m_plane[4], m_vtx , m_vtx+3, m_vtx+7); // left plane
D3DXPlaneFromPoints(&m_plane[5], m_vtx+1, m_vtx+5, m_vtx+6); // right plane
// for OpenGL
// MakePlane(&m_plane[0], m_vtx+4, m_vtx+7, m_vtx+6); // up plane
// MakePlane(&m_plane[1], m_vtx , m_vtx+1, m_vtx+2); // bottom plane
// MakePlane(&m_plane[2], m_vtx , m_vtx+4, m_vtx+5); // near plane
// MakePlane(&m_plane[3], m_vtx+2, m_vtx+6, m_vtx+7); // far plane
// MakePlane(&m_plane[4], m_vtx , m_vtx+3, m_vtx+7); // left plane
// MakePlane(&m_plane[5], m_vtx+1, m_vtx+5, m_vtx+6); // right plane
return TRUE;
}
int CFrustum::IsIn( D3DXVECTOR3* pVec )
{
float fDist;
int i = 0, nLeft = 0, nRight = 0, nUp = 0;
{
for( i = 0; i < 4; i++ )
{
fDist = D3DXPlaneDotCoord( &m_plane[4], &pVec[i] );
if( fDist > 0 )
nLeft++;
fDist = D3DXPlaneDotCoord( &m_plane[5], &pVec[i] );
if( fDist > 0 )
nRight++;
// fDist = D3DXPlaneDotCoord( &m_plane[0], &pVec[i] );
// if( fDist > 0 )
// nUp++;
}
if( (nLeft + nRight ) == 0 )
return 2; //完全绘制好的时候
else if( nLeft == 4 || nRight == 4 )
return 0; //完全没有绘制好的时候
else
return 1; //部分绘制的时候
// for OpenGL
// fDist = m_plane[4].a * pv->x + m_plane[4].b * pv->y + m_plane[4].c * pv->z + m_plane[4].d;
// if( fDist < 0 ) return FALSE;
// fDist = m_plane[5].a * pv->x + m_plane[5].b * pv->y + m_plane[5].c * pv->z + m_plane[5].d;
// if( fDist < 0 ) return FALSE;
}
return TRUE;
}
BOOL CFrustum::Draw( LPDIRECT3DDEVICE8 pDev )
{
WORD index[] = { 0, 2, 1,
0, 3, 2,
4, 7, 6,
4, 6, 5,
1, 5, 6,
1, 6, 2,
0, 3, 7,
0, 7, 4,
0, 4, 5,
0, 5, 1,
3, 7, 6,
3, 6, 2 };
typedef struct tagVTX
{
D3DXVECTOR3 p;
DWORD diffuse;
} VTX;
VTX vtx[8];
for( int i = 0 ; i < 8 ; i++ )
{
vtx[i].p = m_vtx[i];
vtx[i].diffuse = 0x80ff0000;
}
pDev->SetVertexShader( D3DFVF_XYZ|D3DFVF_DIFFUSE );
pDev->SetStreamSource( 0, NULL, 0 );
pDev->SetIndices( NULL, 0 );
pDev->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE);
pDev->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
pDev->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_ONE );
pDev->SetTexture( 0, NULL );
pDev->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
pDev->DrawIndexedPrimitiveUP( D3DPT_TRIANGLELIST, 0, 8, 12, index, D3DFMT_INDEX16, vtx, sizeof( vtx[0] ) );
pDev->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_MODULATE );
pDev->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
pDev->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );
pDev->SetRenderState( D3DRS_ALPHABLENDENABLE, FALSE );
return TRUE;
}
void MakePlane( D3DXPLANE* pPlane, D3DXVECTOR3* pv0, D3DXVECTOR3* pv1, D3DXVECTOR3* pv2 )
{
D3DXPlaneFromPoints( pPlane, pv0, pv1, pv2 );
// for OpenGL
// CVector v0, v1, v2;
// v1 = *pv1 - *pv0;
// v2 = *pv2 - *pv0;
// D3DXVec3Cross( &v0, &v1, &v2 );
// D3DXVec3Normalize( &v0, &v0 );
// pPlane->a = v0.x;
// pPlane->b = v0.y;
// pPlane->c = v0.z;
// pPlane->d = -( v0.x * pv0->x + v0.y * pv0->y + v0.z * pv0->z );
}
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CWinding::CWinding()
{
n = 0;
}
CWinding::~CWinding()
{
}
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CBspNode::CPortal::CPortal()
{
m_pNext[0] = NULL;
m_pNext[1] = NULL;
m_pWinding = NULL;
m_pNode[0] = NULL;
m_pNode[1] = NULL;
m_nVisCnt = 0;
m_nFaceCnt = 0;
m_bRender = TRUE;
m_ppFaceList = NULL;
}
CBspNode::CPortal::~CPortal()
{
if( m_pWinding )
{
delete m_pWinding;
m_pWinding = NULL;
}
if( m_ppFaceList )
{
delete[] m_ppFaceList;
}
m_pNode[0] = NULL;
m_pNode[1] = NULL;
m_pNext[0] = NULL;
m_pNext[1] = NULL;
}
void CBspNode::CPortal::AddPortalToNodes( CBspNode *front, CBspNode *back )
{
if( m_pNode[0] || m_pNode[1] )
; // error
m_pNode[0]= front;
if( front )
{
m_pNext[0] = front->m_pPortals;
front->m_pPortals = this;
}
m_pNode[1] = back;
if( back )
{
m_pNext[1] = back->m_pPortals;
back->m_pPortals = this;
}
}
void CBspNode::CPortal::RemovePortalFromNode ( CBspNode *l )
{
CPortal **pp, *t;
// remove reference to the current portal
pp = &l->m_pPortals;
while (1)
{
t = *pp;
if (!t)
return; //error
if ( t == this )
break;
if (t->m_pNode[0] == l)
pp = &t->m_pNext[0];
else if (t->m_pNode[1] == l)
pp = &t->m_pNext[1];
else
return; //error
}
if ( m_pNode[0] == l)
{
*pp = m_pNext[0];
m_pNode[0] = NULL;
}
else if (m_pNode[1] == l)
{
*pp = m_pNext[1];
m_pNode[1] = NULL;
}
}
void CBspNode::CPortal::Render( LPDIRECT3DDEVICE8 pd3dDevice )
{
if( m_pWinding )
pd3dDevice->DrawPrimitiveUP( D3DPT_TRIANGLEFAN, 2, m_pWinding->vPoint ,sizeof( D3DXVECTOR3 ));
// if( m_pNode[0] )
// m_pNode[0]->Render( pd3dDevice, NULL );
// if( m_pNode[1] )
// m_pNode[1]->Render( pd3dDevice, NULL );
}
CFace::CFace()
{
m_bDelete = FALSE;
m_bCollision = FALSE;
m_bUsed = FALSE;
m_bInside = FALSE;
m_nNum = 0;
m_pNext = NULL;
m_pPrev = NULL;
m_vList = NULL;
m_nTexture = -1;
m_nLightMap = 0;
}
CFace::~CFace()
{
if( m_vList )
{
delete[] m_vList;
}
}
CFace* CFace::CreateFace()
{
CFace* p = new CFace();
return p;
}
BOOL CFace::MakePlane( BSPVERTEX* v, int n )
{
/*
if( n < 3 )
return FALSE;
// D3DXPlaneFromPoints( &m_facePlane, &v[0], &v[2], &v[1] );
m_vList = v;
m_nNum = n;
*/
return TRUE;
}
BOOL CFace::AddNext(CFace *pNext)
{
m_pNext = pNext;
return TRUE;
}
BOOL CFace::AddTail(CFace *pTail)
{
if( m_pNext )
m_pNext->AddTail( pTail );
else
{
m_pNext = pTail;
return TRUE;
}
return FALSE;
}
BOOL CFace::SetVertexList(BSPVERTEX *pList)
{
m_vList = pList;
return TRUE;
}
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CBspNode::CBspNode()
{
m_bIsSolid = FALSE;
m_bIsLeaf = FALSE;
m_bRender = FALSE;
m_pBack = NULL;
m_pFront = NULL;
m_pFaceList = NULL;
m_pPortals = NULL;
m_pTXData = NULL;
m_vMax = D3DXVECTOR3( -BSP_BOGUS, -BSP_BOGUS, -BSP_BOGUS );
m_vMin = D3DXVECTOR3( BSP_BOGUS, BSP_BOGUS, BSP_BOGUS );
}
CBspNode::~CBspNode()
{
if( m_pFaceList && !m_bIsSolid && m_bIsLeaf )
{
CFace * curr = NULL, * next = NULL;
for( curr = m_pFaceList; curr ; curr = next )
{
next = curr->m_pNext;
curr->m_pNext = NULL;
delete curr;
}
}
if( m_pBack )
delete m_pBack;
if( m_pFront )
delete m_pFront;
}
BOOL CBspNode::Render(LPDIRECT3DDEVICE8 pd3dDevice, CD3DFont* pFont )
{
// pd3dDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE );
if( m_bIsLeaf && !m_bIsSolid )
{
pd3dDevice->SetRenderState(D3DRS_LIGHTING,FALSE);
CFace * f;
for( f = m_pFaceList; f ; f = f->m_pNext )
{
pd3dDevice->SetTexture( 0, m_pTXData[f->m_nTexture].texture );
/*
if( pFont )
{
for( int i = 0; i < f->m_nNum ; i++ )
{
D3DXMATRIX mW, mV, mP, mO;
pd3dDevice->GetTransform( D3DTS_WORLD, &mW );
pd3dDevice->GetTransform( D3DTS_VIEW, &mV );
pd3dDevice->GetTransform( D3DTS_PROJECTION, &mP );
mO = mW * mV * mP;
D3DXVECTOR3 vI = f->m_vList[i].pos;
D3DXVECTOR3 vO;
D3DXVec3TransformCoord( &vO, &vI, &mO );
char str[16];
wsprintf( str, "( %d, %d, %d )", (int)f->m_vList[i].pos.x, (int)f->m_vList[i].pos.y,(int)f->m_vList[i].pos.z );
pFont->DrawText(400.0f * (vO.x+1.0f), 600 - 300.0f * (vO.y+1.0f), 0xff000000, str );
}
}
else */
pd3dDevice->DrawPrimitiveUP(D3DPT_TRIANGLELIST, 1,f->m_vList, sizeof( BSPVERTEX ) );
}
}
if( m_pBack )
m_pBack->Render( pd3dDevice, pFont );
if( m_pFront )
m_pFront->Render( pd3dDevice, pFont );
return TRUE;
}
BOOL CBspNode::SetFrontNode(CBspNode *pNode)
{
m_pFront = pNode;
return TRUE;
}
BOOL CBspNode::SetBackNode(CBspNode *pNode)
{
m_pBack = pNode;
return TRUE;
}
BOOL CBspNode::SetFaceList(CFace *pFace)
{
m_pFaceList = pFace;
return TRUE;
}
BOOL CBspNode::IsCollision( BOOL &b, D3DXVECTOR3 &v, CBspNode * & render_start)
{
if( m_bIsLeaf && !m_bIsSolid )
{
render_start = this;
}
if( m_bIsSolid )
{
b = TRUE;
return TRUE;
}
int res = ClassifyPoint( v );
if( res == FACE_FRONT )
{
if( m_pFront && !b )
{
m_pFront->IsCollision( b, v, render_start );
}
}
else if( res == FACE_BACK )
{
if( m_pBack && !b )
{
m_pBack->IsCollision( b, v, render_start );
}
}
return FALSE;
}
int CBspNode::ClassifyPoint(D3DXVECTOR3 &v)
{
float res = D3DXPlaneDotCoord( &m_plane, &v );
if( res > EPSILON )
return FACE_FRONT;
else if( res < -EPSILON )
return FACE_BACK;
else if( res < EPSILON && res > -EPSILON )
return FACE_ON;
return FACE_SPLIT;
}
int CBspNode::GetFaceCount()
{
int count = 0;
for( CFace* f = m_pFaceList ; f ; f = f->m_pNext )
{
count++;
}
return count;
}
void CBspNode::InitRender()
{
m_bRender = FALSE;
if( m_pFront )
m_pFront->InitRender();
if( m_pBack )
m_pBack->InitRender();
}
///////////////////////////////// THING CLASS ///////////////////
void CThing::InitThing()
{
m_pFaceList = new BSPVERTEX[m_nFaceCount*3];
int n = 0;
for( int i = 0; i < m_nFaceCount ; i++)
{
m_pFaceList[n] = m_pVertex[m_pTriangleIndex[i]._0];
m_pFaceList[n].u = m_pTVtx[m_pTIndex[i]._0].x;
m_pFaceList[n].v = m_pTVtx[m_pTIndex[i]._0].z;
n++;
m_pFaceList[n] = m_pVertex[m_pTriangleIndex[i]._1];
m_pFaceList[n].u = m_pTVtx[m_pTIndex[i]._1].x;
m_pFaceList[n].v = m_pTVtx[m_pTIndex[i]._1].z;
n++;
m_pFaceList[n] = m_pVertex[m_pTriangleIndex[i]._2];
m_pFaceList[n].u = m_pTVtx[m_pTIndex[i]._2].x;
m_pFaceList[n].v = m_pTVtx[m_pTIndex[i]._2].z;
n++;
/*
CFace *f = CFace::CreateFace();
BSPVERTEX* ver = new BSPVERTEX[3];
ver[0] = m_pVertex[m_pTriangleIndex[i]._0];
ver[1] = m_pVertex[m_pTriangleIndex[i]._1];
ver[2] = m_pVertex[m_pTriangleIndex[i]._2];
ver[0].u = m_pTVtx[m_pTIndex[i]._0].x;
ver[0].v = m_pTVtx[m_pTIndex[i]._0].z;
ver[1].u = m_pTVtx[m_pTIndex[i]._1].x;
ver[1].v = m_pTVtx[m_pTIndex[i]._1].z;
ver[2].u = m_pTVtx[m_pTIndex[i]._2].x;
ver[2].v = m_pTVtx[m_pTIndex[i]._2].z;
f->m_vList = ver;
f->m_nNum = 3;
// f->m_nTexture = m_nTexture;
D3DXPLANE plane;
D3DXPlaneFromPoints( &plane, &ver[0].pos, &ver[1].pos, &ver[2].pos );
int res = FindSamePlane( plane );
if( res == -1 )
{
m_planes[m_nTotalPlane] = plane;
f->m_nPlane = m_nTotalPlane++;
}
else
f->m_nPlane = res;
f->AddNext( m_pFaceList );
m_pFaceList = f;
*/
}
delete[] m_pVertex;
delete[] m_pTriangleIndex;
delete[] m_pTVtx;
delete[] m_pTIndex;
}
int CThing::FindSamePlane(D3DXPLANE &plane)
{
for( int i = 0 ; i < m_nTotalPlane ; i++ )
{
if( ComparePlane( m_planes[i], plane ) )
return i;
}
return -1;
}
BOOL CThing::ComparePlane(D3DXPLANE &a, D3DXPLANE &b)
{
if( a.a == b.a && a.b == b.b && a.c == b.c && a.d == b.d )
return TRUE;
return FALSE;
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?