⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bspmanager.cpp

📁 BSP地形系统和光照贴图的技术详解
💻 CPP
📖 第 1 页 / 共 5 页
字号:
	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 + -