Holes when rendering Quake 3 maps?

Started by
17 comments, last by Enrico 16 years, 6 months ago
Quote:Original post by Kazade
No, notice I use i + 1 as an index. The end - 1 prevents me reading past the end of the vertex array.


Uhm, yeah but let's say startVertexIndex is 10 and totalVertices is 120 then end would be 130. If you loop from startVertexIndex to i < end - 1 then the maximum value i will ever have is end - 1 - 1 = 128. Shouldn't that be 129?
Advertisement
Quote:Original post by Kazade
Oops, shoulda refreshed...

OK, my engine internally only deals with triangles internally. Whereas Quake 3 represents polys as triangle fans. That is why I break them down into triangles they are then easier to deal with.

This is wrong since the very early days of Quake3! After the first point release (or so) Quake3 uses only the triangles specified in the map file and they abandoned the triangle fans/strips/whatever. There is a comment somewhere in the Quake3 map compiler, that triangle fans are broken and should not be used.
Update your loader to use the raw triangle data from the map file instead and I am really sure your holes will disappear :-)

I have written several articles (floating around somewhere in the net) about Rendering Quake 3 Data, including maps, models and their shader scripts. The one which might be interesting for you is Loading and Rendering Quake3 Maps, over at viCampus.

Loading the texture files specified from the name in the map file is neither correct nor wrong. The correct way is to create a default shader script and use the name from the map as diffuse texture. This was extended to template scripts in Doom 3 and later, btw.

If you have any questions or problems, feel free to ask :-)
--
Wow, thanks for that info! All of the sample code and articles I found said they used triangle fans!

Well I'll do that tonight. I'm not writing a complete Q3 map renderer, I'm just really using the BSP for geometry which is why I'm just reading the texture name, I just use it as an key for my own material system.

Thanks for all the information, that article looks really useful.
Member of the NeHe team.
Just in case anyone else has the same problem. Switching from the triangle fans to triangles fixed the problem. I had no idea that there were 2 sets of indices. [smile]
Member of the NeHe team.
Hi, I also have the same problem with rendering certain Quake3 maps, I'm sure its the same thing causing it and am currently trying to swap over to Triangles but I'm having trouble working out what to change in my code to do that correctly, this is what I think is the relevant section of my current code:

// If we're not using VBOs.if(!GLEE_ARB_vertex_buffer_object || map->mVertexBufferAssigned == false){	// Set the array of vertexes to draw.	glVertexPointer(3, GL_FLOAT, sizeof(Q3Vertex), &(map->mVertexes[0].position));}// If we're using VBOs.else{	// Bind the VBO to use.	glBindBuffer(GL_ARRAY_BUFFER, map->mVBOVertex);	glVertexPointer(3, GL_FLOAT, 0, 0);}// Draw all of the polygon elements.glDrawArrays(GL_TRIANGLE_FAN, curFace.vertex, curFace.numVertices);


I've tried replacing GL_TRIANGLE_FAN with GL_TRIANGLES and that didn't work (all maps became holey), so I'm unsure as to what to change without resorting to trial and error to fix it. Can anyone help? Thanks! :) I apologise if its really obvious how to do this, I'm still fairly new to OpenGL.
http://www.thomaswiggins.co.uk (under construction)
Heres how i did it in d3d.

void Mesh_BSP::Draw( void ){	Globals::D3DDevice->SetStreamSource( 0, Vertex_Buffer, 0, sizeof(Map_Vertex) );	Globals::D3DDevice->SetFVF( FVF_MapVertex );		Globals::D3DDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_MODULATE );	Globals::D3DDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );	Globals::D3DDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );	Globals::D3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTA_DIFFUSE );	Globals::D3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE );	Globals::D3DDevice->SetTextureStageState( 1, D3DTSS_COLOROP, D3DTOP_MODULATE );	Globals::D3DDevice->SetTextureStageState( 1, D3DTSS_COLORARG1, D3DTA_TEXTURE );	Globals::D3DDevice->SetTextureStageState( 1, D3DTSS_COLORARG2, D3DTA_CURRENT );	Globals::D3DDevice->SetTextureStageState( 1, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 );	Globals::D3DDevice->SetTextureStageState( 1, D3DTSS_ALPHAARG1, D3DTA_TEXTURE );	Globals::D3DDevice->SetRenderState( D3DRS_CULLMODE, true );		for( int i = 0; i < NumFaces; i++ )		RenderFace( i );		Globals::D3DDevice->SetRenderState( D3DRS_CULLMODE, false );		Globals::D3DDevice->SetTextureStageState( 1, D3DTSS_COLOROP,  D3DTOP_DISABLE );}void Mesh_BSP::RenderFace( const int &Index ){	BSPFace *FacePtr = &Faces[Index];	if( FacePtr->LmIndex > 0 )		Globals::D3DDevice->SetTexture( 0, LightmapTextures[FacePtr->LmIndex] );	if( BlitTextures[FacePtr->Texture] )		Globals::D3DDevice->SetTexture( 1, BlitTextures[FacePtr->Texture] );		switch( FacePtr->Type )	{		case BSP_POLYGON:			Globals::D3DDevice->DrawPrimitive( D3DPT_TRIANGLEFAN, FacePtr->Vertex, FacePtr->NumVertexes - 2 );			break;		case BSP_PATCH:			break;		case BSP_MESH:			break;	}}
Quote:Original post by S8N

I've tried replacing GL_TRIANGLE_FAN with GL_TRIANGLES and that didn't work (all maps became holey)


The reason is that there are 2 sets of indices...

The way that I was originally doing it was reading the startVertex and looping to startVertex + numVertices drawing a trangle fan.

The proper way to do it is to load the face indices lump, which is a separate chunk of the file to read. These indices describe the polygons as triangles rather than triangle fans.

Take a look at the link Enrico posted above. It describes how to load and render these indices, there is also some sample code at the bottom. If you still have no luck I will post my new code tonight.


Member of the NeHe team.
I think I've worked it out now after looking at the links and the OpenGL API more carefully. [smile] This is what I changed my code to:

// If we're not using VBOs.if(!GLEE_ARB_vertex_buffer_object || map->mVertexBufferAssigned == false){	// Set the array of vertexes to draw.	glVertexPointer(3, GL_FLOAT, sizeof(Q3Vertex), &(map->mVertexes[curFace.vertex].position));}// If we're using VBOs.else{	// Bind the VBO to use.	glBindBuffer(GL_ARRAY_BUFFER, map->mVBOVertex);	glVertexPointer(3, GL_FLOAT, 0, BUFFER_OFFSET(sizeof(float) * 3 * curFace.vertex));}// Draw all of the polygon elements.glDrawElements(GL_TRIANGLES, curFace.numMeshVerts, GL_UNSIGNED_INT, &(map->mMeshVerts[curFace.meshVert]));
I also had to change my texture coord pointers in a similar way. My Face Indices are called Mesh Verts as that is what the Q3 BSP documentation I was using called it when I went to store that lump. The map in question that I tried is rendering much more accurately now, there are still a couple of holes in the map but I think that is probably because I haven't coded any rendering for curved surfaces. [grin] Thanks for the help!
http://www.thomaswiggins.co.uk (under construction)
Quote:Original post by S8N
The map in question that I tried is rendering much more accurately now, there are still a couple of holes in the map but I think that is probably because I haven't coded any rendering for curved surfaces. [grin] Thanks for the help!

I have some more articles on my hard disk, waiting for publishing. The article list includes Quake3's curved surfaces, their shader scripts, model rendering and some more... However, they all need some kind of polishing or are just not finished :-(
--

This topic is closed to new replies.

Advertisement