📄 mgcterrainblock.cpp
字号:
fRMax += ( fDxMax >= fDxMin ? fDxMax : fDxMin );
}
else
{
fRMin += fDxMax;
fRMax += fDxMin;
}
if ( rkModelEye.y < m_kMin.y )
{
fRMin += fDyMin;
fRMax += fDyMax;
}
else if ( rkModelEye.y <= m_kMax.y )
{
fRMax += ( fDyMax >= fDyMin ? fDyMax : fDyMin );
}
else
{
fRMin += fDyMax;
fRMax += fDyMin;
}
// compute fmin
MgcReal fDenom = fRMin + fHMax;
MgcReal fFMin =
(fDenom > 0.0 ? fRMin/(fDenom*fDenom) : MgcMath::INFINITY);
fDenom = fRMax + fHMax;
fTmp = (fDenom > 0.0 ? fRMax/(fDenom*fDenom) : MgcMath::INFINITY);
if ( fTmp < fFMin )
fFMin = fTmp;
// compute fmax
MgcReal fFMax;
if ( fRMin >= fHMin )
{
fDenom = fRMin + fHMin;
fFMax =
(fDenom > 0.0 ? fRMin/(fDenom*fDenom) : MgcMath::INFINITY);
}
else if ( fRMax <= fHMin )
{
fDenom = fRMax + fHMin;
fFMax =
(fDenom > 0.0 ? fRMax/(fDenom*fDenom) : MgcMath::INFINITY);
}
else
{
fFMax = (fHMin > 0.0 ? 0.25/fHMin : MgcMath::INFINITY);
}
m_fDeltaL = fTolerance/fFMax;
m_fDeltaH = (fFMin > 0.0 ? fTolerance/fFMin : MgcMath::INFINITY);
}
else // fTolerance == 0.0
{
m_fDeltaL = 0.0;
m_fDeltaH = MgcMath::INFINITY;
}
}
//---------------------------------------------------------------------------
void MgcTerrainBlock::ComputeInterval (const MgcVector3& rkModelEye,
const MgcVector3& rkModelDir, MgcReal fTolerance, MgcVector2& rkLoc,
MgcReal fSpacing)
{
// close terrain assumption
if ( fTolerance > 0.0 )
{
// compute fmin and fmax
// temporary quantities
MgcReal fLmEx = rkLoc.x - rkModelEye.x;
MgcReal fLmEy = rkLoc.y - rkModelEye.y;
MgcReal fTmp = fSpacing*MgcReal(m_ucStride);
MgcReal fXSum = fLmEx + fTmp;
MgcReal fYSum = fLmEy + fTmp;
MgcReal fXDif = fLmEx - fTmp;
MgcReal fYDif = fLmEy - fTmp;
// find corners of block closest to and farthest from eye
MgcReal fFMin = MgcMath::Abs(rkModelDir.x*fXDif + rkModelDir.y*fYDif);
MgcReal fFMax = fFMin;
fTmp = MgcMath::Abs(rkModelDir.x*fXSum + rkModelDir.y*fYDif);
if ( fTmp >= fFMin )
fFMin = fTmp;
else
fFMax = fTmp;
fTmp = MgcMath::Abs(rkModelDir.x*fXSum + rkModelDir.y*fYSum);
if ( fTmp >= fFMin )
fFMin = fTmp;
else
fFMax = fTmp;
fTmp = MgcMath::Abs(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.0
{
m_fDeltaL = 0.0;
m_fDeltaH = MgcMath::INFINITY;
}
}
//---------------------------------------------------------------------------
bool MgcTerrainBlock::TestIntersect (const MgcBox3& rkBox,
const MgcFrustum& rkFrustum)
{
// for convenience
const MgcVector3* akA = rkBox.Axes();
const MgcReal* afE = rkBox.Extents();
MgcVector3 kDiff = rkBox.Center() - rkFrustum.Origin();
MgcReal afA[3], afB[3], afC[3], afD[3];
MgcReal afNA[3], afNB[3], afNC[3], afND[3];
MgcReal afNApLC[3], afNAmLC[3], afNBpUC[3], afNBmUC[3];
MgcReal afLC[3], afLD[3], afUC[3], afUD[3], afLBpUA[3], afLBmUA[3];
MgcReal fDdD, fR, fP, fMin, fMax, fMTwoLF, fMTwoUF, fLB, fUA, fTmp;
int i, j;
// M = D
afD[2] = kDiff.Dot(rkFrustum.DVector());
for (i = 0; i < 3; i++)
afC[i] = akA[i].Dot(rkFrustum.DVector());
fR = afE[0]*MgcMath::Abs(afC[0]) +
afE[1]*MgcMath::Abs(afC[1]) +
afE[2]*MgcMath::Abs(afC[2]);
if ( afD[2] + fR < rkFrustum.DMin() || afD[2] - fR > rkFrustum.DMax() )
return false;
// M = n*L - l*D
for (i = 0; i < 3; i++)
{
afA[i] = akA[i].Dot(rkFrustum.LVector());
afLC[i] = rkFrustum.LBound()*afC[i];
afNA[i] = rkFrustum.DMin()*afA[i];
afNAmLC[i] = afNA[i] - afLC[i];
}
afD[0] = kDiff.Dot(rkFrustum.LVector());
fR = afE[0]*MgcMath::Abs(afNAmLC[0]) +
afE[1]*MgcMath::Abs(afNAmLC[1]) +
afE[2]*MgcMath::Abs(afNAmLC[2]);
afND[0] = rkFrustum.DMin()*afD[0];
afLD[2] = rkFrustum.LBound()*afD[2];
fDdD = afND[0] - afLD[2];
fMTwoLF = rkFrustum.GetMTwoLF();
if ( fDdD + fR < fMTwoLF || fDdD > fR )
return false;
// M = -n*L - l*D
for (i = 0; i < 3; i++)
afNApLC[i] = afNA[i] + afLC[i];
fR = afE[0]*MgcMath::Abs(afNApLC[0]) +
afE[1]*MgcMath::Abs(afNApLC[1]) +
afE[2]*MgcMath::Abs(afNApLC[2]);
fDdD = -(afND[0] + afLD[2]);
if ( fDdD + fR < fMTwoLF || fDdD > fR )
return false;
// M = n*U - u*D
for (i = 0; i < 3; i++)
{
afB[i] = akA[i].Dot(rkFrustum.UVector());
afUC[i] = rkFrustum.UBound()*afC[i];
afNB[i] = rkFrustum.DMin()*afB[i];
afNBmUC[i] = afNB[i] - afUC[i];
}
afD[1] = kDiff.Dot(rkFrustum.UVector());
fR = afE[0]*MgcMath::Abs(afNBmUC[0]) +
afE[1]*MgcMath::Abs(afNBmUC[1]) +
afE[2]*MgcMath::Abs(afNBmUC[2]);
afND[1] = rkFrustum.DMin()*afD[1];
afUD[2] = rkFrustum.UBound()*afD[2];
fDdD = afND[1] - afUD[2];
fMTwoUF = rkFrustum.GetMTwoUF();
if ( fDdD + fR < fMTwoUF || fDdD > fR )
return false;
// M = -n*U - u*D
for (i = 0; i < 3; i++)
afNBpUC[i] = afNB[i] + afUC[i];
fR = afE[0]*MgcMath::Abs(afNBpUC[0]) +
afE[1]*MgcMath::Abs(afNBpUC[1]) +
afE[2]*MgcMath::Abs(afNBpUC[2]);
fDdD = -(afND[1] + afUD[2]);
if ( fDdD + fR < fMTwoUF || fDdD > fR )
return false;
// M = A[i]
for (i = 0; i < 3; i++)
{
fP = rkFrustum.LBound()*MgcMath::Abs(afA[i]) +
rkFrustum.UBound()*MgcMath::Abs(afB[i]);
afNC[i] = rkFrustum.DMin()*afC[i];
fMin = afNC[i] - fP;
if ( fMin < 0.0 )
fMin *= rkFrustum.GetDRatio();
fMax = afNC[i] + fP;
if ( fMax > 0.0 )
fMax *= rkFrustum.GetDRatio();
fDdD = afA[i]*afD[0] + afB[i]*afD[1] + afC[i]*afD[2];
if ( fDdD + afE[i] < fMin || fDdD - afE[i] > fMax )
return false;
}
// M = Cross(L,A[i])
for (i = 0; i < 3; i++)
{
fP = rkFrustum.UBound()*MgcMath::Abs(afC[i]);
fMin = afNB[i] - fP;
if ( fMin < 0.0 )
fMin *= rkFrustum.GetDRatio();
fMax = afNB[i] + fP;
if ( fMax > 0.0 )
fMax *= rkFrustum.GetDRatio();
fDdD = -afC[i]*afD[1] + afB[i]*afD[2];
fR = afE[0]*MgcMath::Abs(afB[i]*afC[0]-afB[0]*afC[i]) +
afE[1]*MgcMath::Abs(afB[i]*afC[1]-afB[1]*afC[i]) +
afE[2]*MgcMath::Abs(afB[i]*afC[2]-afB[2]*afC[i]);
if ( fDdD + fR < fMin || fDdD - fR > fMax )
return false;
}
// M = Cross(U,A[i])
for (i = 0; i < 3; i++)
{
fP = rkFrustum.LBound()*MgcMath::Abs(afC[i]);
fMin = -afNA[i] - fP;
if ( fMin < 0.0 )
fMin *= rkFrustum.GetDRatio();
fMax = -afNA[i] + fP;
if ( fMax > 0.0 )
fMax *= rkFrustum.GetDRatio();
fDdD = afC[i]*afD[0] - afA[i]*afD[2];
fR = afE[0]*MgcMath::Abs(afA[i]*afC[0]-afA[0]*afC[i]) +
afE[1]*MgcMath::Abs(afA[i]*afC[1]-afA[1]*afC[i]) +
afE[2]*MgcMath::Abs(afA[i]*afC[2]-afA[2]*afC[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++)
{
fLB = rkFrustum.LBound()*afB[i];
fUA = rkFrustum.UBound()*afA[i];
afLBpUA[i] = fLB + fUA;
afLBmUA[i] = fLB - fUA;
}
for (i = 0; i < 3; i++)
{
fP = rkFrustum.LBound()*MgcMath::Abs(afNBmUC[i]) +
rkFrustum.UBound()*MgcMath::Abs(afNAmLC[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]*afNBmUC[i] + afD[1]*afNAmLC[i] + afD[2]*afLBmUA[i];
fR = 0.0;
for (j = 0; j < 3; j++)
{
fR += afE[j]*MgcMath::Abs(-afA[j]*afNBmUC[i]+ afB[j]*afNAmLC[i]
+ afC[j]*afLBmUA[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(afNAmLC[i]);
fTmp = rkFrustum.DMin()*afLBpUA[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]*afNAmLC[i] + afD[2]*afLBpUA[i];
fR = 0.0;
for (j = 0; j < 3; j++)
{
fR += afE[j]*MgcMath::Abs(-afA[j]*afNBpUC[i]+ afB[j]*afNAmLC[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(afNBmUC[i]) +
rkFrustum.UBound()*MgcMath::Abs(afNApLC[i]);
fTmp = -rkFrustum.DMin()*afLBpUA[i];
fMin = fTmp - fP;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -