Rendering Quake III BSP In DirectX

Started by
34 comments, last by xsirxx 19 years, 7 months ago
A gamma ramp is the way to go so you don't have to do all this yourself, however, if you want this to run in a window, you can't use the gamma functions (they only work in fullscreen mode IIRC).

You can see a screenshot of my viewer here
-dizzyGame Institute InternPlease rate me. :)
Advertisement
Don't render the faces as triangle fans, maps compiled with later bsp-compilers don't use triangle fans and you will get som pretty ugly results. Most web pages describing the format got this wrong.

Instead render as triangles with struct face.vertex as the start of the list of vertices and the meshverts starting at struct face.meshvert through struct face.n_meshverts as indices starting from struct face.vertex.

That might sound confusing, basically just take the meshvert indices of the face and index the list of vertices starting at the particular index given in the face by the vertex member.

This works with old and new maps without any problems and it's also the way to render type 3 faces (models) so if you get this down you'll be able to see all the models as well.

Good luck!
Fiskbil,

I think I've finally run into the issue you were talking about in regards to triangle fans. All I got was a whack of geometry all over hell's half acre with textures mapped here and there. I'd have to say it gave me my laugh for the day....but now I'm confused on how to implement what you mentioned in your last post.

Does this mean I require an index buffer as well as my vertex buffer...and I populate the index buffer with the mesh indices...or do I want to call DrawPrimitive() in a loop using the meshes? Everything I've tried up to this point has ended up in my world being warped beyond belief with holes, missing textures and tears all over the place.....and I can't seem to exactly figure out what you're describing in code from your explanation.

Thanks,

Permafried-

[Edited by - Permafried- on September 9, 2004 4:47:13 PM]
OK first you need to create an index buffer to go with the vertex buffer.

Then for each face you do the following:

1. Fill the vertex buffer with the vertices using the first vertex and number of vertices members of the face struct.
2. Fill the index buffer with the indices using the first index and number of indices members of the face struct.
3. Call SetStreamSource passing in your vertex buffer
4. Call SetIndices passing in your index buffer
5. Set your FVF to match your vertex format
3. Call DrawIndexedPrimitive passing in triangle list for the type and numindices/3 for the number of primitives.

This should get you started in the right direction although it doesn't work for bezier patches as they do not have indices. You have to actually do the math on them to calculate all the vertices and indices. Right now stick with rendering just the polys and meshes as they have indices included with them.

Good luck.
Let us know how you make out.
-dizzyGame Institute InternPlease rate me. :)
Yzzid,

Good to hear from you again...and thanks for the much clearer explanation. I thought maybe I'd gotten away without having to use dynamic vertex and index buffers while rendering but apparently I'm right back to square one again. I'm assuming since I'll be rendering one face while preparing for the next that my framerate shouldn't suffer too too much though I'm trying to keep in mind what Circlesoft mentioned way back when this thread first started.

Thanks again and I'll let you know how it goes.

Permafried-
That was just a preliminary test.
If you figure the above algorithm out and get it working you can then optimize it by batching the faces by shader.
This is how I do it in my engine right now.
Now if only I can figure out why the transparent polys are drawing in the wrong order ;)
-dizzyGame Institute InternPlease rate me. :)
Yzzid,

I think I've found a way to get around the dynamic buffers by offsetting into the index buffer using the face information. Basically I have a loop that goes through each face in reverse order (while iNumOfFaces--) and then checks visibility and type prior to rendering.

In my level load I create the vertex and index buffers and populate them with the level information as follows:

// lock the vertex bufferm_pvbLevelVertexBuffer->Lock( 0, 0, (void**)&pVertex, 0 );// load the vertex bufferfor( int i = 0; i < m_pLevel->levelGetNumberOfVertices(); i++ ){	// get the current vertex	pVertex.d3dvPositionCoords			= m_pLevel-&gt;levelGetVertexAtIndex( i )-&gt;d3dvOrigin;<br>	pVertex.d3dvRegularTextureCoords	= m_pLevel-&gt;levelGetVertexAtIndex( i )-&gt;d3dvTexCoords;<br>	pVertex.d3dvLightmapTextureCoords	= m_pLevel-&gt;levelGetVertexAtIndex( i )-&gt;d3dvTexLightMap;<br>}<br><br><span class="cpp-comment">// unlock the vertex buffer</span><br>m_pvbLevelVertexBuffer-&gt;Unlock();<br><br><span class="cpp-comment">// lock the index buffer</span><br>m_pibLevelIndexBuffer-&gt;Lock( <span class="cpp-number">0</span>, <span class="cpp-number">0</span>, (<span class="cpp-keyword">void</span>**)&amp;pIndices, <span class="cpp-number">0</span> );<br><br><span class="cpp-comment">// load the index buffer</span><br>memcpy( pIndices, m_pLevel-&gt;levelGetMeshVertices(), <span class="cpp-keyword">sizeof</span>( <span class="cpp-keyword">int</span> ) * m_pLevel-&gt;levelGetNumberOfMeshVertices() );<br><br><span class="cpp-comment">// unlock the index buffer</span><br>m_pibLevelIndexBuffer-&gt;Unlock();<br><br><br><br></pre></div><!–ENDSCRIPT–><br><br>Back to my render I set the FVF, StreamSource and Indices prior to even entering the faces loop because they will never change so no use in setting it multiple times.  My code looks like the following for rendering the face:<br><br><!–STARTSCRIPT–><!–source lang="cpp"–><div class="source"><pre><br><span class="cpp-keyword">while</span>( iTotalNumberOfFaces– )<br>{<br>	<span class="cpp-comment">// get the current index into the face array, this will allow</span><br>	<span class="cpp-comment">// us to access the face information to render it</span><br>	iCurrentFaceIndex = m_pLevel-&gt;levelGetLeafFaceAtIndex( tCurrentLeaf-&gt;iLeafFace + iTotalNumberOfFaces );<br>					<br>	<span class="cpp-comment">// get the face at iCurrentFaceIndex from the level</span><br>	tCurrentFace = m_pLevel-&gt;levelGetFaceAtIndex( iCurrentFaceIndex );<br>					<br>	<span class="cpp-comment">// make sure this face is a polygon, we're not supporting patches</span><br>	<span class="cpp-comment">// and therefore curves or any special effects of any kind</span><br>	<span class="cpp-keyword">if</span>( tCurrentFace-&gt;iType != <span class="cpp-number">1</span> )<br>	{<br>		<span class="cpp-keyword">continue</span>;<br>	}<br><br>	<span class="cpp-comment">// set the texture stage state for the first texture</span><br>	pd3dDevice-&gt;SetTextureStageState( <span class="cpp-number">0</span>, D3DTSS_COLORARG1, D3DTA_TEXTURE );<br>	pd3dDevice-&gt;SetTextureStageState( <span class="cpp-number">0</span>, D3DTSS_COLOROP, D3DTOP_SELECTARG1 );<br><br>	<span class="cpp-comment">// set the texture stage state for the second texture</span><br>	pd3dDevice-&gt;SetTextureStageState( <span class="cpp-number">1</span>, D3DTSS_COLORARG1, D3DTA_TEXTURE );<br>	pd3dDevice-&gt;SetTextureStageState( <span class="cpp-number">1</span>, D3DTSS_COLORARG2, D3DTA_CURRENT );<br>	pd3dDevice-&gt;SetTextureStageState( <span class="cpp-number">1</span>, D3DTSS_COLOROP, D3DTOP_MODULATE );<br><br>	<span class="cpp-comment">// set the base texture and the lightmap texture, the</span><br>	<span class="cpp-comment">// base texture will be rendered first and the lightmap</span><br>	<span class="cpp-comment">// then blended with it to give the effect of lighting</span><br>	pd3dDevice-&gt;SetTexture( <span class="cpp-number">0</span>, m_pTextures[ tCurrentFace-&gt;iTextureID ].m_d3dtTexture );<br>	pd3dDevice-&gt;SetTexture( <span class="cpp-number">1</span>, m_pLightmaps[ tCurrentFace-&gt;iLightmapID ].m_d3dtTexture );<br><br>	<span class="cpp-comment">// render the face</span><br>	pd3dDevice-&gt;DrawIndexedPrimitive( D3DPT_TRIANGLELIST, tCurrentFace-&gt;iStartVertex, <span class="cpp-number">0</span>, tCurrentFace-&gt;iNumOfVertices, tCurrentFace-&gt;iStartMeshVertex, tCurrentFace-&gt;iNumOfMeshVertices / <span class="cpp-number">3</span> );<br>}<br><br><br></pre></div><!–ENDSCRIPT–><br><br>My problem is this doesn't seem to quite be working the way I expected it to but I'm hoping maybe you could point me in the right direction in regards to my DrawIndexedPrimitive() call.  I thought the arguments looked correct but I could be wrong and thought a second set of eyes might help.  Basically my level is all twisted and inside out not to mention I'll get small chunks of triangles here and there but definitely not the entire level.<br><br>Thanks again,<br><br>Permafried-
On the side, a lil hijacking here sorry... what is yer levelGetMeshVertices()? How is it loading the verticies from yer polys? Are they rending clockwise or cc? Would u mind doing a detailed post on yer levelGetMeshVertices()? Thanks much,

--Brad
--X
Hey,

All level->levelGetMeshVertices() does is return a pointer to my m_pMeshVertices array as follows:

int* CLevel::levelGetMeshVertices( void ){     return m_pMeshVertices;}[/souce]It's an array of int's m_iNumOfMeshVertices big.Permafried-
Well how are you creating yer index then?
--X

This topic is closed to new replies.

Advertisement