Jump to content
  • Advertisement
Sign in to follow this  
yuppies

Geomipmap terain Question

This topic is 4830 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

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

Share this post


Link to post
Share on other sites
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 variables
m_pfDistances = new float[nMaxLOD-1];
float fDisplacement = 0.0f;
float fTempHeight = 0.0f;

// start from the second most detailed patch
nOffSet = 2;

// loop through the vertices using offsets.
// calculate the height displacement between them.
// this will then be used to calculate the distances
for( 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 vertex
U = 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!

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!