   Quake 3 BSP rendering
  I've recently wrote a Quake 3 .bsp loader for my game a while ago, and it appears to work fine for most cases so far.  There are some maps that I can't get to load correctly (usually high-end maps) like the Simpson's map for Quake 3.I based my .bsp loader off of the one from Gametutorials.com and ported the OpenGL code to Direct3D.  So what I basically did was throw all my vertices inside of a vertex buffer and rendered it from there.  All the polygons are rendered as triangle fans as in the OpenGL code.  It works for some maps, but not others.  If you want to see it, here's my BSP rendering code.#include "DXUT.h"#include "d3d9defs.h"#include "Q3Bsp.h"DWORD tBSPRenderVertex::FVF = ( D3DFVF_XYZ | D3DFVF_TEX1 );//--------------------------------------------------------------------------------------// Name: CQuake3BSP::CQuake3BSP()// Desc: Default constructor//--------------------------------------------------------------------------------------CQuake3BSP::CQuake3BSP(){m_NumOfVerts = 0;m_NumOfFaces = 0;m_NumOfTextures = 0;m_pVerts = NULL;m_pFaces = NULL;m_ppTextures = NULL;}CQuake3BSP::~CQuake3BSP(){this->Destroy();}//--------------------------------------------------------------------------------------// Name: CQuake3BSP::FindTextureExtension// Desc: Finds the texture's extension prior to loading it.//--------------------------------------------------------------------------------------void CQuake3BSP::FindTextureExtension( char* szFileName ){char szJPGPath[MAX_PATH] = {0};char szTGAPath[MAX_PATH] = {0};char szDDSPath[MAX_PATH] = {0};FILE* fp = NULL;// Get the directory we are inGetCurrentDirectoryA( MAX_PATH, szJPGPath );// Add on a '\' and the file name to the end of the current path.// We create 2 seperate strings to test each image extension.strcat( szJPGPath, "\\" );strcat( szJPGPath, szFileName );strcat( szTGAPath, szJPGPath );strcat( szDDSPath, szJPGPath );// Add the file extensionsstrcat( szJPGPath, ".jpg" );strcat( szTGAPath, ".tga" );strcat( szTGAPath, ".dds" );// Is this a JPEG?if( ( fp = fopen( szJPGPath, "rb" ) ) != NULL ){// If so, add ".jpg" onto the file namestrcat( szFileName, ".jpg" );fclose(fp);return;}// Is this a TARGA?if( ( fp = fopen( szTGAPath, "rb" ) ) != NULL ){// If so, add ".tga" onto the file namestrcat( szFileName, ".tga" );fclose(fp);return;}// Is this a DDS?if( ( fp = fopen( szDDSPath, "rb" ) ) != NULL ){// If so, add ".tga" onto the file namestrcat( szFileName, ".dds" );fclose(fp);return;}}//--------------------------------------------------------------------------------------// File: CQuake3BSP::LoadBSP// Desc: //--------------------------------------------------------------------------------------bool CQuake3BSP::LoadBSP( char* szFileName ){HRESULT hr;FILE* fp = NULL;int i = 0;// Open the .bsp fileif( ( fp = fopen( szFileName, "rb" ) ) == NULL ){MessageBoxA( NULL, "Error loading the .bsp file!", "BSP Demo", MB_OK );return false;}// Initialize the header and lump structurestBSPHeader header = {0};tBSPLump lumps[kMaxLumps] = {0};// Read in the header and lump datafread( &header, 1, sizeof( tBSPHeader ), fp );fread( &lumps, kMaxLumps, sizeof( tBSPLump ), fp );// Allocate vertex memorym_NumOfVerts = lumps[kVertices].length / sizeof( tBSPVertex );m_pVerts = new tBSPVertex[m_NumOfVerts];// Allocate the face memorym_NumOfFaces = lumps[kFaces].length / sizeof( tBSPFace );m_pFaces = new tBSPFace[m_NumOfFaces];// Allocate memory for texture informationm_NumOfTextures = lumps[kTextures].length / sizeof( tBSPTexture );tBSPTexture* pTextures = new tBSPTexture[m_NumOfTextures];// Seek to the position in the file that stores vertex informationfseek( fp, lumps[kVertices].offset, SEEK_SET );// Create a vertex buffer to store all of our vertex dataV( DXUTGetD3D9Device()->CreateVertexBuffer( m_NumOfVerts * sizeof( tBSPRenderVertex ), 0, tBSPRenderVertex::FVF,D3DPOOL_MANAGED, &m_pVertexBuffer, NULL ) );// Lock the vertex buffer and start giving it vertex datatBSPRenderVertex* 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 vertexfread( &m_pVerts, 1, sizeof( tBSPVertex ), fp );// Swap the y and z values and negate the z so y is upfloat temp = m_pVerts.vecPosition.y;m_pVerts.vecPosition.y = m_pVerts.vecPosition.z;m_pVerts.vecPosition.z = -temp;// Negate the the v tex coord for OpenGLm_pVerts.vecTextureCoord.x *= -1;// Write the most important vertex data to the vertex bufferpVerts.vecPosition = m_pVerts.vecPosition;pVerts.vecTextureCoord = m_pVerts.vecTextureCoord;}// Unlock the vertex bufferV( m_pVertexBuffer->Unlock() );// Seek to the position in the file that stores face informationfseek( fp, lumps[kFaces].offset, SEEK_SET );// Read in all face informationfread( m_pFaces, m_NumOfFaces, sizeof( tBSPFace ), fp );// Seek to the position in the file that stores texture information.fseek( fp, lumps[kTextures].offset, SEEK_SET );// Read in all the texture informationfread( pTextures, m_NumOfTextures, sizeof( tBSPTexture ), fp );// Allocate space for Direct3D texturesm_ppTextures = new LPDIRECT3DTEXTURE9[m_NumOfTextures];// Load the textures.int FailedTextureLoads = 0;for( i = 0; i < m_NumOfTextures; i++ ){// Find the textensin if any and append it FindTextureExtension( pTextures.strName );// Create the textureif( FAILED( D3DXCreateTextureFromFileA( DXUTGetD3D9Device(), pTextures.strName, &m_ppTextures ) ) ){FailedTextureLoads++;m_ppTextures = NULL;}}if( FailedTextureLoads ){char string[128];sprintf( string, "%d out of %d failed texture loads!", FailedTextureLoads, m_NumOfTextures );MessageBoxA( NULL, string, "BSP", MB_ICONERROR );}// Free the texture information pointerdelete [] pTextures;// Close the file pointerfclose( fp );// Allocate enough bits to store all the faces for our bitsetm_FacesDrawn.Resize( m_NumOfFaces );return true;}//--------------------------------------------------------------------------------------// Name: CQuake3BSP::RenderFace// Desc: //--------------------------------------------------------------------------------------void CQuake3BSP::RenderFace( int FaceIndex ){IDirect3DDevice9* pD3DDevice = DXUTGetD3D9Device();HRESULT hr;// Grab the face from the index passed intBSPFace* pFace = &m_pFaces[FaceIndex];// Set the textureV( pD3DDevice->SetTexture( 0, m_ppTextures[pFace->textureID] ) );// Render the faceV( pD3DDevice->SetStreamSource( 0, m_pVertexBuffer, 0, sizeof( tBSPRenderVertex ) ) );V( pD3DDevice->SetFVF( tBSPRenderVertex::FVF ) );V( pD3DDevice->DrawPrimitive( D3DPT_TRIANGLEFAN, pFace->startVertexIndex, pFace->numOfVerts - 2 ) );/*V( pD3DDevice->DrawPrimitiveUP( D3DPT_TRIANGLEFAN, pFace->numOfVerts, (m_pVerts + (pFace->startVertexIndex*sizeof(tBSPVertex))),sizeof(tBSPVertex) ) );*/}//--------------------------------------------------------------------------------------// Name: CQuake3BSP::RenderLevel// Desc: Renders the entire BSP level.//--------------------------------------------------------------------------------------void CQuake3BSP::RenderLevel( const XGVec3 &vecPos ){int i = m_NumOfFaces;// Render each face of this BSPm_FacesDrawn.ClearAll();// while( i-- ){// Only handle polygons and meshes for nowif( m_pFaces.type != FACE_POLYGON && m_pFaces.type != FACE_MESH ) continue;// If this face hasn't been drawn already, set it as// so and render it.if( !m_FacesDrawn.On(i) ){m_FacesDrawn.Set(i);RenderFace(i);}}}//--------------------------------------------------------------------------------------// Name: CQuake3BSP::Destroy()// Desc: //--------------------------------------------------------------------------------------void CQuake3BSP::Destroy(){SAFE_DELETE_ARRAY( m_pFaces );SAFE_DELETE_ARRAY( m_pVerts );if( m_ppTextures )for( int i = 0; i < m_NumOfTextures; i++ )SAFE_RELEASE( m_ppTextures );SAFE_DELETE_ARRAY( m_ppTextures );SAFE_RELEASE( m_pVertexBuffer );}So far, this is the best I could come up with.  I haven't implemented curved surfaces or billboards yet (but this map does use all 4 face types).  My guess is that I should instead be using a triangle list with indexed geometry (DrawIndexedVertices) for accuracy and speed since I heard indexed vertices are faster, but I'm not show how to do that.  This sucks.  Any helpful links/ideas?  Thanks.   
  Take a look here if you haven't already.Did you try to use this map with the GameTutorials loader?   ;  What do you mean that all the polygons are rendered as triangle fans? Are you using the draw indices to get the correct ordering to draw the meshes or are you bypassing the indices and making assumptions that they are always ordered the same way? If the latter, that's likely the issue.   