Sign in to follow this  
crippeli

Quake 3 BSP problem

Recommended Posts

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

Share this post


Link to post
Share on other sites
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[i];
Vertex v = Vertices[index];
}



Sorry if you already know all this [smile]

Share this post


Link to post
Share on other sites
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[i].VertexIndex].Point));

glDrawElements(GL_TRIANGLES, Faces[i].NumMeshVerts, GL_UNSIGNED_INT, &MeshVertices[Faces[i].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

Share this post


Link to post
Share on other sites
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[i] );
}

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.

Share this post


Link to post
Share on other sites
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).

Share this post


Link to post
Share on other sites
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 :)

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites
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 :)

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
yeh i think there is a flag.. but i can't remember for the life of me..

i use mingw which is windows port of gcc..

try using

typedef struct {

/* stuff here */

}__attribute__((packed)) Tfoo;

on your structures.

Share this post


Link to post
Share on other sites
If your Header struct is correct, then I don't see how this could be a padding issue:

struct DirEntry {
unsigned int offset; // 32 bit
unsigned int length; // 32 bit
};

struct Header {
char magic[4]; // 32 bit
unsigned int version; // 32 bit
DirEntry dir[17]; // 17 * 64 bit
};

So unless you are on a 64 bit machine...?

Share this post


Link to post
Share on other sites
I tried using the padding-attribute suggested by dev_null, but no dice.
I've checked my structs about 50 times, and they look like they should.

And i'm not on a 64-bit machine. I guess i'll go RTFM for gcc or something. :)

Share this post


Link to post
Share on other sites

very true.. was just a sugestion.. i got caught out when i did MD3 model loading.
couldn't remember if there was any funnys in the BSP format.

i think we need to see more code to help solve this problem.. :)

Share this post


Link to post
Share on other sites
Here are my structure definitions. I'm sorry about weird naming and lack of comments, but i'm just doing this as a test. I've not yet implemented structs for the other data in the bsp file, I thought i'd begin with vertices and faces.

Do you see something I don't? :)


enum BspLumps
{
ENTITIES = 0,
TEXTURES,
PLANES,
NODES,
LEAFS,
LEAFFACES,
LEAFBRUSHES,
MODELS,
BRUSHES,
BRUSHSIDES,
VERTICES,
MESHVERTS,
SHADERS,
FACES,
LIGHTMAPS,
LIGHTVOLUMES,
VISDATA,
MAXLUMPS
};

typedef struct
{
char ID[4];
unsigned int Version;
} BspHeader_t;

typedef struct {
unsigned int Offset;
unsigned int Length;
} BspLump_t;

typedef struct {
float Point[3];
float TexCoords[2];
float LightMapCoords[2];
float Normal[3];
char Color[4];
} BspVertex_t;

typedef struct {

int TextureID;
int Effect;
int Type;
int VertexIndex;
int NumVerts;
int MeshVertIndex;
int NumMeshVerts;
int LightmapID;
int LMapCorner[2];
int LMapSize[2];
float LMapPos[3];
float LMapBitsets[2][3];
float VNormal[3];
int Size[2];
} BspFace_t;

class CBsp
{
public:
CBsp();
~CBsp();

bool LoadBSP(char *fileName);
void DrawBSP();
private:
BspVertex_t *Vertices;
BspFace_t *Faces;
int *MeshVertices;

int NumVertices;
int NumMeshVertices;
int NumFaces;

CTextureManager *TextureManager;
CLogger *Logger;
};


Share this post


Link to post
Share on other sites
hmm... can't see anything there... though its starting to get late here.

might call it a night and have a closer look tomorrow (when my eyes aren't so saw)

:)

Share this post


Link to post
Share on other sites
Okay, now this is getting weird. I added a texture-struct and read these from the file. Now the program crashes again, and I get completely different values in the meshvertex indices. What could be causing this? I'm not even using the textures yet, I just read them. :(

[Edited by - crippeli on May 26, 2005 8:03:42 AM]

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this