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;
Geomipmap terain Question
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)
What are the other way of doing this?
thanks
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:
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:
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!
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!
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement