Geomipmap terain Question

Started by
0 comments, last by DirectXFreak 18 years, 8 months ago
i already have a Geomipmapping terrain rendered via a triangle fan, i only based it in Jim Adams' Terrain book i have a question for Geomipmapping; ) How can i determine the LOD for its patch effectively, since in adams book setting the LOD is hardcoded after computing the distance from the camera position to the center of the patch heres an exerpt of Jim's code( see how the Distance is compared and also the setting for the LOD of the patch)

m_pPatches[index].fDistance = sqrtf( ((m_pPatches[index].centerx - campos.m_vector.x) * (m_pPatches[index].centerx - campos.m_vector.x)) + 
													 ((m_pPatches[index].centery - campos.m_vector.y) * (m_pPatches[index].centery - campos.m_vector.y)) +
													 ((m_pPatches[index].centerz - campos.m_vector.z) * (m_pPatches[index].centerz - campos.m_vector.z)));
				//a bit of a hack
				if( m_pPatches[index].fDistance < 1000 )
					m_pPatches[index].iLOD= 0;

				else if( m_pPatches[index].fDistance< 1500 )
					m_pPatches[index].iLOD= 1;

				else if( m_pPatches[index].fDistance< 2000 )
					m_pPatches[index].iLOD= 2;

				else if( m_pPatches[index].fDistance>=2000)
					m_pPatches[index].iLOD= 3;

What are the other way of doing this? thanks
Advertisement
Yes,

The whitepaper for geomipmapping explains a method that transforms the height error into screenspace I believe.

Anyway, I implemented this while ago, here's some code I dug up:

[source lang = "cpp"]// the distance variablesm_pfDistances			 = new float[nMaxLOD-1];float fDisplacement		 = 0.0f;float fTempHeight		 = 0.0f;	// start from the second most detailed patchnOffSet = 2;// loop through the vertices using offsets.// calculate the height displacement between them.// this will then be used to calculate the distancesfor( i=0;i<nMaxLOD-1;i++ ) {	// loop through all of the indices	for( UINT x=0;x<nPatchSize-1; ) 	{		for( UINT z=0;z<nPatchSize-1; ) 		{			// get midpoint			fTempHeight = fabs(pVerts[(z*nPatchSize)+x].fY+pVerts[(z*nPatchSize)+x+nOffSet].fY);			fTempHeight /= 2;			// now jump back half and compare			fTempHeight = fabs(pVerts[(z*nPatchSize)+x+(nOffSet/2)].fY-fTempHeight);							// fTempHeight is the displacement of the LOD, compare it with the overall find			if( fDisplacement < fTempHeight ) 			{				fDisplacement = fTempHeight;			}			z+=nOffSet;		}		x+=nOffSet;	}	// D = |Displacement|*C	// C = A/T	// A = n/|t|	// T = (2*pxallw)/vres	//--------------------	// Get helper variables first	//--------------------	// Near clipping plane	float fNearClip;	m_pGMMParent->m_pDevice->vGetClippingPlanes(&fNearClip,NULL);	// FOV	float fFOV = m_pGMMParent->m_pDevice->fGetFOV();	// Pixel allowance	float fPxlAllowance = m_pGMMParent->m_nPixelAllowance;	// ViewPort	CViewPort viewPort  = m_pGMMParent->m_pDevice->GetViewPort(nStage);		//--------------------	// Now solve for the Distance	//--------------------	// Solve for A	float fA = fNearClip/(fNearClip*tanf(fFOV));	// Solve for T	float fT = (fPxlAllowance)/viewPort.dwHeight;	// Solve for C	float fC = fA/fabs(fT);	// Solve for D	float fD = (fDisplacement*fDisplacement)*(fC*fC);	//--------------------	// fD is now the minimum distance	// that this patch can be showed.	//--------------------	float fDistPadding;	fDistPadding  = ((float)nPatchSize*0.5f*m_pGMMParent->m_vScale.x);	fDistPadding *= ((float)nPatchSize*0.5f*m_pGMMParent->m_vScale.x);	// add padding	fD += fDistPadding;	// add previous distances	if( i != 0 ) 	{		m_pfDistances = fD+m_pfDistances[i-1];	}	else 	{		m_pfDistances = fD;	}	// go on to the next LOD	nOffSet *= 2;}


Now, what this code does is loop through all the LODs in a patch (I had one index buffer per LOD). Then it loops through all the vertices in the current LOD, and finds the midpoint between every two vertices. For example:

O = Current vertexU = midpoint displacement*   0 U *   *   *     <- Terrain Patch   *   *   *   *   **   *   *   *   **   *   *   *   **   *   *   *   * Another View:(*) = Vertex      (*)       / \    The O is the midpoint displacement, it may not be a perfect midpoint as     /   \   it is here, because lower lods will have other vertices between them.    O     0   /       \ <- side view, a point in the terrain,   /         \   left and right points in the X or Z (*)          (*) axis direction (either) and Y is up


The loop finds the largest displacement value in the patch, and stores it.
Next, the displacement value is put through a serious of calculations that convert it screen space. This means that the displacement error will be in pixels, 5 pixels high for example. The fPxlAllowance variable tells the equation the limit that you will allow for the error in pixels. Five to eight are good values. If you implement vertex tweening you get away with higher.

The final calulation adds a padding value to the distance (the radius of the patch). This is necessary because the distance assumes the error to be at the center of the patch, so a vertex jutting out at the edge of the patch will be considerablely more noticeable than the limit allows for.

Finally, the distance is added with the distance for the previous LOD patch, and the final value is stored.

This method works a ton better.

I hope this helped!
--m_nPostCount++

This topic is closed to new replies.

Advertisement