//-------------------------------------------------------------- // Name: CGEOMIPMAPPING::RenderPatch - private // Description: Render a patch of terrain // Arguments: -PX, PZ: the patch location // -bMultitex: use multitexturing or not // -bDetail: render with a detail map or not // Return Value: None //-------------------------------------------------------------- void CGEOMIPMAPPING::RenderPatch( int PX, int PZ, bool bMultiTex, bool bDetail ) { SGEOMM_NEIGHBOR patchNeighbor; SGEOMM_NEIGHBOR fanNeighbor; float fSize; float fHalfSize; float x, z; int iPatch= GetPatchNumber( PX, PZ ); int iDivisor; int iLOD; //find out information about the patch to the current patch's left, if the patch is of a //greater detail or there is no patch to the left, we can render the mid-left vertex if( m_pPatches[GetPatchNumber( PX-1, PZ )].m_iLOD<=m_pPatches[iPatch].m_iLOD || PX==0 ) patchNeighbor.m_bLeft= true; else patchNeighbor.m_bLeft= false; //find out about the upper patch if( m_pPatches[GetPatchNumber( PX, PZ+1 )].m_iLOD<=m_pPatches[iPatch].m_iLOD || PZ==m_iNumPatchesPerSide ) patchNeighbor.m_bUp= true; else patchNeighbor.m_bUp= false; //find out about the right patch if( m_pPatches[GetPatchNumber( PX+1, PZ )].m_iLOD<=m_pPatches[iPatch].m_iLOD || PX==m_iNumPatchesPerSide ) patchNeighbor.m_bRight= true; else patchNeighbor.m_bRight= false; //find out about the lower patch if( m_pPatches[GetPatchNumber( PX, PZ-1 )].m_iLOD<=m_pPatches[iPatch].m_iLOD || PZ==0 ) patchNeighbor.m_bDown= true; else patchNeighbor.m_bDown= false; //we need to determine the distance between each triangle-fan that //we will be rendering iLOD = m_pPatches[GetPatchNumber( PX, PZ )].m_iLOD+1; fSize = ( float )m_iPatchSize; iDivisor= m_iPatchSize-1; //find out how many fan divisions we are going to have while( --iLOD>-1 ) iDivisor= iDivisor>>1; //the size between the center of each triangle fan fSize/= iDivisor; //half the size between the center of each triangle fan (this will be //the size between each vertex) fHalfSize= fSize/2.0f; for( z=fHalfSize; ( ( int )( z+fHalfSize ) )<m_iPatchSize+1; z+=fSize ) { for( x=fHalfSize; ( ( int )( x+fHalfSize ))<m_iPatchSize+1; x+=fSize ) { //if this fan is in the left row, we may need to adjust it's rendering to //prevent cracks if( x==fHalfSize ) fanNeighbor.m_bLeft= patchNeighbor.m_bLeft; else fanNeighbor.m_bLeft= true; //if this fan is in the bottom row, we may need to adjust it's rendering to //prevent cracks if( z==fHalfSize ) fanNeighbor.m_bDown= patchNeighbor.m_bDown; else fanNeighbor.m_bDown= true; //if this fan is in the right row, we may need to adjust it's rendering to //prevent cracks if( x>=( m_iPatchSize-fHalfSize ) ) fanNeighbor.m_bRight= patchNeighbor.m_bRight; else fanNeighbor.m_bRight= true; //if this fan is in the top row, we may need to adjust it's rendering to //prevent cracks if( z>=( m_iPatchSize-fHalfSize ) ) fanNeighbor.m_bUp= patchNeighbor.m_bUp; else fanNeighbor.m_bUp= true; //render the triangle fan RenderFan( ( PX*m_iPatchSize )+x, ( PZ*m_iPatchSize )+z, fSize, fanNeighbor, bMultiTex, bDetail ); } } }
void GeoMipMapping::RenderPatch(int px, int pz) { SGEOMM_NEIGHBOR patchNeighbor; SGEOMM_NEIGHBOR fanNeighbor; float fSize = 0.0f; float fHalfSize = 0.0f; float z, x; int iPatch = GetPatchNumber(px, pz); int iDivisor = 0; int iLOD = 0; //左边的比较精细,所以不用管,直接可以绘制 if (m_pPatches[GetPatchNumber(px - 1, pz)].m_iLOD <= m_pPatches[iPatch].m_iLOD || px == 0) patchNeighbor.m_bLeft = true; //可以绘制 else patchNeighbor.m_bLeft = false; //不能绘制 if (m_pPatches[GetPatchNumber(px, pz + 1)].m_iLOD <= m_pPatches[iPatch].m_iLOD || pz == m_iNumPatchesPerSide) patchNeighbor.m_bUp = true; else patchNeighbor.m_bUp = false; if (m_pPatches[GetPatchNumber(px + 1, pz)].m_iLOD <= m_pPatches[iPatch].m_iLOD || px == m_iNumPatchesPerSide) patchNeighbor.m_bRight = true; else patchNeighbor.m_bRight = false; if (m_pPatches[GetPatchNumber(px, pz - 1)].m_iLOD <= m_pPatches[iPatch].m_iLOD || pz == 0) patchNeighbor.m_bBottom = true; else patchNeighbor.m_bBottom = false; fSize = (float)m_iPatchSize; iDivisor = m_iPatchSize - 1; iLOD = m_pPatches[iPatch].m_iLOD; while (iLOD-- >= 0) iDivisor >>= 1; fSize /= iDivisor; fHalfSize = fSize / 2.0f; for (z = fHalfSize; ((int)z + fHalfSize ) < m_iPatchSize + 1; z += fSize) { for (x = fHalfSize; ((int)x + fHalfSize) < m_iPatchSize + 1; x += fSize) { if (x == fHalfSize) fanNeighbor.m_bLeft = patchNeighbor.m_bLeft; else fanNeighbor.m_bLeft = true; if (z == fHalfSize) fanNeighbor.m_bBottom = patchNeighbor.m_bBottom; else fanNeighbor.m_bBottom = true; if (x >= (m_iPatchSize - fHalfSize)) fanNeighbor.m_bRight = patchNeighbor.m_bRight; else fanNeighbor.m_bRight = true; if (z >= (m_iPatchSize - fHalfSize)) fanNeighbor.m_bUp = patchNeighbor.m_bUp; else fanNeighbor.m_bUp = true; RenderFan((px * m_iPatchSize) + x, (pz * m_iPatchSize) + z, fSize, fanNeighbor); } } }