www.xbdev.net xbdev - software development
Friday October 18, 2019
home | about | contact | Donations
>>
     
 

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-----------------------------//

enum BSP_TYPES

{

      enEntities=0,

      enTextures,

      enPlanes,

      enNodes,

      enLeaves,

      enLeafFaces,

      enLeafBrushes,

      enModels,

      enBrushes,

      enBrushSides,

      enVertices,

      enMeshIndices,

      enEffect,

      enFaces,

      enLightmaps,

      enLightVols,

      enVisData

};

 

//------------------------- 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

//Entities

//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

//Planes

struct stPlane

{

      Vector3 Normal;               // Normal vector for plane

      float fDist;                  // Distance from plane to origin

};

 

 

//Lump 3

//Nodes

struct stNode

{

      int         nPlane;                 // Space partitioning plane

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

      nBBox BBoxI;                  // Bounding box of node

};

 

//Lump 4

//Leaves

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

//Models

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

//Brushes

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

//Vertices

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

//MeshVert

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

                                          // vertex of corresponding face. 

 

 

 

//Lump 12

//Effect

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

//Faces

#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

//Lightmaps

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

 

//Lump 15

//Light Grid

//Unknown

 

//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

//Unknown

 

 

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;

 

public:

 

      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;

 

            Create(szFile);

      }

      ~CBSP(){ Release(); }

 

      int GetNumFaces()

      {

            return m_nNumFaces;

      }

 

      bool Release()

      {

            delete[] m_pVerts;

            m_pVerts=NULL;

 

            delete[] m_pFaces;

            m_pFaces=NULL;

 

            delete[] m_pMeshVerts;

            m_pMeshVerts=NULL;

 

 

            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;

            }

 

            Release();

 

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

 

            // Open BSP File

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

            assert(fp);

 

            // 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;

 

 

      //------------------------------------Vertices------------------------------------//

            stLump * pLump = &pLumps[enVertices];

            fseek(      fp,

                        pLump->nFileofs,

                        SEEK_SET );

 

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

            assert(m_pVerts);

 

            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);

            ErrLog(buf);

 

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

            pLump = &pLumps[enFaces];

            fseek(      fp,

                        pLump->nFileofs,

                        SEEK_SET );

 

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

            assert(m_pFaces);

 

            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);

            ErrLog(buf);

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

 

            pLump = &pLumps[enMeshIndices];

            fseek(      fp,

                        pLump->nFileofs,

                        SEEK_SET );

 

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

            assert(m_pMeshVerts);

 

            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(buf);

 

 

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

            // Close BSP File

            fclose(fp);

 

            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;

 

                        Triangle3D(pDevice,

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

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

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

                              0xffffffff);

                       

                        nFirstF+=3;

                  }

            }

 

      }

 

};//End CBSP class

 

 

#endif // BSP_H

Log File:

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

 

 

 
 Visitor: 9534626  { 209.237.238.175 } Copyright (c) 2002-2017 xbdev.net - All rights reserved.
Designated tutorial and software are the property of their respective owners.