Untitled

posted in DruinkJournal
Published January 10, 2008
Advertisement
Yay! Textures work!

It's currently less than efficient, I'm drawing each face seperately, which means I have silly numbers of draw calls, but I can batch by texture later on to make that much better.

It's a bit of a pain to do, since I need to patch up vertex indices, but it works. And textures were surprisingly easy (Thank god for the Unofficial Quake Specs telling you how to use them).

So, screenshot time:
Slipgate
(Click to enlarge)

And the code that makes it work - Which isn't really that interesting, but might be useful if someone else writing a Quake BSP renderer stumbles across this:
// BSP vertices are just points, we need point + texture coordinate.// Since all vertices of a face share the same texture, we can cache// vertices on a per-face basis. So, create a lookup table that will// look up BSP vertexindices to "real" indices (-1 means "not// yet initialised").s32* pVertexLookup = new s32[nVerts];if(!pVertexLookup){	Cleanup();	ELog::Get().DebugLog(L"MapContextBSP::Load: Out of memory!\n");	return false;}std::vector vVerts;vVerts.reserve(nVerts);u16* pLock = (u16*)m_pIB->Lock(0, nEdges*2);if(!pLock){	delete[] pVertexLookup;	Cleanup();	ELog::Get().DebugLog(L"MapContextBSP::Load: Failed to lock index buffer\n");	return false;}size_t nIndex = 0;for(u32 nLeaf=1; nLeaf<75; ++nLeaf){	const BSPLeaf& leaf = pLeafs[nLeaf];	for(u32 nFace=0; nFace	{		const BSPFace& face = pFaces[pFaceLookup[leaf.lface_id + nFace]];		const BSPTextureInfo& texinfo = pTexInfos[face.texinfo_id];		Face outFace;		outFace.nTexture = texinfo.miptex;		outFace.nStartIndex = nIndex;		outFace.nNumTris = 0;		u16 nRoot=0;		u16 nLast=0;		std::fill(pVertexLookup, pVertexLookup+nVerts, -1);		for(u32 nEdge=0; nEdge		{			// Find indices for this edge			s32 nEdgeLookup = pEdgeLookup[face.ledge_id + nEdge];			u16 v0, v1;			if(nEdgeLookup > 0)			{				v0 = pEdges[nEdgeLookup].v0;				v1 = pEdges[nEdgeLookup].v1;			}			else			{				v0 = pEdges[-nEdgeLookup].v1;				v1 = pEdges[-nEdgeLookup].v0;			}			// Make up a triangle			if(nEdge == 0)				nRoot = v0;			else			{				Assert(nLast == v0, "Face edges do not form a line loop!");				// Patch up vertices				u16 nIndices[3] = {nRoot, nLast, v1};				for(int j=0; j<3; ++j)				{					u16 nIndex = nIndices[j];					if(pVertexLookup[nIndex] == -1)					{						Vertex vert;						vert.vPos = EVector3(pVertices[nIndex].pos.x,							pVertices[nIndex].pos.z,							pVertices[nIndex].pos.y);						vert.nColour = 0xffffffff;						vert.tu = (pVertices[nIndex].pos.DotProduct(texinfo.vecS) + texinfo.distS) /							(float)m_vTextures[texinfo.miptex].pTexture->GetWidth();						vert.tv = (pVertices[nIndex].pos.DotProduct(texinfo.vecT) + texinfo.distT) /							(float)m_vTextures[texinfo.miptex].pTexture->GetHeight();						pVertexLookup[nIndex] = (u32)vVerts.size();						vVerts.push_back(vert);						Assert(vVerts.size() < 65536, "More than 64k vertices! Start panicing!");					}					*pLock++ = (u16)pVertexLookup[nIndex];				}				nIndex += 3;				++outFace.nNumTris;			}			nLast = v1;		}		m_vFaces.push_back(outFace);	}}m_pIB->Unlock();delete[] pVertexLookup;

There's nothing much to say about that code really. The loop over the leafs is a magic number again (75 just happens to be the number of leafs in that chunk of the map). m_vTextures is a vector of structs containing a texture pointer (In the order specified in the BSP file), and that code fills the index buffer, and fills a vector of faces and vertices. I'll have to change the code so that the number of indices is worked out rather than using a magic number (Which you can't see in that code).

Rendering is pretty simple too:
bool PMapContextBSP::Render(PGraphics& gfx){	m_pShader->SetMatrix("mWorldViewProj", m_pOwner->GetTransform() * gfx.GetViewProj());	gfx.SetIndices(m_pIB);	gfx.SetVertexDecl(m_pVertexDecl);	gfx.SetVertexShader(m_pShader);	gfx.SetStreamSource(m_pVB, 0);	for(size_t i=0; i	{		const Face& face = m_vFaces;		gfx.SetTexture(0, m_vTextures[face.nTexture].pTexture);		gfx.DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, m_header.lumps[BSPHeader::LUMP_Vertices].nSize / sizeof(BSPVert),			(UINT)face.nStartIndex, (UINT)face.nNumTris);	}	return true;}

Again, not very efficient. It transforms all the vertices (And that's the wrong number, I just noticed...), and uses worst case parameters for the DIP() call. There's no sorting by texture or anything (yet) either. Still, it works, and that's the main thing.

Anyhoo, back to work I think...
Previous Entry Untitled
Next Entry Untitled
0 likes 0 comments

Comments

Nobody has left a comment. You can be the first!
You must log in to join the conversation.
Don't have a GameDev.net account? Sign up!
Advertisement
Advertisement