xbdev - software development
Sunday June 16, 2024
Home | Contact | Support | 3D File Formats The bits and bytes... | 3D File Formats The bits and bytes...

3D File Formats

The bits and bytes...


Quake 3 BSP [Displaying Meshes & Vertices]

Author bkenwright@xbdev.net


Forgetting all BSP stuff, and just finding our lot of vertices and indices, we can render the lot using directx.  For our simple test bsp file, we only have a few thousand vertices at most, so its not to much of a struggle for us.  Levels can contain millions of vertices with tons of textures.


The BSP Level Demo Code - Uses a simple class in bsp.h and bsp.cpp.  We only do the most basic of work, which is loading in the mesh and vertice data in the constructor and then, when we call Render(..) we render the mesh data to the screen.  You can drag and rotate the mesh level around to see what it looks like.

You can notice a large centre room and 4 smaller rooms off to each side.

I've only pasted the main bsp code below, which is the bsp.h file. 

In my opinion the trickiest part of getting the data, and rendering it, is taking into account the various offsets.  As you have the list of faces, which has offsets to the start of the mesh data and vertices data.

Download Source Code (79kb)


Download Code


/*                                                                                */

/* File:   bsp.h                                                                  */

/* Author: bkenwright@xbdev.net                                                   */

/* URL:    www.xbdev.net                                                          */

/* Date:   22-12-2005 (xmas)                                                      */

/*                                                                                */



#ifndef BSP_H

#define BSP_H


#include <d3dx9.h>                                    // DirectX Header Files

#pragma comment(lib, "d3d9.lib")                      // DirectX Library Files

#pragma comment(lib, "d3dx9.lib")                     // IDirect3DDevice* etc


#include "common.h"                                   // SafeRelease(..)


#include "dxdbg.h"                                    // Triangle3D(..)



//----------------------- Various BSP Lump Data Types-----------------------------//






















//------------------------- Various Structure Definitions ------------------------//

struct stLump


      int         nFileofs;               // Offset to start of lump, relative to

                                          // beginning of file.

      int         nFileLen;               // Length of lump. Always a multiple of 4.



struct stHeader


      char   cMagic[4];

      int      nVersion;

      stLump Lumps[17];



//----------------------------- Lump Definitions ---------------------------------//


typedef float     Vector2[2];

typedef float     Vector3[3];

typedef float     Vector4[4];


typedef float     TexCoord[2];


typedef int       nBBox[6]; // Integer bounding box (mins, maxs)


typedef float     fBBox[6]; // Float bounding box



//Lump 0


//char *entities; // A pointer to text



//Lump 1

//Shader Texture Info

struct stShaderRef


      char  Name[64];         // Texture name

      int         nSurfaceFlags;    // Type of surface (See Surface Flags below)

      int         nContentFlags;    // Leaf content (See Content Flags below)




//Lump 2


struct stPlane


      Vector3 Normal;               // Normal vector for plane

      float fDist;                  // Distance from plane to origin




//Lump 3


struct stNode


      int         nPlane;                 // Space partitioning plane

      int         nChildren[2];     // Back and front child nodes

      nBBox BBoxI;                  // Bounding box of node



//Lump 4


struct stLeaf


      int         nCluster;         // Visibility cluster number

      int         nArea;                  // Volume of the leaf

      nBBox BBoxI;                  // Bounding box of leaf


      int         nFirstFace,

                  NumFaces;         // Lookup for the face list (indexes

                                          // are for faces)


      int         nFirstBrush,

                  NumBrushes;       // Lookup for the brush list (indexes

                                          // are for brushes)




//Lump 5

//Leaf Faces

//int *pFaces;                      // a pointer to a series of indexes to

                                          // a face list


//Lump 6

//Leaf Brushes

//int *pBrushes;              // a pointer to a series of indexes to

                                          // a brush list


//Lump 7


struct stModel


      fBBox BBoxF;                  // Bounding box of model


      int         nFirstFace,       // First face for model

                  NumFaces;         // Number of faces for model


      int         nFirstBrush,      // First brush for model

                  NumBrushes;       // Number of brushes for model



//Lump 8


struct stBrush


      int         nFirstSide,       // First brushside for brush

                  NumSides;         // Number of brushsides for brush


      int         nIndex;                 // Texture index



//Lump 9

//Brush Sides

struct stBrushSide


      int         PlaneNum;         // Lookup for plane

      int         nIndex;                 // Texture index



//Lump 10


struct stVertex


      Vector3  vPoint;        // Vertex Position

      TexCoord Tex;                 // Texture coordinates

      TexCoord LightTexCoord; // Light Map texture coordinates

      Vector3  vNormal;       // Normal vector (used for lighting ?)


      unsigned int RGBA;            // Vertex color. RGBA




//Lump 11


//int nOffset;                      // Vertex index offset, relative to first

                                          // vertex of corresponding face. 




//Lump 12


struct stEffect


      char cName[64];               // Effect shader. 

      int   nBrush;                // Brush that generated this effect. 

      int  Unknown;                 // Always 5, except in q3dm8, which has

                                          // one effect with -1. 





//Lump 13


#pragma pack(1)

struct stFace // size 24*4


      int nShader;                  // Refers to a shader

      int nEffect;                  // Index into lump 12 (Effects), or -1

      int nFaceType;                // Face type. 1=polygon, 2=patch, 3=mesh, 4=billboard

      int FirstVert,

            NumVerts;               // Reference to vertices


      int nFirstMeshVerts,    // Index of first meshvert

                                          // Every three meshverts describe a triangle

            NumMeshVerts;           // Number of meshverts


      int LMIndex;                  // Lightmap index.

      int LMStart[2];               // X,Y Corner of this face's lightmap image in lightmap.

      int LMSize[2];                // Size of lightmap


      float LMOrigin[3];            // World space origin of lightmap.

      float LMVects[2][3];    // World space lightmap s and t unit vectors.


      Vector3 vNormal;        // Face normal


      int nSize[2];                 // Patch dimensions. 


#pragma pack()



//Lump 14


//unsigned char pMap[128][128][3]; // Lightmap color data. RGB. 


//Lump 15

//Light Grid



//Lump 16

//Visibility Lists

struct stVisibility


      int NumVectors;               // Number of vectors.

      int nSizeVector;        // Size of each vector, in bytes

      unsigned char *pData;   // [NumVectors * nSizeVector]; 

                                          // Visibility data. One bit per cluster per vector



//Lump 17

//Number of Lumps




void ErrLog(char *str);       // bsp.cpp



class CBSP


      stHeader    m_Header;


      stVertex    *m_pVerts;

      int               m_nNumVerts;


      stFace            *m_pFaces;

      int               m_nNumFaces;


      int               *m_pMeshVerts;

      int               m_nNumMeshVerts;




      CBSP(char * szFile )


            // Always initialize variables

            m_nNumVerts = 0;

            m_nNumFaces = 0;

            m_nNumMeshVerts = 0;


            // Always initialise pointers to NULL

            m_pFaces = NULL;

            m_pVerts = NULL;

            m_pMeshVerts = NULL;




      ~CBSP(){ Release(); }


      int GetNumFaces()


            return m_nNumFaces;



      bool Release()


            delete[] m_pVerts;



            delete[] m_pFaces;



            delete[] m_pMeshVerts;




            m_nNumVerts = 0;

            m_nNumFaces = 0;

            m_nNumMeshVerts = 0;


            return true;                              // No Error



      bool Create(const char * szBSPFile)


            if( szBSPFile==NULL )


                  ErrLog("<->Error NULL File Pointer");

                  return false;





            ErrLog("<->Opening File\n\n");


            // Open BSP File

            FILE * fp = fopen(szBSPFile, "rb");



            // Temporary Buffer

            fread(&m_Header,                    // Buffer

                  1,                                        // Size

                  sizeof(stHeader),             // Number of times

                  fp);                                // File Pointer



            // Get the pointer to our array of lumps

            stLump * pLumps = m_Header.Lumps;




            stLump * pLump = &pLumps[enVertices];

            fseek(      fp,


                        SEEK_SET );


            m_pVerts = (stVertex*)new char[pLump->nFileLen];



            fread(      (void*)m_pVerts,        // Buffer

                        1,                                  // Size

                        pLump->nFileLen,        // Number of times

                        fp );                         // File Pointer



            m_nNumVerts = pLump->nFileLen / sizeof(stVertex);


            // Record Information

            char buf[100];                            // Temp text buffer

            sprintf(buf, "\n<?>Num Vertices: %d\n", m_nNumVerts);



      //------------------------------------ Faces -------------------------------------//

            pLump = &pLumps[enFaces];

            fseek(      fp,


                        SEEK_SET );


            m_pFaces = (stFace*)new char[pLump->nFileLen];



            fread(      (void*)m_pFaces,        // Buffer

                        pLump->nFileLen,        // Size

                        1,                                  // Number of times

                        fp );                         // File Pointer



            m_nNumFaces = pLump->nFileLen / sizeof(stFace);


            // Record Information

            sprintf(buf, "\n<?>Num Faces: %d\n", m_nNumFaces);


      //-------------------------------- Mesh Vert Tris -------------------------------------//


            pLump = &pLumps[enMeshIndices];

            fseek(      fp,


                        SEEK_SET );


            m_pMeshVerts = (int*)new char[pLump->nFileLen];



            fread(      (void*)m_pMeshVerts,    // Buffer

                        pLump->nFileLen,        // Size

                        1,                                  // Number of times

                        fp );                         // File Pointer



            m_nNumMeshVerts = pLump->nFileLen / sizeof(int);


            // Record Information

            sprintf(buf, "\n<?>Num Mesh Verts: %d\n", m_nNumMeshVerts);




            ErrLog("\n<->Closing File\n");

            // Close BSP File



            return true;                              // No Error



      void Render(IDirect3DDevice9 * pDevice)


            for(int i=0; i<m_nNumFaces; i++)


                  // If its not a tri mesh

                  if( m_pFaces[i].nFaceType != 1 ) continue;


                  int nFirstF = m_pFaces[i].nFirstMeshVerts;

                  int nNumF   = m_pFaces[i].NumMeshVerts;


                  int nFirstV = m_pFaces[i].FirstVert;

                  int nNumV   = m_pFaces[i].NumVerts;


                  for(int j=0; j<nNumF; j+=3)


                        int i0 = m_pMeshVerts[nFirstF+0];

                        int i1 = m_pMeshVerts[nFirstF+1];

                        int i2 = m_pMeshVerts[nFirstF+2];


                        float *pA = m_pVerts[nFirstV + i0].vPoint;

                        float *pB = m_pVerts[nFirstV + i1].vPoint;

                        float *pC = m_pVerts[nFirstV + i2].vPoint;



                              pA[0], pA[1], pA[2],

                              pB[0], pB[1], pB[2],

                              pC[0], pC[1], pC[2],









};//End CBSP class



#endif // BSP_H

Log File:

<->Opening File
<?>Num Vertices: 1659
<?>Num Faces: 145
<?>Num Mesh Verts: 3384
<->Closing File



Advert (Support Website)

Copyright (c) 2002-2024 xbdev.net - All rights reserved.
Designated articles, tutorials and software are the property of their respective owners.