Quake 3 BSP problem

Started by
18 comments, last by dev_null 18 years, 10 months ago
Hello chaps. I'm having trouble loading a quake 3 bsp file. The Meshvertex index-values are "weird", or at least the first 50 or so. Anyway this causes my application to segfault. This is how I read in the indices: fseek(bspFile, Lumps[MESHVERTS].Offset, SEEK_SET); fread(MeshVertices, sizeof(int), NumMeshVertices, bspFile); MeshVertices is an array of ints. My program crashes when it's time to render using these indices, so i thought i'd write them to my logfile and see what's up. It turns out the first 48 of the values are either 1098907648 or 0. The rest is useable index-data. (Tried to render a couple of faces into the face-array, and it looked as it should). So, any ideas? I've tried with several different bsp files with the same result. /Crippeli
Advertisement
Are you rendering the meshverts array directly? You shouldn't do that, instead use the first model in the Models array. Go through the faces starting with the first face in the model. In the face is an index into the meshverts array. Also note that the meshverts are not indices into the vertex array, but offsets from the first vertex in the face. So, to get the correct vertex do something like

for( int32 i = face.index; i < face.index + face.index_count; ++i ) {    int32 index = face.vertex + MeshVerts;    Vertex v = Vertices[index];}


Sorry if you already know all this [smile]
Yeah, i've already got that covered. :)

I'm using vertex arrays with glDrawElements to draw the faces.

Example:

glVertexPointer(3, GL_FLOAT, sizeof(BspVertex_t),&(Vertices[Faces.VertexIndex].Point));glDrawElements(GL_TRIANGLES, Faces.NumMeshVerts, GL_UNSIGNED_INT, &MeshVertices[Faces.MeshVertIndex]);


But i'm still curious about these faulty values. The lump's offset is relative to the beginning of the file right? Not the beginning of file + header-size + directory entries (lump info)?

It seems to me that my problem has something to do with reading the index data from file.

/Crippeli
Hmm, I tried looking at the meshverts values I read (from q3dm18.bsp) and I don't get the values you describe.

I use the following code to read all lumps:

template<typename T>void read( const DirEntries& dir_entry, std::vector<T>& list ) {    uint32 count = Header_.dir[dir_entry].length / sizeof( T );    T* ptr = new T[count];    assert( ptr );    seek( Header_.dir[dir_entry] );    read( ptr, sizeof( T ) * count );    fill( list, ptr, count );    SUCL::safe_delete_array( ptr );}template<typename T>void fill( std::vector<T>& list, T* src, uint32 count ) const {    list.clear();    for( uint32 i = 0; i < count; ++i )        list.push_back( src );}void read( void* ptr, std::streamsize size ) { Input_.read( (char*)ptr, size ); }void seek( const BSP::DirEntry& dir_entry ) { Input_.seekg( dir_entry.offset, std::ios_base::beg ); }std::ifstream	Input_;


I can't comment on the rendering code, I use DirectX.
Hmm, you seem to read the data from the same place as I do. Only with other methods.

As for my rendering code, it works if I skip the first 20 faces, since they use indices in the beginning of the meshvert indices-array (which are bad for some reason).
Are you sure your value in Lumps[MESHVERTS].Offset is correct?

i'm assuming you have MESHVERTS set to 11 and have a couple of structures something like this

typedef struct {

char acMagic[4]; /* always "IBSP" */
int iVersion; /* always 0x2E for Quake 3 BSP files */

} __attribute__((packed)) BSPHeader;

typedef struct {

int iOffset; /* offset to start of lump, relative to beginning of
* file
*/
int iLength; /* length of lump.*/

} __attribute__((packed)) BSPLump;

and reading from the BSP something like this?

/* read the header information from the file, to make sure this is a
* BSP file */
fread( &header, sizeof( BSPHeader ),1, pFile );

/* check this is a BSP file by comparing the magic in the header to what
* we expect */
if( memcmp( header.acMagic, "IBSP", 4 ) != 0 ) {
fclose( pFile );
return false;
}

/* read lump information from the file */
fread( &lumps, sizeof( BSPLump ),17, pFile );


you could be experiencing padding problems?

my 2c :)
Yes, that's basically how i've set it up. :)

I got it to work now, i had forgotten to check the face type before rendering.
Now rendering is only performed if the face type is 1 or 3 (polygon or mesh).

But this working might only be a coincidence. I doubt that the beginning of the meshvertex index-array is stuffed with unusable index values just because they aren't supposed to be used by any faces.

What do you mean by padding problems? :)

/Crippeli
padding problems, alignment problems?

sometimes the compiler adds extra bytes into structures to
keep the data aligned on say the 32bit boundry (depends on processor).

if you use sizeof then you may get values higher than expected
and as a result read in too many bytes from the file.

typedef struct {

unsigned short int a;
unsigned int b;
unsigned short int c;
unsigned short int d;
unsigned int e;

} Tfoo;

i.e this structure will be 14 but may return 16 as a result from a sizeof :)

just one of the nasty gotyah's :)
just a thought how are u calculating NumMeshVertices?

lump.length / sizeof ( int ) ?

Yes, that's how I do it.

About this alignment-problem. This is an optimization feature right? Good data-alignment = fewer cycles for read/write?

Can I turn it off by setting the optimization level to none? Or is there a flag I can pass to gcc? Just to see if this is what's causing my problem.

This topic is closed to new replies.

Advertisement