📄 mgcterrainpage.cpp
字号:
break;
}
}
else // distant assumption
{
for (i = 0; i < 4; i++, pkChild++)
{
pkChild->ComputeInterval(rkModelEye,
m_fWorldTolerance);
if (pkChild->GetDeltaMax() > pkChild->GetDeltaL())
break;
}
}
// subdivide only if children all agree it should happen
if ( i < 4 )
{
// add child blocks (parent already removed)
for (i = 0; i < 4; i++, usChild++)
{
// add child block
AddToQueue(usChild);
assert( !m_akBlock[usChild].GetProcessed() );
m_usNumUnprocessed++;
}
continue;
}
}
}
// tag block as processed
pkBlock->SetProcessed(true);
}
// put processed block at rear of queue
AddToQueue(usBlock);
}
}
//---------------------------------------------------------------------------
void MgcTerrainPage::SimplifyVertices (const MgcVector3& rkModelEye,
const MgcVector3& rkModelDir, bool bCloseAssumption)
{
unsigned int usQueue, usBlock;
if ( m_usFront < m_usRear )
{
for (usQueue = m_usFront; usQueue < m_usRear; usQueue++)
{
usBlock = m_ausQueue[usQueue];
if ( m_akBlock[usBlock].GetVisible() )
{
m_akBlock[usBlock].SimplifyVertices(this,rkModelEye,
rkModelDir,m_fWorldTolerance,bCloseAssumption);
}
}
}
else
{
for (usQueue = m_usFront; usQueue < m_usQueueQuantity; usQueue++)
{
usBlock = m_ausQueue[usQueue];
if ( m_akBlock[usBlock].GetVisible() )
{
m_akBlock[usBlock].SimplifyVertices(this,rkModelEye,
rkModelDir,m_fWorldTolerance,bCloseAssumption);
}
}
for (usQueue = 0; usQueue < m_usRear; usQueue++)
{
usBlock = m_ausQueue[usQueue];
if ( m_akBlock[usBlock].GetVisible() )
{
m_akBlock[usBlock].SimplifyVertices(this,rkModelEye,
rkModelDir,m_fWorldTolerance,bCloseAssumption);
}
}
}
}
//---------------------------------------------------------------------------
void MgcTerrainPage::Simplify (MgcRenderer* pkRenderer,
const MgcVector3& rkModelEye, const MgcVector3& rkModelDir,
bool bCloseAssumption)
{
if ( m_fWorldTolerance == -1.0f )
SetPixelTolerance(pkRenderer,m_fPixelTolerance);
SimplifyBlocks(pkRenderer->GetCamera(),rkModelEye,rkModelDir,
bCloseAssumption);
SimplifyVertices(rkModelEye,rkModelDir,bCloseAssumption);
m_bNeedsTessellation = true;
}
//---------------------------------------------------------------------------
void MgcTerrainPage::Render (MgcTerrainBlock& rkBlock)
{
unsigned short usOrigin = rkBlock.GetX() + m_usSize*rkBlock.GetY();
unsigned short usTwoStride = 2*rkBlock.GetStride();
unsigned short usTwoStrideTimesSize = usTwoStride*m_usSize;
unsigned short usIndex[5] =
{
usOrigin,
usOrigin + usTwoStride,
usOrigin + rkBlock.GetStride()*(m_usSize + 1),
usOrigin + usTwoStrideTimesSize,
usOrigin + usTwoStrideTimesSize + usTwoStride
};
if ( rkBlock.GetEven() )
{
RenderTriangle(usIndex[0],usIndex[3],usIndex[1]);
RenderTriangle(usIndex[4],usIndex[1],usIndex[3]);
}
else
{
RenderTriangle(usIndex[1],usIndex[0],usIndex[4]);
RenderTriangle(usIndex[3],usIndex[4],usIndex[0]);
}
}
//---------------------------------------------------------------------------
void MgcTerrainPage::RenderTriangle (unsigned short usT, unsigned short usL,
unsigned short usR)
{
// determine if triangle is leaf or interior
bool bInterior;
if ( usR > usT )
{
if ( usL > usT )
bInterior = (usR - usT > 1);
else
bInterior = (usT - usL > 1);
}
else
{
if ( usL > usT )
bInterior = (usL - usT > 1);
else
bInterior = (usT - usR > 1);
}
if ( bInterior )
{
// Triangle is part of internal block and can be subdivided. M is
// the midpoint of edge <L,R>.
unsigned short usM = ((usL + usR) >> 1);
if ( m_akTVertex[usM].GetEnabled() )
{
RenderTriangle(usM,usT,usL);
RenderTriangle(usM,usR,usT);
return;
}
}
// pack the vertex data
unsigned char ucX, ucY;
if ( m_ausLookup[usT] == (unsigned short)(~0) )
{
ucX = usT % m_usSize;
ucY = usT / m_usSize;
m_akVertex[m_uiVertexQuantity].x = GetX(ucX);
m_akVertex[m_uiVertexQuantity].y = GetY(ucY);
m_akVertex[m_uiVertexQuantity].z = GetHeight(usT);
m_akTexture[m_uiVertexQuantity].x = GetTexture(ucX);
m_akTexture[m_uiVertexQuantity].y = GetTexture(ucY);
m_ausLookup[usT] = m_uiVertexQuantity++;
}
if ( m_ausLookup[usR] == (unsigned short)(~0) )
{
ucX = usR % m_usSize;
ucY = usR / m_usSize;
m_akVertex[m_uiVertexQuantity].x = GetX(ucX);
m_akVertex[m_uiVertexQuantity].y = GetY(ucY);
m_akVertex[m_uiVertexQuantity].z = GetHeight(usR);
m_akTexture[m_uiVertexQuantity].x = GetTexture(ucX);
m_akTexture[m_uiVertexQuantity].y = GetTexture(ucY);
m_ausLookup[usR] = m_uiVertexQuantity++;
}
if ( m_ausLookup[usL] == (unsigned short)(~0) )
{
ucX = usL % m_usSize;
ucY = usL / m_usSize;
m_akVertex[m_uiVertexQuantity].x = GetX(ucX);
m_akVertex[m_uiVertexQuantity].y = GetY(ucY);
m_akVertex[m_uiVertexQuantity].z = GetHeight(usL);
m_akTexture[m_uiVertexQuantity].x = GetTexture(ucX);
m_akTexture[m_uiVertexQuantity].y = GetTexture(ucY);
m_ausLookup[usL] = m_uiVertexQuantity++;
}
// add triangle to connectivity array
m_auiConnect[m_uiConnectLength++] = m_ausLookup[usT];
m_auiConnect[m_uiConnectLength++] = m_ausLookup[usR];
m_auiConnect[m_uiConnectLength++] = m_ausLookup[usL];
m_uiTriangleQuantity++;
}
//---------------------------------------------------------------------------
void MgcTerrainPage::RenderBlocks ()
{
// reset dynamic quantities
memset(m_ausLookup,0xFF,m_usSize*m_usSize*sizeof(unsigned short));
m_uiVertexQuantity = 0;
m_uiTriangleQuantity = 0;
m_uiConnectLength = 0;
unsigned short usQueue;
if ( m_usFront < m_usRear )
{
for (usQueue = m_usFront; usQueue < m_usRear; usQueue++)
{
MgcTerrainBlock& rkBlock = m_akBlock[m_ausQueue[usQueue]];
if ( rkBlock.GetVisible() )
Render(rkBlock);
}
}
else
{
for (usQueue = m_usFront; usQueue < m_usQueueQuantity; usQueue++)
{
MgcTerrainBlock& rkBlock = m_akBlock[m_ausQueue[usQueue]];
if ( rkBlock.GetVisible() )
Render(rkBlock);
}
for (usQueue = 0; usQueue < m_usRear; usQueue++)
{
MgcTerrainBlock& rkBlock = m_akBlock[m_ausQueue[usQueue]];
if ( rkBlock.GetVisible() )
Render(rkBlock);
}
}
}
//---------------------------------------------------------------------------
void MgcTerrainPage::StitchLR (MgcTerrainPage* pkRight)
{
// 'this' is left page, 'pkRight' is right page
assert( pkRight->m_usSize == m_usSize );
unsigned short usR = m_usSize;
for (unsigned short usY = 1; usY < m_usSizeM1; usY++, usR += m_usSize)
{
unsigned short usL = m_usSizeM1 + usR;
MgcTerrainVertex* pkLVertex = &m_akTVertex[usL];
MgcTerrainVertex* pkRVertex = &pkRight->m_akTVertex[usR];
pkRVertex->SetDependent(0,pkLVertex);
pkLVertex->SetDependent(1,pkRVertex);
}
}
//---------------------------------------------------------------------------
void MgcTerrainPage::StitchTB (MgcTerrainPage* pkBottom)
{
// 'this' is top page, 'pkBottom' is bottom page
assert( pkBottom->m_usSize == m_usSize );
unsigned short usOffset = m_usSize*m_usSizeM1;
for (unsigned short usB = 1; usB < m_usSizeM1; usB++)
{
unsigned short usT = usB + usOffset;
MgcTerrainVertex* pkTVertex = &m_akTVertex[usT];
MgcTerrainVertex* pkBVertex = &pkBottom->m_akTVertex[usB];
pkBVertex->SetDependent(1,pkTVertex);
pkTVertex->SetDependent(0,pkBVertex);
}
}
//---------------------------------------------------------------------------
void MgcTerrainPage::UnstitchLR (MgcTerrainPage* pkRight)
{
// 'this' is left page, 'pkRight' is right page
assert( pkRight->m_usSize == m_usSize );
unsigned short usR = m_usSize; // y = 1
for (unsigned short usY = 1; usY < m_usSizeM1; usY++, usR += m_usSize)
{
unsigned short usL = m_usSizeM1 + usR;
MgcTerrainVertex* pkLVertex = &m_akTVertex[usL];
MgcTerrainVertex* pkRVertex = &pkRight->m_akTVertex[usR];
pkRVertex->SetDependent(0,0);
pkLVertex->SetDependent(1,0);
}
}
//---------------------------------------------------------------------------
void MgcTerrainPage::UnstitchTB (MgcTerrainPage* pkBottom)
{
// 'this' is top page, 'pBottom' is bottom page
assert( pkBottom->m_usSize == m_usSize );
unsigned short usOffset = m_usSize*m_usSizeM1;
for (unsigned short usB = 1; usB < m_usSizeM1; usB++)
{
unsigned short usT = usB + usOffset;
MgcTerrainVertex* pkTVertex = &m_akTVertex[usT];
MgcTerrainVertex* pkBVertex = &pkBottom->m_akTVertex[usB];
pkBVertex->SetDependent(1,0);
pkTVertex->SetDependent(0,0);
}
}
//---------------------------------------------------------------------------
void MgcTerrainPage::Draw (MgcRenderer& rkRenderer)
{
if ( m_bNeedsTessellation )
{
m_bNeedsTessellation = false;
RenderBlocks();
}
MgcTriMesh::Draw(rkRenderer);
}
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
// streaming
//---------------------------------------------------------------------------
MgcObject* MgcTerrainPage::Factory (MgcStream& rkStream)
{
MgcTerrainPage* pkObject = new MgcTerrainPage;
MgcStream::Link* pkLink = new MgcStream::Link(pkObject);
pkObject->Load(rkStream,pkLink);
return pkObject;
}
//---------------------------------------------------------------------------
void MgcTerrainPage::Load (MgcStream& rkStream, MgcStream::Link* pkLink)
{
MgcTriMesh::Load(rkStream,pkLink);
}
//---------------------------------------------------------------------------
void MgcTerrainPage::Link (MgcStream& rkStream, MgcStream::Link* pkLink)
{
MgcTriMesh::Link(rkStream,pkLink);
}
//---------------------------------------------------------------------------
bool MgcTerrainPage::Register (MgcStream& rkStream)
{
return MgcTriMesh::Register(rkStream);
}
//---------------------------------------------------------------------------
void MgcTerrainPage::Save (MgcStream& rkStream)
{
MgcTriMesh::Save(rkStream);
}
//---------------------------------------------------------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -