📄 bspmanager.cpp
字号:
GetToken( fp, lpszFormer );
D3DXMATRIX mat;
while(1)
{
GetFormerNOther(fp, lpszFormer, lpszOther);
for( int i = 0 ; i < 5 ; i++ )
{
ch[i] = lpszFormer[i];
}
ch[5] = '\0';
if(!strcmp(lpszOther, "EOF"))
break;
else if(!strcmp(ch, "Fspot"))
{
GetTM( lpszOther, &mat );
m_pLight[num].m_radius = LIGHT_RADIUS;
m_pLight[num++].m_vPosition = D3DXVECTOR3( mat._41, mat._42, mat._43 );
}
}
}
void CBspManager::SetFaceIndex(FILE* fp)
{
char lpszFormer[STR_MAX], lpszOther[STR_MAX];
int num = 0;
CBrush* curr = NULL;
WORD first=0, second=0, third=0;
GetToken( fp, lpszFormer );
while(1)
{
GetFormerNOther(fp, lpszFormer, lpszOther);
if(!strcmp(lpszOther, "EOF"))
break;
else if(!strcmp(lpszFormer, "NAME"))
{
curr = GetBrushFromName( lpszOther );
num = 0;
}
else if(!strcmp(lpszFormer, "COUNT"))
{
curr->m_nFaceCount = atoi(lpszOther);
curr->m_pTriangleIndex = new TRIANGLEINDEX[curr->m_nFaceCount];
}
else if( curr )
{
if(curr->m_nFaceCount > 0)
{
//GetIndex中, 互相改变first和 third.
GetIndex(lpszOther, &first, &second, &third);
curr->m_pTriangleIndex[num]._0 = first;
curr->m_pTriangleIndex[num]._1 = second;
curr->m_pTriangleIndex[num]._2 = third;
num++;
}
}
}
}
void CBspManager::GetToken(FILE* fp, LPSTR lpszToken)
{
char ch = 0;
while( fgetc(fp)!=START_BRACE );
while(1)
{
ch = fgetc(fp);
if(ch == END_BRACE)
{
*lpszToken = NULL;
return;
}
*lpszToken = ch;
lpszToken++;
}
}
void CBspManager::GetFormerNOther(FILE* fp, LPSTR lpszFormer, LPSTR lpszOther)
{
GetToken(fp, lpszFormer);
GetToken(fp, lpszOther);
}
BOOL CBspManager::Render(LPDIRECT3DDEVICE8 pd3dDevice , CD3DFont* pFont)
{
pd3dDevice->SetVertexShader( D3DFVF_BSPVERTEX );
pd3dDevice->SetStreamSource( 0, NULL, 0 );
pd3dDevice->SetIndices( NULL, 0 );
pd3dDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_WIREFRAME);
pd3dDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE );
// pd3dDevice->DrawIndexedPrimitiveUP(D3DPT_TRIANGLELIST, 0, m_nVertexCount,
// m_nFaceCount, m_pTriangleIndex, D3DFMT_INDEX16, m_pPos, sizeof( BSPVERTEX ) );
// if( m_pCSGBrushs )
// {
// m_pCSGBrushs->Render( pd3dDevice, pFont );
// }
m_pBspRoot->Render( pd3dDevice, pFont );
return TRUE;
}
BOOL CBspManager::RenderPVS( LPDIRECT3DDEVICE8 pd3dDevice, BOOL bSolid, CD3DFont* pFont )
{
pd3dDevice->SetVertexShader( D3DFVF_BSPVERTEX );
pd3dDevice->SetStreamSource( 0, NULL, 0 );
pd3dDevice->SetIndices( NULL, 0 );
if( bSolid )
pd3dDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
else
pd3dDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_WIREFRAME);
pd3dDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW );
m_pBspRoot->InitRender();
CBspNode::CPortal* portal = m_pRenderNode->m_pPortals;
for( int i = 0 ; i < portal->m_nFaceCnt ; i++ )
{
pd3dDevice->SetRenderState(D3DRS_LIGHTING,FALSE);
pd3dDevice->SetTexture( 0, m_pTXData[portal->m_ppFaceList[i]->m_nTexture].texture);
pd3dDevice->DrawPrimitiveUP( D3DPT_TRIANGLELIST, 1,
portal->m_ppFaceList[i]->m_vList, sizeof( BSPVERTEX ) ) ;
}
if( pFont )
{
D3DXMATRIX mW, mV, mP, mO;
pd3dDevice->GetTransform( D3DTS_WORLD, &mW );
pd3dDevice->GetTransform( D3DTS_VIEW, &mV );
pd3dDevice->GetTransform( D3DTS_PROJECTION, &mP );
mO = mW * mV * mP;
char str[32];
wsprintf( str, "COUNT FACE( %d )", portal->m_nFaceCnt );
pFont->DrawText(400.0f, 20.0f, 0xffffff00, str );
}
/*
for( portal = m_pRenderNode->m_pPortals ; portal ; portal = portal->m_pNext[0] )
{
CFace* f = NULL;
if( !portal->m_pNode[0]->m_bRender )
{
portal->m_pNode[0]->m_bRender = TRUE;
portal->m_pNode[0]->Render( pd3dDevice, NULL );
}
if( portal->m_pNode[1] && !portal->m_pNode[1]->m_bRender )
{
portal->m_pNode[1]->m_bRender = TRUE;
f = portal->m_pNode[1]->m_pFaceList;
portal->m_pNode[1]->Render( pd3dDevice, NULL );
}
for( int i = 0 ; i < portal->m_nVisCnt ; i++ )
{
if( !portal->m_visPortals[i]->m_pNode[0]->m_bRender )
{
portal->m_visPortals[i]->m_pNode[0]->m_bRender = TRUE;
portal->m_visPortals[i]->m_pNode[0]->Render( pd3dDevice, NULL );
}
if( portal->m_visPortals[i]->m_pNode[1] && !portal->m_visPortals[i]->m_pNode[1]->m_bRender )
{
portal->m_visPortals[i]->m_pNode[1]->m_bRender = TRUE;
portal->m_visPortals[i]->m_pNode[1]->Render( pd3dDevice, NULL );
}
}
}
*/
return TRUE;
}
void CBspManager::TryPVS()
{
for( int i = 0 ; i < m_nPortalCnt ; i++ )
{
PortalFlow( m_ppPortals[i] );
}
for( i = 0 ; i < m_nPortalCnt ; i++ )
{
m_pBspRoot->InitRender();
CBspNode::CPortal* portal = m_ppPortals[i];
m_ppPortals[i]->m_nFaceCnt = 0;
for( ; portal ; portal = portal->m_pNext[0] )
{
CFace* f = NULL;
if( !portal->m_pNode[0]->m_bRender )
{
portal->m_pNode[0]->m_bRender = TRUE;
for( f = portal->m_pNode[0]->m_pFaceList ; f ; f = f->m_pNext )
m_ppPortals[i]->m_nFaceCnt++;
}
if( portal->m_pNode[1] && !portal->m_pNode[1]->m_bRender )
{
portal->m_pNode[1]->m_bRender = TRUE;
for( f = portal->m_pNode[1]->m_pFaceList ; f ; f = f->m_pNext )
m_ppPortals[i]->m_nFaceCnt++;
}
for( int j = 0 ; j < portal->m_nVisCnt ; j++ )
{
if( !portal->m_visPortals[j]->m_pNode[0]->m_bRender )
{
portal->m_visPortals[j]->m_pNode[0]->m_bRender = TRUE;
for( f = portal->m_visPortals[j]->m_pNode[0]->m_pFaceList; f ; f = f->m_pNext )
m_ppPortals[i]->m_nFaceCnt++;
}
if( portal->m_visPortals[j]->m_pNode[1] && !portal->m_visPortals[j]->m_pNode[1]->m_bRender )
{
portal->m_visPortals[j]->m_pNode[1]->m_bRender = TRUE;
for( f = portal->m_visPortals[j]->m_pNode[1]->m_pFaceList; f ; f = f->m_pNext )
m_ppPortals[i]->m_nFaceCnt++;
}
}
}
}
for( i = 0 ; i < m_nPortalCnt ; i++ )
{
m_pBspRoot->InitRender();
CBspNode::CPortal* portal = m_ppPortals[i];
portal->m_ppFaceList = new CFace*[portal->m_nFaceCnt];
int fCount = 0 ;
for( ; portal ; portal = portal->m_pNext[0] )
{
CFace* f = NULL;
if( !portal->m_pNode[0]->m_bRender )
{
portal->m_pNode[0]->m_bRender = TRUE;
for( f = portal->m_pNode[0]->m_pFaceList ; f ; f = f->m_pNext )
m_ppPortals[i]->m_ppFaceList[fCount++] = f;
}
if( portal->m_pNode[1] && !portal->m_pNode[1]->m_bRender )
{
portal->m_pNode[1]->m_bRender = TRUE;
for( f = portal->m_pNode[1]->m_pFaceList ; f ; f = f->m_pNext )
m_ppPortals[i]->m_ppFaceList[fCount++] = f;
}
for( int j = 0 ; j < portal->m_nVisCnt ; j++ )
{
if( !portal->m_visPortals[j]->m_pNode[0]->m_bRender )
{
portal->m_visPortals[j]->m_pNode[0]->m_bRender = TRUE;
for( f = portal->m_visPortals[j]->m_pNode[0]->m_pFaceList; f ; f = f->m_pNext )
m_ppPortals[i]->m_ppFaceList[fCount++] = f;
}
if( portal->m_visPortals[j]->m_pNode[1] && !portal->m_visPortals[j]->m_pNode[1]->m_bRender )
{
portal->m_visPortals[j]->m_pNode[1]->m_bRender = TRUE;
for( f = portal->m_visPortals[j]->m_pNode[1]->m_pFaceList; f ; f = f->m_pNext )
m_ppPortals[i]->m_ppFaceList[fCount++] = f;
}
}
}
}
}
void CBspManager::PortalFlow( CBspNode::CPortal* portal )
{
PVSDATA pvs;
int faceCnt = 0;
CBspNode::CPortal* p = portal;
pvs.source = portal->m_pWinding;
portal->m_nFaceCnt += portal->m_pNode[0]->GetFaceCount(); //for Render
if( !portal->m_pNode[1] )
return;
portal->m_nFaceCnt += portal->m_pNode[1]->GetFaceCount(); //for Render
CBspNode::CPortal* p1 = portal->m_pNode[1]->m_pPortals;
for( ; p1 ; p1 = p1->m_pNext[0] )
{
D3DXPLANE plane;
D3DXPlaneFromPoints( &plane, &portal->m_pWinding->vPoint[0],
&portal->m_pWinding->vPoint[1],
&portal->m_pWinding->vPoint[2] );
BSPVERTEX winding[8];
for( int k = 0; k < p1->m_pWinding->n; k++ )
{
winding[k].pos = p1->m_pWinding->vPoint[k];
}
if( FACE_ON == Classify( &plane, winding, p1->m_pWinding->n ) )
continue;
if( !IsEqualWinding( portal->m_pWinding, p1->m_pWinding ) )
{
portal->m_visPortals[portal->m_nVisCnt++] = p1;
portal->m_nFaceCnt += p1->m_pNode[0]->GetFaceCount(); //for Render
pvs.pass = p1->m_pWinding;
if( !p1->m_pNode[1] )
continue;
portal->m_nFaceCnt += p1->m_pNode[1]->GetFaceCount(); //for Render
CBspNode::CPortal * p2 = p1->m_pNode[1]->m_pPortals;
for( ; p2 ; p2 = p2->m_pNext[0] )
{
if( !IsEqualWinding( p1->m_pWinding, p2->m_pWinding ) )
{
RecursiveLeafFlow( &pvs, p2 , portal );
}
}
}
}
}
void CBspManager::RecursiveLeafFlow( PVSDATA* pvs, CBspNode::CPortal* target, CBspNode::CPortal* source )
{
D3DXPLANE plane;
D3DXPlaneFromPoints( &plane, &pvs->source->vPoint[0],
&pvs->source->vPoint[1],
&pvs->source->vPoint[2] );
BSPVERTEX winding[8];
for( int k = 0; k < pvs->pass->n; k++ )
{
winding[k].pos = pvs->pass->vPoint[k];
}
if( FACE_ON == Classify( &plane, winding, pvs->pass->n ) )
return;
PVSDATA pvsdata;
pvsdata.pass = pvs->pass;
pvsdata.source = pvs->source;
CWinding * w = CopyWinding( target->m_pWinding ), * tmp = NULL;
tmp = ClipToSeperators( pvsdata.source, pvsdata.pass, w, FALSE );
if( tmp )
{
source->m_nFaceCnt += target->m_pNode[0]->GetFaceCount();
if( target->m_pNode[1] )
source->m_nFaceCnt += target->m_pNode[1]->GetFaceCount();
source->m_visPortals[source->m_nVisCnt++] = target;
pvsdata.source = pvsdata.pass;
pvsdata.pass = tmp;
CBspNode::CPortal* p = target->m_pNode[1]->m_pPortals;
for( ; p ; p = p->m_pNext[0] )
{
if( !IsEqualWinding( target->m_pWinding, p->m_pWinding ) )
{
RecursiveLeafFlow( &pvsdata, p, source );
}
}
}
if( w )
delete w;
}
CWinding* CBspManager::CopyWinding( CWinding* w )
{
CWinding* neww = new CWinding();
neww->n = w->n;
for( int i = 0 ; i < w->n ; i++ )
neww->vPoint[i] = w->vPoint[i];
return neww;
}
BOOL CBspManager::IsEqualWinding( CWinding* w1, CWinding* w2 )
{
if( w1->n != w2->n )
return FALSE;
for( int i = 0 ; i < w1->n ; i++ )
{
BOOL bCheck = FALSE;
for( int k = 0 ; k < w2->n ; k++ )
{
int con = 0;
if( fabs(w1->vPoint[i].x - w2->vPoint[k].x) > EPSILON )
con++;
if( fabs(w1->vPoint[i].y - w2->vPoint[k].y) > EPSILON )
con++;
if( fabs(w1->vPoint[i].z - w2->vPoint[k].z) > EPSILON )
con++;
if( !con )
bCheck = TRUE;
}
if( !bCheck )
return FALSE;
}
return TRUE;
}
CWinding * CBspManager::ClipToSeperators (CWinding *source, CWinding *pass, CWinding *target, BOOL flipclip)
{
int i, j, k, l;
D3DXPLANE plane;
D3DXVECTOR3 v1, v2;
float d;
float length;
int counts[3];
bool fliptest;
D3DXVECTOR3 vec3_origin = D3DXVECTOR3( 0, 0, 0 );
// check all combinations
for (i=0 ; i<source->n ; i++)
{
l = (i+1)%source->n;
v1 = source->vPoint[l] - source->vPoint[i];
// fing a vertex of pass that makes a plane that puts all of the
// vertexes of pass on the front side and all of the vertexes of
// source on the back side
for (j=0 ; j<pass->n ; j++)
{
v2 = pass->vPoint[j] - source->vPoint[i];
plane.a = v1.y*v2.z - v1.z*v2.y;
plane.b = v1.z*v2.x - v1.x*v2.z;
plane.c = v1.x*v2.y - v1.y*v2.x;
// if points don't make a valid plane, skip it
length = plane.a * plane.a + plane.b * plane.b + plane.c * plane.c;
if (length < EPSILON)
continue;
length = 1/sqrt(length);
plane.a *= length;
plane.b *= length;
plane.c *= length;
D3DXVECTOR3 normal = D3DXVECTOR3( plane.a, plane.b, plane.c );
plane.d = (-1)*D3DXVec3Dot( &pass->vPoint[j], &normal);
//
// find out which side of the generated seperating plane has the
// source portal
//
fliptest = false;
for (k=0 ; k<source->n ; k++)
{
if (k == i || k == l)
continue;
d = D3DXVec3Dot( &source->vPoint[k], &normal) + plane.d;
if (d < -EPSILON)
{ // source is on the negative side, so we want all
// pass and target on the positive side
fliptest = false;
break;
}
else if (d > EPSILON)
{ // source is on the positive side, so we want all
// pass and target on the negative side
fliptest = true;
break;
}
}
if (k == source->n)
continue; // planar with source portal
//
// flip the normal if the source portal is backwards
//
if (fliptest)
{
normal = vec3_origin - normal;
plane.a = normal.x;
plane.b = normal.y;
plane.c = normal.z;
plane.d = -plane.d;
}
//
// if all of the pass portal points are now on the positive side,
// this is the seperating plane
//
counts[0] = counts[1] = counts[2] = 0;
for (k=0 ; k<pass->n ; k++)
{
if (k==j)
continue;
d = D3DXVec3Dot ( &pass->vPoint[k], &normal) + plane.d;
if (d < -EPSILON)
break;
else if (d > EPSILON)
counts[0]++;
else
counts[2]++;
}
if (k != pass->n)
continue; // points on negative side, not a seperating plane
if (!counts[0])
{
continue; // planar with seperating plane
}
//
// flip the normal if we want the back side
//
if (flipclip)
{
normal = vec3_origin - normal;
plane.a = normal.x;
plane.b = normal.y;
plane.c = normal.z;
plane.d = -plane.d;
}
//
// clip target by the seperating plane
//
CWinding* t = new CWinding();
t->n = target->n;
for( int i = 0 ; i < t->n ; i++ )
{
t->vPoint[i] = target->vPoint[i];
}
t = ClipWinding (t, &plane, false);
if (!t)
{
return NULL; // target is not visible
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -