📄 wmlterrainblock.cpp
字号:
fDenom = fRMax + fHMin;
fFMax = (fDenom > 0.0f ? fRMax/(fDenom*fDenom) : Mathf::MAX_REAL);
}
else
{
fFMax = (fHMin > 0.0f ? 0.25f/fHMin : Mathf::MAX_REAL);
}
m_fDeltaL = fTolerance/fFMax;
m_fDeltaH = (fFMin > 0.0f ? fTolerance/fFMin : Mathf::MAX_REAL);
}
else // fTolerance == 0
{
m_fDeltaL = 0.0f;
m_fDeltaH = Mathf::MAX_REAL;
}
}
//----------------------------------------------------------------------------
void TerrainBlock::ComputeInterval (const Vector3f& rkModelEye,
const Vector3f& rkModelDir, float fTolerance, Vector2f& rkLoc,
float fSpacing)
{
// close terrain assumption
if ( fTolerance > 0.0f )
{
// compute fmin and fmax
// temporary quantities
float fLmEx = rkLoc.X() - rkModelEye.X();
float fLmEy = rkLoc.Y() - rkModelEye.Y();
float fTmp = fSpacing*float(m_ucStride);
float fXSum = fLmEx + fTmp;
float fYSum = fLmEy + fTmp;
float fXDif = fLmEx - fTmp;
float fYDif = fLmEy - fTmp;
// find corners of block closest to and farthest from eye
float fFMin = fabsf(rkModelDir.X()*fXDif + rkModelDir.Y()*fYDif);
float fFMax = fFMin;
fTmp = fabsf(rkModelDir.X()*fXSum + rkModelDir.Y()*fYDif);
if ( fTmp >= fFMin )
fFMin = fTmp;
else
fFMax = fTmp;
fTmp = fabsf(rkModelDir.X()*fXSum + rkModelDir.Y()*fYSum);
if ( fTmp >= fFMin )
fFMin = fTmp;
else
fFMax = fTmp;
fTmp = fabsf(rkModelDir.X()*fXDif + rkModelDir.Y()*fYSum);
if ( fTmp >= fFMin )
fFMin = fTmp;
else
fFMax = fTmp;
m_fDeltaL = fTolerance*fFMax;
m_fDeltaH = fTolerance*fFMin;
}
else // fTolerance == 0
{
m_fDeltaL = 0.0f;
m_fDeltaH = Mathf::MAX_REAL;
}
}
//----------------------------------------------------------------------------
void TerrainBlock::TestIntersectFrustum (const TerrainPage* pkPage,
const Camera* pkCamera)
{
SetVisibilityTested(true);
// axis-aligned bounding box of page in terrain model space
Vector3f kMCenter = 0.5f*(m_kMin + m_kMax);
Vector3f kMExtent = 0.5f*(m_kMax - m_kMin);
// transform to world space (parent's coordinate system)
Box3f kWBox;
kWBox.Center() = pkPage->Scale()*(pkPage->Rotate()*kMCenter) +
pkPage->Translate();
int i;
for (i = 0; i < 3; i++)
{
kWBox.Axis(i) = pkPage->Rotate().GetColumn(i);
kWBox.Extent(i) = pkPage->Scale()*kMExtent[i];
}
// inverse transform from world space to camera space
Box3f kCBox;
Vector3f kDiff = kWBox.Center() - pkCamera->GetLocation();
kCBox.Center() = Vector3f(kDiff.Dot(pkCamera->GetLeft()),
kDiff.Dot(pkCamera->GetUp()),kDiff.Dot(pkCamera->GetDirection()));
for (i = 0; i < 3; i++)
{
kCBox.Axis(i) = Vector3f(
pkCamera->GetLeft().Dot(kWBox.Axis(i)),
pkCamera->GetUp().Dot(kWBox.Axis(i)),
pkCamera->GetDirection().Dot(kWBox.Axis(i)));
kCBox.Extent(i) = kWBox.Extent(i);
}
// default frustum matches camera coordinate frame
Frustum3f kFrustum;
kFrustum.LBound() = pkCamera->GetFrustumRight();
kFrustum.UBound() = pkCamera->GetFrustumTop();
kFrustum.DMin() = pkCamera->GetFrustumNear();
kFrustum.DMax() = pkCamera->GetFrustumFar();
kFrustum.Update();
SetVisible(TestIntersection(kCBox,kFrustum));
}
//----------------------------------------------------------------------------
void TerrainBlock::SimplifyVertices (TerrainPage* pkPage,
const Vector3f& rkModelEye, const Vector3f& rkModelDir, float fTolerance,
bool bCloseAssumption)
{
unsigned short usSize = pkPage->m_usSize;
unsigned short usOrigin = m_ucX + usSize*m_ucY;
TerrainVertex* pkVOrigin = pkPage->m_akTVertex + usOrigin;
TerrainVertex* pkTVertex;
unsigned short usOffset;
Vector3f kDiff;
float 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 TerrainBlock::Disable (TerrainPage* pkPage)
{
TerrainVertex* 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 + -