📄 mgcterrainblock.cpp
字号:
if ( fMin < 0.0 )
fMin *= rkFrustum.GetDRatio();
fMax = fTmp + fP;
if ( fMax > 0.0 )
fMax *= rkFrustum.GetDRatio();
fDdD = -afD[0]*afNBmUC[i] + afD[1]*afNApLC[i] - afD[2]*afLBpUA[i];
fR = 0.0;
for (j = 0; j < 3; j++)
{
fR += afE[j]*MgcMath::Abs(-afA[j]*afNBmUC[i]+ afB[j]*afNApLC[i]
- afC[j]*afLBpUA[i]);
}
if ( fDdD + fR < fMin || fDdD - fR > fMax )
return false;
}
// M = Cross(n*D-l*L-u*U,A[i])
for (i = 0; i < 3; i++)
{
fP = rkFrustum.LBound()*MgcMath::Abs(afNBpUC[i]) +
rkFrustum.UBound()*MgcMath::Abs(afNApLC[i]);
fTmp = -rkFrustum.DMin()*afLBmUA[i];
fMin = fTmp - fP;
if ( fMin < 0.0 )
fMin *= rkFrustum.GetDRatio();
fMax = fTmp + fP;
if ( fMax > 0.0 )
fMax *= rkFrustum.GetDRatio();
fDdD = -afD[0]*afNBpUC[i] + afD[1]*afNApLC[i] - afD[2]*afLBmUA[i];
fR = 0.0;
for (j = 0; j < 3; j++)
{
fR += afE[j]*MgcMath::Abs(-afA[j]*afNBpUC[i]+ afB[j]*afNApLC[i]
- afC[j]*afLBmUA[i]);
}
if ( fDdD + fR < fMin || fDdD - fR > fMax )
return false;
}
return true;
}
//---------------------------------------------------------------------------
void MgcTerrainBlock::TestIntersectFrustum (const MgcTerrainPage* pPage,
const MgcCamera* pkCamera)
{
SetVisibilityTested(true);
// centered-form bounding box of page in terrain model space
MgcBox3 kBox;
kBox.Center() = 0.5*(m_kMin + m_kMax);
kBox.Extent(0) = 0.5*(m_kMax.x - m_kMin.x);
kBox.Extent(1) = 0.5*(m_kMax.y - m_kMin.y);
kBox.Extent(2) = 0.5*(m_kMax.z - m_kMin.z);
kBox.Axis(0) = MgcVector3::UNIT_X;
kBox.Axis(1) = MgcVector3::UNIT_Y;
kBox.Axis(2) = MgcVector3::UNIT_Z;
// inverse transform to camera space
MgcVector3 kDiff = kBox.Center() - pkCamera->GetLocation();
kBox.Center() = MgcVector3(kDiff.Dot(pkCamera->GetLeft()),
kDiff.Dot(pkCamera->GetUp()),kDiff.Dot(pkCamera->GetDirection()));
kBox.Axis(0) = MgcVector3(pkCamera->GetLeft().x,pkCamera->GetUp().x,
pkCamera->GetDirection().x);
kBox.Axis(1) = MgcVector3(pkCamera->GetLeft().y,pkCamera->GetUp().y,
pkCamera->GetDirection().y);
kBox.Axis(2) = MgcVector3(pkCamera->GetLeft().z,pkCamera->GetUp().z,
pkCamera->GetDirection().z);
// default frustum matches camera coordinate frame
MgcFrustum kFrustum;
kFrustum.LBound() = pkCamera->GetFrustumRight();
kFrustum.UBound() = pkCamera->GetFrustumTop();
kFrustum.DMin() = pkCamera->GetFrustumNear();
kFrustum.DMax() = pkCamera->GetFrustumFar();
kFrustum.Update();
SetVisible(TestIntersect(kBox,kFrustum));
//SetVisible(true);
}
//---------------------------------------------------------------------------
void MgcTerrainBlock::SimplifyVertices (MgcTerrainPage* pkPage,
const MgcVector3& rkModelEye, const MgcVector3& rkModelDir,
MgcReal fTolerance, bool bCloseAssumption)
{
unsigned short usSize = pkPage->m_usSize;
unsigned short usOrigin = m_ucX + usSize*m_ucY;
MgcTerrainVertex* pkVOrigin = pkPage->m_akTVertex + usOrigin;
MgcTerrainVertex* pkTVertex;
unsigned short usOffset;
MgcVector3 kDiff;
MgcReal fRSqr, fLenSqr, fDistDir;
// simplify at (stride,0)
if ( m_fDeltaL <= m_fDelta[0] )
{
pkTVertex = pkVOrigin + m_ucStride;
if ( m_fDelta[0] <= m_fDeltaH )
{
// test vertex delta against tolerance
if ( !pkTVertex->GetEnabled() )
{
kDiff.x = rkModelEye.x - pkPage->GetX(m_ucX+m_ucStride);
kDiff.y = rkModelEye.y - pkPage->GetY(m_ucY);
if ( bCloseAssumption )
{
fDistDir = rkModelDir.x*kDiff.x + rkModelDir.y*kDiff.y;
if ( m_fDelta[0] > fTolerance*fDistDir*fDistDir )
pkTVertex->Enable();
}
else // distant assumption
{
kDiff.z = rkModelEye.z -
pkPage->GetHeight(usOrigin+m_ucStride);
fRSqr = kDiff.x*kDiff.x + kDiff.y*kDiff.y;
fLenSqr = fRSqr + kDiff.z*kDiff.z;
if ( m_fDelta[0]*fRSqr > fTolerance*fLenSqr*fLenSqr )
pkTVertex->Enable();
}
}
}
else
{
if ( !pkTVertex->GetEnabled() )
pkTVertex->Enable();
}
}
// simplify at (2*stride,stride)
if ( m_fDeltaL <= m_fDelta[1] )
{
usOffset = (usSize+2)*m_ucStride;
pkTVertex = pkVOrigin + usOffset;
if ( m_fDelta[1] <= m_fDeltaH )
{
// test vertex delta against tolerance
if ( !pkTVertex->GetEnabled() )
{
kDiff.x = rkModelEye.x - pkPage->GetX(m_ucX+2*m_ucStride);
kDiff.y = rkModelEye.y - pkPage->GetY(m_ucY+m_ucStride);
if ( bCloseAssumption )
{
fDistDir = rkModelDir.x*kDiff.x + rkModelDir.y*kDiff.y;
if ( m_fDelta[1] > fTolerance*fDistDir*fDistDir )
pkTVertex->Enable();
}
else // distant assumption
{
kDiff.z = rkModelEye.z -
pkPage->GetHeight(usOrigin+usOffset);
fRSqr = kDiff.x*kDiff.x + kDiff.y*kDiff.y;
fLenSqr = fRSqr + kDiff.z*kDiff.z;
if ( m_fDelta[1]*fRSqr > fTolerance*fLenSqr*fLenSqr )
pkTVertex->Enable();
}
}
}
else
{
if ( !pkTVertex->GetEnabled() )
{
pkTVertex->Enable();
}
}
}
// simplify at (stride,2*stride)
if ( m_fDeltaL <= m_fDelta[2] )
{
usOffset = (2*usSize+1)*m_ucStride;
pkTVertex = pkVOrigin + usOffset;
if ( m_fDelta[2] <= m_fDeltaH )
{
// test vertex delta against tolerance
if ( !pkTVertex->GetEnabled() )
{
kDiff.x = rkModelEye.x - pkPage->GetX(m_ucX+m_ucStride);
kDiff.y = rkModelEye.y - pkPage->GetY(m_ucY+2*m_ucStride);
if ( bCloseAssumption )
{
fDistDir = rkModelDir.x*kDiff.x + rkModelDir.y*kDiff.y;
if ( m_fDelta[2] > fTolerance*fDistDir*fDistDir )
pkTVertex->Enable();
}
else // distant assumption
{
kDiff.z = rkModelEye.z -
pkPage->GetHeight(usOrigin+usOffset);
fRSqr = kDiff.x*kDiff.x + kDiff.y*kDiff.y;
fLenSqr = fRSqr + kDiff.z*kDiff.z;
if ( m_fDelta[2]*fRSqr > fTolerance*fLenSqr*fLenSqr )
pkTVertex->Enable();
}
}
}
else
{
if ( !pkTVertex->GetEnabled() )
pkTVertex->Enable();
}
}
// simplify at (0,stride)
if ( m_fDeltaL <= m_fDelta[3] )
{
usOffset = usSize*m_ucStride;
pkTVertex = pkVOrigin + usOffset;
if ( m_fDelta[3] <= m_fDeltaH )
{
// test vertex delta against tolerance
if ( !pkTVertex->GetEnabled() )
{
kDiff.x = rkModelEye.x - pkPage->GetX(m_ucX);
kDiff.y = rkModelEye.y - pkPage->GetY(m_ucY+m_ucStride);
if ( bCloseAssumption )
{
fDistDir = rkModelDir.x*kDiff.x + rkModelDir.y*kDiff.y;
if ( m_fDelta[3] > fTolerance*fDistDir*fDistDir )
pkTVertex->Enable();
}
else // distant terrain assumption
{
kDiff.z = rkModelEye.z -
pkPage->GetHeight(usOrigin+usOffset);
fRSqr = kDiff.x*kDiff.x + kDiff.y*kDiff.y;
fLenSqr = fRSqr + kDiff.z*kDiff.z;
if ( m_fDelta[3]*fRSqr > fTolerance*fLenSqr*fLenSqr )
pkTVertex->Enable();
}
}
}
else
{
if ( !pkTVertex->GetEnabled() )
pkTVertex->Enable();
}
}
// simplify at (stride,stride)
if ( m_fDeltaL <= m_fDelta[4] )
{
usOffset = (usSize+1)*m_ucStride;
pkTVertex = pkVOrigin + usOffset;
if ( m_fDelta[4] <= m_fDeltaH )
{
// test vertex delta against tolerance
if ( !pkTVertex->GetEnabled() )
{
kDiff.x = rkModelEye.x - pkPage->GetX(m_ucX+m_ucStride);
kDiff.y = rkModelEye.y - pkPage->GetY(m_ucY+m_ucStride);
if ( bCloseAssumption )
{
fDistDir = rkModelDir.x*kDiff.x + rkModelDir.y*kDiff.y;
if ( m_fDelta[4] > fTolerance*fDistDir*fDistDir )
pkTVertex->Enable();
}
else // distant terrain assumption
{
kDiff.z = rkModelEye.z -
pkPage->GetHeight(usOrigin+usOffset);
fRSqr = kDiff.x*kDiff.x + kDiff.y*kDiff.y;
fLenSqr = fRSqr + kDiff.z*kDiff.z;
if ( m_fDelta[4]*fRSqr > fTolerance*fLenSqr*fLenSqr )
pkTVertex->Enable();
}
}
}
else
{
if ( !pkTVertex->GetEnabled() )
pkTVertex->Enable();
}
}
// enable the corner vertices
if ( GetEven() )
{
pkTVertex = pkVOrigin + 2*m_ucStride;
if ( !pkTVertex->GetEnabled() )
pkTVertex->Enable();
pkTVertex = pkVOrigin + 2*usSize*m_ucStride;
if ( !pkTVertex->GetEnabled() )
pkTVertex->Enable();
}
else
{
pkTVertex = pkVOrigin;
if ( !pkTVertex->GetEnabled() )
pkTVertex->Enable();
pkTVertex = pkVOrigin + 2*(usSize+1)*m_ucStride;
if ( !pkTVertex->GetEnabled() )
pkTVertex->Enable();
}
}
//---------------------------------------------------------------------------
void MgcTerrainBlock::Disable (MgcTerrainPage* pkPage)
{
MgcTerrainVertex* akTVertex[9];
GetVertex9(pkPage->m_usSize,pkPage->m_akTVertex,akTVertex);
for (int i = 0; i < 9; i++)
{
if ( akTVertex[i]->GetEnabled() )
akTVertex[i]->Disable();
}
}
//---------------------------------------------------------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -