Q3 BSP File....

Hi there,
I try to display a Q3 BSP Map in OpenGL… I looked up “Unofficial Quake 3 Map Specs” and wrote a loading function… If I try to display the Faces I just get some weird Triangles… Here’s my draw function:

typedef struct BSPFaceStruct
{
int Texture;
int Effect;
int Type;
int Vertex;
int n_Vertices;
int Meshvert;
int n_Meshverts;
int lm_Index;
int lm_Start[2];
int lm_Size[2];
float lm_Origin[3];
float lm_Vecs[2][3];
float Normal[3];
int Size[2];
} BSPFace;

typedef struct BSPVertexStruct
{
float Position[3];
float Texcoord[2][2];
float Normal[3];
unsigned char Color[4];
} BSPVertex;

if(Map==NULL) return FALSE;
BSPVertex *vPtr;
BSPFace *fPtr=Map->Faces.pFaces;
for(int i=0;i<Map->Faces.Number;++i)
{
if(fPtr->Type==1)
{
vPtr=Map->Vertices.pVertices+fPtr->Vertex;
glBegin(GL_TRIANGLE_FAN);
for(int j=0;j<fPtr->n_Vertices;++j)
{
glColor3f(1,1,1);
glNormal3fv(vPtr->Normal);
glColor4ubv(vPtr->Color);
glVertex3fv(vPtr->Position);
vPtr+=sizeof(BSPVertex);
}
glEnd();
}
fPtr+=sizeof(BSPFace);
}

And in my import function:

unsigned char *pPtr=pBuffer;
BSPHeader pHeader = (BSPHeader)pPtr;

Map->Header=*pHeader;
if(Map->Header.Version!=MAPVERSION) return FALSE;

Map->Vertices.Number=Map->Header.DirEntries[DETYPE_VERTICES].length/sizeof(BSPVertex);
Map->Vertices.pVertices=new BSPVertex[Map->Header.DirEntries[DETYPE_VERTICES].length];
memcpy(Map->Vertices.pVertices,pPtr+Map->Header.DirEntries[DETYPE_VERTICES].offset,Map->Header.DirEntries[DETYPE_VERTICES].length);

Map->Faces.Number=Map->Header.DirEntries[DETYPE_FACES].length/sizeof(BSPFace);
Map->Faces.pFaces=new BSPFace[Map->Header.DirEntries[DETYPE_FACES].length];
memcpy(Map->Faces.pFaces,pPtr+Map->Header.DirEntries[DETYPE_FACES].offset,Map->Header.DirEntries[DETYPE_FACES].length);

[This message has been edited by Geniuz (edited 05-20-2001).]

i got a q3 bsp loader up and running within 3 hours the other day with the hwlp of the aftershock code IIRC www.planetquake.com/aftershock perhaps the incorrect triangles are the mesh patches for the curves in the game. the aftershock code has an example of how to construct curves from the mesh points.

The code only draws faces of type 1 (polygon)…
But I’ll try Aftershock anyway…
Thanx

I got a q3bsp viewer running from the code on that site and there doesn’t look too much wrong with your code but I might have spoted a few problems with your code:

1.) In your rendering loop you pre increment i & j which if I’m correct will mean you will miss out the last face and the last vertex of each face. Because most of the faces are probably quads which contain 2 triangles this will mean you only get the first triangle drawn. It should be

for (int i=0;i<Map->Faces.Number; i++)

and

for (int j=0;j<fPtr->nVertices; j++)

2.) Map->Vertices.pVertices=new BSPVertex[Map->Header.DirEntries[DETYPE_VERTICES].length];

Should be:

Map->Vertices.pVertices = new BSPVertex[Map->Vertices.Number];

The same is the case for the Faces, your code creates arrays way too big.

The post increment/preincrement thing doesn’t matter. In fact, using preincrement is usually more efficient as it means the program doesn’t have to create a temporary object to store the value of the object being incremented.

The for loop doesn’t compare the value of the increment expression to the exit criteria, it just evaulates the increment expression and then compares the value of the loop variable using the middle expression.

Got it:
Loading:

Map->Vertices.Number=Map->Header.DirEntries[DETYPE_VERTICES].length/sizeof(BSPVertex);
Map->Vertices.pVertices=new BSPVertex[Map->Vertices.Number];
memcpy(Map->Vertices.pVertices,pPtr+Map->Header.DirEntries[DETYPE_VERTICES].offset,Map->Header.DirEntries[DETYPE_VERTICES].length);
// Y->Z & Z->Y & H-Mirroring
BSPVertex *vPtr=Map->Vertices.pVertices;
float t;
for(int i=0;i<Map->Vertices.Number;++i)
{
t=vPtr->Position[1];
vPtr->Position[0]= -vPtr->Position[0];
vPtr->Position[1]=vPtr->Position[2];
vPtr->Position[2]=t;
t=vPtr->Normal[1];
vPtr->Normal[1]=vPtr->Normal[2];
vPtr->Normal[2]=t;
vPtr->Normal[0]= -vPtr->Normal[0];
++vPtr;
}

Map->Faces.Number=Map->Header.DirEntries[DETYPE_FACES].length/sizeof(BSPFace);
Map->Faces.pFaces=new BSPFace[Map->Faces.Number];
memcpy(Map->Faces.pFaces,pPtr+Map->Header.DirEntries[DETYPE_FACES].offset,Map->Header.DirEntries[DETYPE_FACES].length);
// Y->Z & Z->Y & H-Mirroring
BSPFace *fPtr=Map->Faces.pFaces;
for(i=0;i<Map->Faces.Number;++i)
{
t=fPtr->Normal[1];
fPtr->Normal[1]=fPtr->Normal[2];
fPtr->Normal[2]=t;
fPtr->Normal[0]= -fPtr->Normal[0];
++fPtr;
}

Drawing:
BSPVertex *vPtr;
BSPFace *fPtr=Map->Faces.pFaces;
for(int i=0;i<Map->Faces.Number;++i)
{
if(fPtr->Type==1)
{
vPtr=Map->Vertices.pVertices+fPtr->Vertex;
glBegin(GL_TRIANGLE_FAN);
for(int j=0;j<fPtr->n_Vertices;++j)
{
glNormal3fv(vPtr->Normal);
glColor4ubv(vPtr->Color);
glVertex3fv(vPtr->Position);
++vPtr;
}
glEnd();
}
++fPtr;
}

Have fun with it

[This message has been edited by Geniuz (edited 05-22-2001).]