Problem rendering Quake 3 BSP files

Started by
14 comments, last by industrialgrok 11 years ago

I attached the source file I used to render .bsp files. It's a heavily modified version of the one from gametutorials.com. I modified it to use Direct3D9 and use triangle lists instead of fans. Maybe I should have included the entire project source. If you need it, I'll upload that too.

So far, my BSP loader is the only one I've ever seen render the Simpsons Q3 map correctly (besides Q3 itself), which is the most complex Q3 map I've seen to date. Hopefully this helps.

Shogun.

PS: Be warned, it's messy!

Advertisement

Ok thanks borntocode I was unaware of this. Thanks blueshotgun, Have you actually implemented the PVS system? (like paulsprojects)

Ok thanks borntocode I was unaware of this. Thanks blueshotgun, Have you actually implemented the PVS system? (like paulsprojects)

PVS system? I'm sorry, what does that mean? The only thing I used from paulsprojects is his patch rendering code. My D3D implementation isn't very efficient since it uses D3DDevice::DrawIndexedPrimitiveUP every frame N times per tessellation, but it works.

Btw, my nickname is blueshogun, not blueshotgun. No worries, happens all the time. happy.png

Shogun.

Ok thanks borntocode I was unaware of this. Thanks blueshotgun, Have you actually implemented the PVS system? (like paulsprojects)

PVS system? I'm sorry, what does that mean? The only thing I used from paulsprojects is his patch rendering code. My D3D implementation isn't very efficient since it uses D3DDevice::DrawIndexedPrimitiveUP every frame N times per tessellation, but it works.

Btw, my nickname is blueshogun, not blueshotgun. No worries, happens all the time. happy.png

Shogun.

PVS=Potensial visibility set. It is a system used in an BSP tree that does Occlusion.

Ok thanks borntocode I was unaware of this. Thanks blueshotgun, Have you actually implemented the PVS system? (like paulsprojects)

PVS system? I'm sorry, what does that mean? The only thing I used from paulsprojects is his patch rendering code. My D3D implementation isn't very efficient since it uses D3DDevice::DrawIndexedPrimitiveUP every frame N times per tessellation, but it works.

Btw, my nickname is blueshogun, not blueshotgun. No worries, happens all the time. happy.png

Shogun.

PVS=Potensial visibility set. It is a system used in an BSP tree that does Occlusion.

Oh, now I remember. Yeah, my code does support PVS. IIRC, it supports everything except billboards and Q3 shaders. Everything else works, but my beizer patch code isn't perfect because I screwed up the fragment colour thing.

Shogun

Ok guys (blueshogun96 BornToCode mhagain) I read the xbox dev tutorial. Then I worked on it a week got frustrated and then started working on other parts of my engine instead (Finished normal mapping biggrin.png )

anyway I started working on it a week ago and just got it working but now faces wont render correctly.

http://postimg.org/image/o2lf8vlp9/ Here are the vertices for a map

and here's what happens when I render faces on a map

http://postimg.org/image/6hmoht7ep/

here's the code to it


#include <stdio.h>                        
#include <cstdio>
#include <string>
#include <algorithm>
#include <fstream>
#include <cstdio>
#include <iostream>
#include <stdlib.h>
#include <sstream>
#include <GL/GL.h>                                    
#include <SDL/SDL.h>

#include <assert.h>                                  

#include "sys_mem.h"
using namespace std; 

 int SCREEN_WIDTH = 640;
 int SCREEN_HEIGHT = 480;
 int SCREEN_BPP = 24;
 bool running = true;
 bool lightmaps;
 SDL_Event event;

#define MAX_BRUSHES   10000
#define MAX_FACES     10000
#define MAX_VERTS     10000000
#define MAX_TEXTURES  1000

struct bspface
{
 int   textureid;        // The index into the texture array 
 int   effect;           // The index for the effects (or -1 = n/a) 
 int   type;             // 1=polygon, 2=patch, 3=mesh, 4=billboard 
 int   vertexindex;      // The index into this face's first vertex 
 int   numofverts;       // The number of vertices for this face 
 int   meshvertindex;    // The index into the first meshvertex 
 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 
 float lmappos[3];     // The 3D origin of lightmap. 
 float lmapbitsets[2][3]; // The 3D space for s and t unit vectors. 
 float vnormal[3];     // The face normal. 
 int   size[2];          // The bezier patch dimensions. 
};

struct bspvertex
{
 float position[3];      //x y z 
 float texturecoord[2];  //u, v texture coordinate
 float lightmapcoord[2]; //u, v lightmap coordinate
 float normal[3];        //x, y, z normalized vector
 char  color[4];         //RGBA color for the vertex 
};

struct bsptexture
{
 char name[64];      // The name of the texture w/o the extension 
 int flags;          // The surface flags (unknown) 
 int contents;       // The content flags (unknown)
};

struct bspbrush 
{
 int brushSide;           // The starting brush side for the brush 
 int numofbrushsides;     // Number of brush sides for the brush
 int textureid;           // The texture index for the brush
};

struct bsplump
{
 int offset;
 int length;
};

class bsp
{
 public:
  ifstream    bspfile;
  bsplump     lumps[16];
  char        entities[10000]; 
  bspvertex   vertices[MAX_VERTS];
  bspface     faces[MAX_FACES];
  bsptexture  textures[MAX_TEXTURES];
  bspbrush    brushs[MAX_BRUSHES];
  void load(string);
  void render();  
};

void bsp::load(string name)
{
 cout << "Loading BSP \"" << name << "\"" << endl; 
 bsp::bspfile.open (name.c_str(), istream::binary);
 if(bsp::bspfile == NULL)
   cout << "ERROR: No file named \""<< name <<"\" found" << endl;
 else
     {
      char magic[64];           //Number used in BSP header	
      bsp::bspfile.read(magic, 4);   //Read the magic number in the header of the BSP file it should be "IBSP"
      if((magic[0] != 'I')||(magic[1] != 'B')||(magic[2] != 'S')||(magic[3] != 'P'))
        {
         cout << "ERROR: Not a valid Quake 3 BSP file" << endl;
        }
      else
          {
           int version;
           version = readInt(bsp::bspfile);
           if(version != 46)//46 = 0x2e in hexidecimal
             cout << "ERROR: Unknown version of Quake 3 BSP" << endl;
           else
               {
                for (int i = 0; i <= 16; i++)
                   {                 
                    bsp::lumps.offset = readInt(bsp::bspfile);
                    bsp::lumps.length = readInt(bsp::bspfile);
                    cout << "Lump " << i << " offset is " << bsp::lumps.offset << endl
                         << "Lump " << i << " length is " << bsp::lumps.length << endl << endl;                   
                   }
				   
				//Load entities (LUMP 0)
			    bsp::bspfile.seekg (bsp::lumps[0].offset, ios::beg); 
		        bsp::bspfile.read(bsp::entities, bsp::lumps[0].length);  
                
                //Load textures	(LUMP 1)			
				bsp::bspfile.seekg (bsp::lumps[1].offset, ios::beg); //Load face data from vertex lump (13)
                for (int j = 0; j <= bsp::lumps[1].length/sizeof(bsptexture); j++)//Read until end of lump
                   {			   
				    char buffer[72];           
                    bsp::bspfile.read(buffer, 72);  
					
                    for (int k = 0; k <= 71; k++)//Read until end of lump
                       {
					    ((char*)&bsp::textures[j])[k] = buffer[k];
					   }
                   }
				   
                //Load vertices (LUMP 10)
                bsp::bspfile.seekg (bsp::lumps[10].offset, ios::beg); //Load vertex data from vertex lump (10)
                for (int j = 0; j <= bsp::lumps[10].length/sizeof(bspvertex); j++)//Read until end of lump
                   { 
				    char buffer[44];           //create buffer for verts	
                    bsp::bspfile.read(buffer, 44);   //Read 
                    for (int k = 0; k <= 43; k++)//Read until end of lump
                       {
					    ((char*)&bsp::vertices[j])[k] = buffer[k];
					   }
                   }
				
                //Load faces (LUMP 13)
                bsp::bspfile.seekg (bsp::lumps[13].offset, ios::beg); //Load vertex data from vertex lump (10)
                for (int j = 0; j <= bsp::lumps[13].length/sizeof(bspface); j++)//Read until end of lump
                   {
				    char buffer[104];           //create buffer for verts	
                    bsp::bspfile.read(buffer, 104);   //Read 
                    for (int k = 0; k <= 103; k++)//Read until end of lump
                       {
					    ((char*)&bsp::faces[j])[k] = buffer[k];
					   }
                   }


                cout << "Lump 13 loaded" << endl;
               }
          }

     }
}
//glVertex3f(bspbuffer.vertices[j].position[0], bspbuffer.vertices[j].position[1], bspbuffer.vertices[j].position[2]);
void bsp::render()
{  
 for (int j = 0; j <= bsp::lumps[13].length/sizeof(bspface); j++)//Read until end of lump
    {
	 if ((bsp::faces[j].type == 1)||(bsp::faces[j].type == 3))       // 1=polygon, 2=patch, 3=mesh, 4=billboard	 
       {		
		 glFrontFace(GL_CW);
         glBegin(GL_TRIANGLE_STRIP); 
	          //cout << bsp::faces[j].vertexindex << " " << bsp::faces[j].numofverts <<endl;
              for (int k = 0; k <=  bsp::faces[j].numofverts - 1; k++)//Read until end of lump
                 {
                  //cout<< " " <<bsp::faces[j].vertexindex+k << " vertex" << endl;
                  glVertex3f(bsp::vertices[bsp::faces[j].vertexindex+k].position[0], bsp::vertices[bsp::faces[j].vertexindex+k].position[1], bsp::vertices[bsp::faces[j].vertexindex+k].position[2]);
		         }
		      glEnd();
			 
		}
    }
}

bsp bspbuffer;

 bool initGL() 
 { 
    //Initialize Projection Matrix 
	glMatrixMode( GL_PROJECTION ); 
	glLoadIdentity(); 
	//Initialize Modelview Matrix 
	glMatrixMode( GL_MODELVIEW ); 
	glLoadIdentity(); 
	//Initialize clear color 
	glClearColor( 0.f, 0.f, 0.f, 1.f ); 
	
    //glPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
	return true; 
 }
 
 float angle;
 void render() 
  { 
   angle = angle + 1;
   glPushMatrix();
   //Clear color buffer 
   glClear( GL_COLOR_BUFFER_BIT ); 
   //Render quad 
   glPointSize(5.0);
   glRotatef(angle,1,1,1);
   glScalef(.002,.002,.002);
   bspbuffer.render();
   //Update screen
   glPopMatrix();
   SDL_GL_SwapBuffers(); 
   
   //While there are events to handle 
   while( SDL_PollEvent( &event ) ) 
        { 
		 if(event.type == SDL_QUIT) 
		   { 
		    running = false;
		    exit(0); 
           }
        }	   
   SDL_Delay( 1000 / 30 );
 }
 
 bool init() 
 { 

  //Initialize SDL 
  if( SDL_Init( SDL_INIT_EVERYTHING ) < 0 ) 
    {
     return false; 
	 } 
  //Create Window 
  if( SDL_SetVideoMode( SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP, SDL_OPENGL ) == NULL ) 
    {
     return false; 
	} 
  //Initialize OpenGL 
  if( initGL() == false ) 
    {
     return false; 
	} //Set caption 
  SDL_WM_SetCaption( "OpenGL BSP", NULL ); 
  return true; 
 }

#undef main
int main()
{
 init();
 bspbuffer.load("test1.bsp");
 do
   {
    render(); 
   }while(running);   
 return 0;
}//End main()


This topic is closed to new replies.

Advertisement