Is generating normals for this impossible...?

Started by
6 comments, last by ajoling 19 years, 6 months ago
... or is it just so hard that you need to be a rocket scientist. I've been spending days on this by now. This GameDev topic is my last try to, hopefully, find a solution. My problem is pretty straightforward: - When generating vertices of my heightmap, I'm immediatly separating them in chuncks of 16x16 vertices, for my quadtree - After that, my indices are generated. Now, there's just one tough nut to crack: All the vertices are generated quad wise, instead of row wise. I just cannot believe I have only found one topic/article about this on the entire gamedev forums/articles, and Google doesn't bring up anything usefull either. I mean.. if you want to use quadtrees, you have to put your vertices in an order so you can simply say: quadtree[0].StartVertex = 0 quadtree[0].VertexAmount = 100 quadtree[0].StartIndex = 1200 quadtree[0].Indices = 600 Right? Without generating your vertices to be quad wise instead of row-wise, this is impossible, as far as I can figure out. (The numbers are going wrong after 9, but it should show how everything is arranged, it's like 1/9) I've tried so many things, that showing all the code would fill pages. I only turn to GameDev when I'm really desperate :). The problem: The normals are simply generated incorrect, not taking into account the borders. I was using the code from Andy's site:

D3DXVECTOR3 CTerrain::GetTriangleNormal(D3DXVECTOR3* vVertex1,
D3DXVECTOR3* vVertex2, D3DXVECTOR3* vVertex3)
{
    D3DXVECTOR3 vNormal;
    D3DXVECTOR3 v1;
    D3DXVECTOR3 v2;

    D3DXVec3Subtract(&v1, vVertex2, vVertex1);
    D3DXVec3Subtract(&v2, vVertex3, vVertex1);

    D3DXVec3Cross(&vNormal, &v1, &v2);

    D3DXVec3Normalize(&vNormal, &vNormal);

    return vNormal;
}

for(i = 0; i < m_dwNumOfIndices; i=i+3)
    {
        
        dwVertex1 = pBufferIndices;
        dwVertex2 = pBufferIndices;
        dwVertex3 = pBufferIndices;

        vNormal = GetTriangleNormal(&amp;D3DXVECTOR3(pcvVertices[dwVertex1].x, pcvVertices[dwVertex1].y,
 pcvVertices[dwVertex1].z),
&amp;D3DXVECTOR3(pcvVertices[dwVertex2].x,
pcvVertices[dwVertex2].y,
 pcvVertices[dwVertex2].z), 
 &amp;D3DXVECTOR3(pcvVertices[dwVertex3].x, 
pcvVertices[dwVertex3].y,
 pcvVertices[dwVertex3].z));

        
        pNumOfSharedPolygons[dwVertex1]++;
        pNumOfSharedPolygons[dwVertex2]++;
        pNumOfSharedPolygons[dwVertex3]++;

        pSumVertexNormal[dwVertex1].x += vNormal.x;
        pSumVertexNormal[dwVertex1].y += vNormal.y;
        pSumVertexNormal[dwVertex1].z += vNormal.z;
        
        pSumVertexNormal[dwVertex2].x += vNormal.x;
        pSumVertexNormal[dwVertex2].y += vNormal.y;
        pSumVertexNormal[dwVertex2].z += vNormal.z;

        pSumVertexNormal[dwVertex3].x += vNormal.x;
        pSumVertexNormal[dwVertex3].y += vNormal.y;
        pSumVertexNormal[dwVertex3].z += vNormal.z;
    }

    
    <span class="cpp-comment">//Unlock the index buffer</span>
    m_pIndexBuffer-&gt;Unlock();

    <span class="cpp-keyword">for</span>(i = <span class="cpp-number">0</span>; i &lt; m_dwNumOfVertices; i++)
    {
        vNormal.x = (<span class="cpp-keyword">float</span>)pSumVertexNormal<span style="font-weight:bold;">.x / pNumOfSharedPolygons<span style="font-weight:bold;">;
        vNormal.y = (<span class="cpp-keyword">float</span>)pSumVertexNormal<span style="font-weight:bold;">.y / pNumOfSharedPolygons<span style="font-weight:bold;">;
        vNormal.z = (<span class="cpp-keyword">float</span>)pSumVertexNormal<span style="font-weight:bold;">.z / pNumOfSharedPolygons<span style="font-weight:bold;">;

        D3DXVec3Normalize(&amp;vNormal, &amp;vNormal);

        pcvVertices<span style="font-weight:bold;">.nx = vNormal.x;
        pcvVertices<span style="font-weight:bold;">.ny = vNormal.y;
        pcvVertices<span style="font-weight:bold;">.nz = vNormal.z;
    }



</pre></div><!–ENDSCRIPT–>

Which worked well, until I started with the quad ordered vertices. I have tried other code, takin into account 4 positions 

around, using the vertex position instead of the indices, which are generated like this:

<!–STARTSCRIPT–><!–source lang="cpp"–><div class="source"><pre>
	<span class="cpp-keyword">int</span> iCalcX = <span class="cpp-number">0</span>, iCalcY = <span class="cpp-number">0</span>;
		DWORD CurrVertex = <span class="cpp-number">0</span>;
		<span class="cpp-keyword">int</span> QuadNum = <span class="cpp-number">0</span>;
		<span class="cpp-keyword">int</span> VertsPerQuad = (Size * Size);
		<span class="cpp-keyword">int</span> RowNum = <span class="cpp-number">0</span>;
		<span class="cpp-keyword">int</span> ColsPerRow = <span class="cpp-number">8</span>;
		
		<span class="cpp-keyword">for</span> (QuadNum = <span class="cpp-number">1</span>; QuadNum &lt; <span class="cpp-number">85</span> ; QuadNum++) {
			pNode = &amp;objQuadTree.pNodeList[QuadNum];					
			
			<span class="cpp-comment">//Is it a leaf?</span>
			<span class="cpp-keyword">if</span> (pNode-&gt;bType == LEAF_TYPE) {
				<span class="cpp-comment">//Back to 8x8 grid position</span>
				iCalcX = (pNode-&gt;vBoundingCoordinates[<span class="cpp-number">0</span>].x + <span class="cpp-number">1024</span>)/<span class="cpp-number">256</span>;
				iCalcY = (pNode-&gt;vBoundingCoordinates[<span class="cpp-number">0</span>].z + <span class="cpp-number">1024</span>)/<span class="cpp-number">256</span>;
				
				<span class="cpp-comment">//Calculate row/col position</span>
				QuadPosition = ((iCalcY * <span class="cpp-number">8</span>) + iCalcX);
				
				pNode-&gt;bGridRow = (BYTE)iCalcY; <span class="cpp-comment">//Store row position</span>
				pNode-&gt;bGridCol = (BYTE)iCalcY; <span class="cpp-comment">//Store col position</span>

				<span class="cpp-comment">//Calculate start values</span>
				pNode-&gt;StartIndices = n;
				pNode-&gt;MinVertex = (VertsPerQuad*QuadPosition);

				<span class="cpp-keyword">for</span> (y = <span class="cpp-number">0</span>; y &lt; <span class="cpp-number">16</span>;y++)	{
					<span class="cpp-keyword">for</span> (x = <span class="cpp-number">0</span>; x &lt; <span class="cpp-number">16</span>;x++)	{
						CurrVertex = (VertsPerQuad*QuadPosition)+(y*Size) + x;

						pIndices[n++] = CurrVertex;	<span class="cpp-comment">// triangle 1</span>
						pIndices[n++] = CurrVertex+<span class="cpp-number">1</span>;	<span class="cpp-comment">// triangle 2  </span>
						pIndices[n++] = CurrVertex+Size;	<span class="cpp-comment">// triangle 3</span>
						
						pIndices[n++] = CurrVertex+Size+<span class="cpp-number">1</span>;	<span class="cpp-comment">// triangle 3</span>
						pIndices[n++] = CurrVertex+Size;	<span class="cpp-comment">// triangle 4</span>
						pIndices[n++] = CurrVertex+<span class="cpp-number">1</span>;	<span class="cpp-comment">// triangle 5</span>

					}

				}
				<span class="cpp-comment">//Calculate end values. Divide indices by 3 already.</span>
				pNode-&gt;IndicesLength = (n - pNode-&gt;StartIndices) /<span class="cpp-number">3</span>;
				pNode-&gt;NumVertex = (VertsPerQuad*(QuadPosition+<span class="cpp-number">1</span>)) - pNode-&gt;MinVertex;
			}
		}


</pre></div><!–ENDSCRIPT–>

(some things are hardcoded for testing)

It looks all good:

<img src"http://www.persistentrealities.com/problem/bad3.jpg">

But the terrain is acting weird too:

<img src="http://www.persistentrealities.com/problem/bad1.jpg">

I hope someone can help me &#111;n this. If you need more info, simply ask.

So note though: I have never access to full vertex row data, as it's organized by quadtree level.

Any help appreciated,
Almar
www.persistentrealities.com for Inline ASM for VB, VB Fibre, and other nice code samples in C++, PHP, ASP, etc.<br/>Play Yet Another Laser Game!<br/>
Advertisement
Computing normals for vertices and placing verticies into a quadtree are two separate things. First do one, then the other.

karg
Note that you can compute normals without knowing anything about the neighboring vertices, if you know the data that generated those vertices. Thus, you can compute a normal per vertex by just evaluating the slope of your heighfield at the point in question; say by running a Sobel filter on the height map data around the point that generated the vertex.
enum Bool { True, False, FileNotFound };
I generally find it handy to have a method of querying height values by absolute coords rather than just by trying to manually extract the vertices from whatever crazy optimised format you've got for rendering. Then normal generation will become much easier.

For the second problem of your terrain looking odd, it looks as if you've forgotten to turn on depth testing, and chunks are being drawn over the top of each other.
I'm going to try one more time tommorow, using the heightmap directly (did that before though)

If it won't work (which will probably happen), I'm going to change my stuff row-based again, and think of a new structure. I got the theory on paper already.

As for the rendering: the Z buffer is enabled, if that's what you mean. (16 bit though, my *uch* voodoo3 doesn't like 32).

Thanks :)

www.persistentrealities.com for Inline ASM for VB, VB Fibre, and other nice code samples in C++, PHP, ASP, etc.<br/>Play Yet Another Laser Game!<br/>




That's a lot better :). The squary look. That's the vertex lighting I guess? Still haven't found out how to solve the hills being transparant though.

Thanks :)
www.persistentrealities.com for Inline ASM for VB, VB Fibre, and other nice code samples in C++, PHP, ASP, etc.<br/>Play Yet Another Laser Game!<br/>
You're just not enabling backface culling. Or Z-buffering. Either will fix that; you're drawing the terrain behind the hill after you draw the hill, which means it gets drawn overtop.
RIP GameDev.net: launched 2 unusably-broken forum engines in as many years, and now has ceased operating as a forum at all, happy to remain naught but an advertising platform with an attached social media presense, headed by a staff who by their own admission have no idea what their userbase wants or expects.Here's to the good times; shame they exist in the past.
Yeah, I got it fixed. somehow the Zbuffer wasn't doing very properly - But it didn't give any errors either.

Now it's time for some detail texturing :)
www.persistentrealities.com for Inline ASM for VB, VB Fibre, and other nice code samples in C++, PHP, ASP, etc.<br/>Play Yet Another Laser Game!<br/>

This topic is closed to new replies.

Advertisement