Original Post
is there any body who has tried out the roam 2.0 algorithm? i have a question about the rendering code of the implementation example step 3. i am wondering how this can be done in a single pass. if i understand correctly, each diamond needs two parents if you want to split it. so there is something like the force split in roam. so when i force to split a diamond which has already been drawn, i would get an error. so how does it still function?
//the high-level rendering function to being ROAM rendering
void Terrain::ROAM::Render( void ) {
//reset the debug counters
m_vertsPerFrame= 0;
m_trisPerFrame = 0;
//turn on textured drawing (with the grid texture for now)
glBindTexture( GL_TEXTURE_2D, m_texture.GetID( ) );
glEnable( GL_TEXTURE_2D );
glColor3f( 1.0f, 1.0f, 1.0f );
//recurse on the two base triangles
glBegin( GL_TRIANGLES );
RenderChild( m_pLevel1Dmnd[2][1], 2, 0 );
RenderChild( m_pLevel1Dmnd[1][2], 0, 0 );
glEnd( );
//end texturing
glDisable( GL_TEXTURE_2D );
}
//recursive rendering function
void Terrain::ROAM::RenderChild( ROAMDiamond *pDmnd, int i, int cull ) {
ROAMDiamond *centerDmnd; //center, split-edge diamond
float *dmndCenter; //center vertex
float dist;
//get selected child create if not there, indicate recent use
centerDmnd= GetChild( pDmnd, i );
dmndCenter= centerDmnd->m_vert;
//check the triangle's bounding sphere against the view frustum
if( cull != CULL_ALLIN ) {
float r, rad;
int j, m;
rad= centerDmnd->m_bound;
//perform culling against the view frustum
for( j= 0, m= 1; j < 6; j++, m<<= 1 ) {
if( !( cull & m ) ) {
r= m_frustum[j][0]*dmndCenter[0] +
m_frustum[j][1]*dmndCenter[1] +
m_frustum[j][2]*dmndCenter[2] +
m_frustum[j][3];
//check for frustum inclusion
if( r*r > rad ) {
//check to see if the triangle is actually within the viewing frustum
if( r < 0.0f ) {
Unlock( centerDmnd );
return;
}
//triangle is within view
cull|= m;
}
}
}
}
//distance calculation
dist= SQR( ( dmndCenter[0] - m_camX ) ) +
SQR( ( dmndCenter[1] - m_camY ) ) +
SQR( ( dmndCenter[2] - m_camZ ) );
//recurse down to the next level if possible
if( centerDmnd->m_level < m_maxLevel && centerDmnd->m_error > dist*0.000001f ) {
if( centerDmnd->m_pParent[0] == pDmnd ) {
RenderChild( centerDmnd, 0, cull );
RenderChild( centerDmnd, 1, cull );
} else {
RenderChild( centerDmnd, 2, cull );
RenderChild( centerDmnd, 3, cull );
}
} else {
ROAMDiamond *pPrevDmnd, *pNextDmnd; //diamonds of other two triangle vertices
//determine all tri's verts
if( centerDmnd->m_pParent[0] == pDmnd ) {
pPrevDmnd= centerDmnd->m_pParent[2];
pNextDmnd= centerDmnd->m_pParent[3];
} else {
pPrevDmnd= centerDmnd->m_pParent[3];
pNextDmnd= centerDmnd->m_pParent[2];
}
//draw the tri with simple per-tri texture the shows the grid
glTexCoord2f( pPrevDmnd->m_vert[0]/m_size, pPrevDmnd->m_vert[2]/m_size ); glVertex3fv( pPrevDmnd->m_vert );
glTexCoord2f( pDmnd->m_vert[0]/m_size, pDmnd->m_vert[2]/m_size ); glVertex3fv( pDmnd->m_vert );
glTexCoord2f( pNextDmnd->m_vert[0]/m_size, pNextDmnd->m_vert[2]/m_size ); glVertex3fv( pNextDmnd->m_vert );
m_vertsPerFrame+= 3;
m_trisPerFrame++;
}
//undo locking from GetChild()
Unlock( centerDmnd );
}