BSP rendering: How to go from strips/fans to triangle lists?

Started by
1 comment, last by Hodgman 13 years, 5 months ago
I've been trying to fix my BSP renderer for a long time now, and so far, I can't get certain maps to load properly. I know I've already created 2 threads about this, but so far, my final problem remains, how can I re-order my geometry into triangle lists? I've searched the net for solutions, but found nothing time after time after time again. So far, I just heard that using triangle strips instead of fans and strips fixes the problems I have.

Here's the code that I am using right now. The first is my definition of the BSP face:

// BSP face structurestruct tBSPFace{	int textureID;			// The index into the texture array	int effect;				// The index for the effects (-1 == none)	int type;				// 1 = Polygon, 2 = Patch, 3 = Mesh, 4 = Billboard	int startVertexIndex;	// The starting index into this face's first vertex	int numOfVerts;			// The number of vertices for this face	int meshVertexIndex;	// The index into the first mesh vertex	int numMeshVerts;		// The number of mesh vertices	int lightmapID;			// The texture index for the lightmap	int lMapCorner[2];		// The face's lightmap corner in the image	int lMapSize[2];		// The size of the lightmap section	XGVec3 lMapPos;			// The 3D origin of lightmap	XGVec3 lMapVecs[2];		// The 3D space for s and t unit vector	XGVec3 vNormal;			// The face normal	int size[2];			// The besier patch dimensions};


This way, you can get a better understanding of what each field is compared to your own loaders. Next is my code for the loader, but I'll only show up to the part where the vertex buffer is created and filled so you understand what I am doing:

//--------------------------------------------------------------------------------------// File: CQuake3BSP::LoadBSP// Desc: //--------------------------------------------------------------------------------------bool CQuake3BSP::LoadBSP( char* szFileName ){	HRESULT hr;	FILE* fp = NULL;	int i = 0;	// Open the .bsp file	if( ( fp = fopen( szFileName, "rb" ) ) == NULL )	{		MessageBoxA( NULL, "Error loading the .bsp file!", "BSP Demo", MB_OK );		return false;	}	// Initialize the header and lump structures	tBSPHeader header = {0};	tBSPLump lumps[kMaxLumps] = {0};	// Read in the header and lump data	fread( &header, 1, sizeof( tBSPHeader ), fp );	fread( &lumps, kMaxLumps, sizeof( tBSPLump ), fp );	// Allocate vertex memory	m_NumOfVerts = lumps[kVertices].length / sizeof( tBSPVertex );	m_pVerts	 = new tBSPVertex[m_NumOfVerts];	// Allocate the face memory	m_NumOfFaces = lumps[kFaces].length / sizeof( tBSPFace );	m_pFaces	 = new tBSPFace[m_NumOfFaces];	// Allocate memory for texture information	m_NumOfTextures = lumps[kTextures].length / sizeof( tBSPTexture );	tBSPTexture* pTextures = new tBSPTexture[m_NumOfTextures];	// Seek to the position in the file that stores vertex information	fseek( fp, lumps[kVertices].offset, SEEK_SET );	// Create a vertex buffer to store all of our vertex data	V( DXUTGetD3D9Device()->CreateVertexBuffer( m_NumOfVerts * sizeof( tBSPRenderVertex ), 0, 												tBSPRenderVertex::FVF,												D3DPOOL_MANAGED, &m_pVertexBuffer, NULL ) );	// Lock the vertex buffer and start giving it vertex data	tBSPRenderVertex* pVerts = NULL;	V( m_pVertexBuffer->Lock( 0, 0, (void**) &pVerts, 0 ) );	// Swap the z coordinate with the y coordinate so that the BSP is rendered	// correctly.	for( i = 0; i < m_NumOfVerts; i++ )	{		// Read current vertex		fread( &m_pVerts, 1, sizeof( tBSPVertex ), fp );		// Swap the y and z values and negate the z so y is up		float temp = m_pVerts.vecPosition.y;		m_pVerts.vecPosition.y = m_pVerts.vecPosition.z;		m_pVerts.vecPosition.z = -temp;		// Negate the the u tex coord for Direct3D		m_pVerts.vecTextureCoord.x *= -1;		// Write the most important vertex data to the vertex buffer		pVerts.vecPosition = m_pVerts.vecPosition;		pVerts.vecTextureCoord = m_pVerts.vecTextureCoord;	}	// Unlock the vertex buffer	V( m_pVertexBuffer->Unlock() );....


Now, for the rendering part. This is my code for rendering faces. I haven't added support for patches, curves or surfaces yet because I haven't gotten that far. I need the general stuff to work first so I can get this game up and running ASAP.

//--------------------------------------------------------------------------------------// Name: CQuake3BSP::RenderFace// Desc: //--------------------------------------------------------------------------------------void CQuake3BSP::RenderFace( int FaceIndex ){	IDirect3DDevice9* pD3DDevice = DXUTGetD3D9Device();	HRESULT hr;	// Grab the face from the index passed in	tBSPFace* pFace = &m_pFaces[FaceIndex];	// Set the texture	V( pD3DDevice->SetTexture( 0, m_ppTextures[pFace->textureID] ) );	// Render the face	V( pD3DDevice->SetStreamSource( 0, m_pVertexBuffer, 0, sizeof( tBSPRenderVertex ) ) );	V( pD3DDevice->SetFVF( tBSPRenderVertex::FVF ) );	V( pD3DDevice->DrawPrimitive( D3DPT_TRIANGLEFAN, pFace->startVertexIndex, pFace->numOfVerts - 2 ) );	m_NumOfPrimitives += pFace->numOfVerts - 2;	/*V( pD3DDevice->DrawPrimitiveUP( D3DPT_TRIANGLEFAN, pFace->numOfVerts, 									(m_pVerts + (pFace->startVertexIndex*sizeof(tBSPVertex))),									sizeof(tBSPVertex) ) );*/}


How would I go about re-ordering all of this into triangle lists? I've tried various methods, but I can't get anything to work better than what I already have. This sucks. Any ideas?? Thanks.
Advertisement
Bump.
Quote:How to go from strips/fans to triangle lists?
Count how many tris are in the fan/strip.
Allocate an index buffer with that number times 3 space.
For each triangle in the fan/strip, add the 3 indices to the index buffer.
Use the original vertex buffer along with the new index buffer to render an indexed tri list.

Not tested, but something like this:
bool isStrip = ...;//fan or stripint numVerts = ...;assert(numVerts>=3);int numTris = numVerts-2;uint16 indices = new uint16[numTris*3];for( int tri=2; tri!=numVerts; ++tri ){  indices[i++] = isStrip ? tri-2 : 0;  indices[i++] = tri-1;  indices[i++] = tri;}

This topic is closed to new replies.

Advertisement