📄 wmlintrtri2tri2.cpp
字号:
else // d1 < d0 < d2
{
m_eMap = M11;
m_aiIndex[0] = 1;
m_aiIndex[1] = 0;
m_aiIndex[2] = 2;
m_fMin = fD1;
m_fMax = fD2;
}
}
}
//----------------------------------------------------------------------------
template <class Real>
bool _Configuration<Real>::NoIntersect (const _Configuration& rkCfg0,
const _Configuration& rkCfg1, Real fTMax, Real fSpeed, int& riSide,
_Configuration& rkTCfg0, _Configuration& rkTCfg1, Real& rfTFirst,
Real& rfTLast)
{
Real fInvSpeed, fT;
if ( rkCfg1.m_fMax < rkCfg0.m_fMin )
{
// V1-interval initially on left of V0-interval
if ( fSpeed <= (Real)0.0 )
return true; // intervals moving apart
// update first time
fInvSpeed = ((Real)1.0)/fSpeed;
fT = (rkCfg0.m_fMin - rkCfg1.m_fMax)*fInvSpeed;
if ( fT > rfTFirst )
{
rfTFirst = fT;
riSide = -1;
rkTCfg0 = rkCfg0;
rkTCfg1 = rkCfg1;
}
// test for exceedance of time interval
if ( rfTFirst > fTMax )
return true;
// update last time
fT = (rkCfg0.m_fMax - rkCfg1.m_fMin)*fInvSpeed;
if ( fT < rfTLast )
rfTLast = fT;
// test for separation
if ( rfTFirst > rfTLast )
return true;
}
else if ( rkCfg0.m_fMax < rkCfg1.m_fMin )
{
// V1-interval initially on right of V0-interval
if ( fSpeed >= (Real)0.0 )
return true; // intervals moving apart
// update first time
fInvSpeed = ((Real)1.0)/fSpeed;
fT = (rkCfg0.m_fMax - rkCfg1.m_fMin)*fInvSpeed;
if ( fT > rfTFirst )
{
rfTFirst = fT;
riSide = 1;
rkTCfg0 = rkCfg0;
rkTCfg1 = rkCfg1;
}
// test for exceedance of time interval
if ( rfTFirst > fTMax )
return true;
// update last time
fT = (rkCfg0.m_fMin - rkCfg1.m_fMax)*fInvSpeed;
if ( fT < rfTLast )
rfTLast = fT;
// test for separation
if ( rfTFirst > rfTLast )
return true;
}
else
{
// V0-interval and V1-interval initially overlap
if ( fSpeed > (Real)0.0 )
{
// update last time
fInvSpeed = ((Real)1.0)/fSpeed;
fT = (rkCfg0.m_fMax - rkCfg1.m_fMin)*fInvSpeed;
if ( fT < rfTLast )
rfTLast = fT;
// test for separation
if ( rfTFirst > rfTLast )
return true;
}
else if ( fSpeed < (Real)0.0 )
{
// update last time
fInvSpeed = ((Real)1.0)/fSpeed;
fT = (rkCfg0.m_fMin - rkCfg1.m_fMax)*fInvSpeed;
if ( fT < rfTLast )
rfTLast = fT;
// test for separation
if ( rfTFirst > rfTLast )
return true;
}
}
return false;
}
//----------------------------------------------------------------------------
template <class Real>
void _Configuration<Real>::GetIntersection (const _Configuration& rkCfg0,
const _Configuration& rkCfg1, int iSide, const Vector2<Real> akV0[3],
const Vector2<Real> akV1[3], int& riQuantity, Vector2<Real> akVertex[6])
{
Vector2<Real> kEdge, kDiff;
const Vector2<Real>* pkOrigin;
Real fInvEdE, fMin, fMax, afInterval[2];
int i;
if ( iSide == 1 ) // V1-interval contacts V0-interval on right
{
if ( rkCfg0.m_eMap == M21 || rkCfg0.m_eMap == M11 )
{
riQuantity = 1;
akVertex[0] = akV0[rkCfg0.m_aiIndex[2]];
}
else if ( rkCfg1.m_eMap == M12 || rkCfg1.m_eMap == M11 )
{
riQuantity = 1;
akVertex[0] = akV1[rkCfg1.m_aiIndex[0]];
}
else // rkCfg0.m_eMap == M12 && rkCfg1.m_eMap == M21 (edge overlap)
{
pkOrigin = &akV0[rkCfg0.m_aiIndex[1]];
kEdge = akV0[rkCfg0.m_aiIndex[2]] - *pkOrigin;
fInvEdE = ((Real)1.0)/kEdge.Dot(kEdge);
kDiff = akV1[rkCfg1.m_aiIndex[1]] - *pkOrigin;
fMin = kEdge.Dot(kDiff)*fInvEdE;
kDiff = akV1[rkCfg1.m_aiIndex[0]] - *pkOrigin;
fMax = kEdge.Dot(kDiff)*fInvEdE;
assert( fMin <= fMax );
riQuantity = FindIntersection((Real)0.0,(Real)1.0,fMin,fMax,
afInterval[0],afInterval[1]);
assert( riQuantity > 0 );
for (i = 0; i < riQuantity; i++)
akVertex[i] = *pkOrigin + afInterval[i]*kEdge;
}
}
else if ( iSide == -1 ) // V1-interval contacts V0-interval on left
{
if ( rkCfg1.m_eMap == M21 || rkCfg1.m_eMap == M11 )
{
riQuantity = 1;
akVertex[0] = akV1[rkCfg1.m_aiIndex[2]];
}
else if ( rkCfg0.m_eMap == M12 || rkCfg0.m_eMap == M11 )
{
riQuantity = 1;
akVertex[0] = akV0[rkCfg0.m_aiIndex[0]];
}
else // rkCfg1.m_eMap == M12 && rkCfg0.m_eMap == M21 (edge overlap)
{
pkOrigin = &akV1[rkCfg1.m_aiIndex[1]];
kEdge = akV1[rkCfg1.m_aiIndex[2]] - *pkOrigin;
fInvEdE = 1.0f/kEdge.Dot(kEdge);
kDiff = akV0[rkCfg0.m_aiIndex[1]] - *pkOrigin;
fMin = kEdge.Dot(kDiff)*fInvEdE;
kDiff = akV0[rkCfg0.m_aiIndex[0]] - *pkOrigin;
fMax = kEdge.Dot(kDiff)*fInvEdE;
assert( fMin <= fMax );
riQuantity = FindIntersection((Real)0.0,(Real)1.0,fMin,fMax,
afInterval[0],afInterval[1]);
assert( riQuantity > 0 );
for (i = 0; i < riQuantity; i++)
akVertex[i] = *pkOrigin + afInterval[i]*kEdge;
}
}
else // triangles were initially intersecting
{
Triangle2<Real> kTri0, kTri1;
kTri0.Origin() = akV0[0];
kTri0.Edge0() = akV0[1] - akV0[0];
kTri0.Edge1() = akV0[2] - akV0[0];
kTri1.Origin() = akV1[0];
kTri1.Edge0() = akV1[1] - akV1[0];
kTri1.Edge1() = akV1[2] - akV1[0];
FindIntersection(kTri0,kTri1,riQuantity,akVertex);
}
}
//----------------------------------------------------------------------------
template <class Real>
bool Wml::TestIntersection (Real fTMax, const Triangle2<Real>& rkTri0,
const Vector2<Real>& rkW0, const Triangle2<Real>& rkTri1,
const Vector2<Real>& rkW1, Real& rfTFirst, Real& rfTLast)
{
Vector2<Real> akV0[3] =
{
rkTri0.Origin(),
rkTri0.Origin() + rkTri0.Edge0(),
rkTri0.Origin() + rkTri0.Edge1()
};
Vector2<Real> akV1[3] =
{
rkTri1.Origin(),
rkTri1.Origin() + rkTri1.Edge0(),
rkTri1.Origin() + rkTri1.Edge1()
};
// process as if V0-triangle is stationary and V1-triangle is moving
Vector2<Real> kW = rkW1 - rkW0;
int iSide = 0; // 0 = NONE, -1 = LEFT, +1 = RIGHT
rfTFirst = (Real)0.0f;
rfTLast = Math<Real>::MAX_REAL;
_Configuration<Real> kCfg0, kCfg1, kTCfg0, kTCfg1;
int iI0, iI1, iI2;
Vector2<Real> kD;
Real fSpeed;
// process edges of V0-triangle
for (iI0 = 1, iI1 = 2, iI2 = 0; iI2 < 3; iI0 = iI1, iI1 = iI2, iI2++)
{
// test axis V0[i1] + t*perp(V0[i2]-V0[i1]), perp(x,y) = (y,-x)
kD.X() = akV0[iI2].Y() - akV0[iI1].Y();
kD.Y() = akV0[iI1].X() - akV0[iI2].X();
fSpeed = kD.Dot(kW);
kCfg0.ComputeTwo(akV0,kD,iI0,iI1,iI2);
kCfg1.ComputeThree(akV1,kD,akV0[iI1]);
if ( _Configuration<Real>::NoIntersect(kCfg0,kCfg1,fTMax,fSpeed,iSide,
kTCfg0,kTCfg1,rfTFirst,rfTLast) )
{
return false;
}
}
// process edges of V1-triangle
for (iI0 = 1, iI1 = 2, iI2 = 0; iI2 < 3; iI0 = iI1, iI1 = iI2, iI2++)
{
// test axis V1[i1] + t*perp(V1[i2]-V1[i1]), perp(x,y) = (y,-x)
kD.X() = akV1[iI2].Y() - akV1[iI1].Y();
kD.Y() = akV1[iI1].X() - akV1[iI2].X();
fSpeed = kD.Dot(kW);
kCfg1.ComputeTwo(akV1,kD,iI0,iI1,iI2);
kCfg0.ComputeThree(akV0,kD,akV1[iI1]);
if ( _Configuration<Real>::NoIntersect(kCfg0,kCfg1,fTMax,fSpeed,iSide,
kTCfg0,kTCfg1,rfTFirst,rfTLast) )
{
return false;
}
}
return true;
}
//----------------------------------------------------------------------------
template <class Real>
bool Wml::FindIntersection (Real fTMax, const Triangle2<Real>& rkTri0,
const Vector2<Real>& rkW0, const Triangle2<Real>& rkTri1,
const Vector2<Real>& rkW1, Real& rfTFirst, Real& rfTLast,
int& riQuantity, Vector2<Real> akVertex[6])
{
Vector2<Real> akV0[3] =
{
rkTri0.Origin(),
rkTri0.Origin() + rkTri0.Edge0(),
rkTri0.Origin() + rkTri0.Edge1()
};
Vector2<Real> akV1[3] =
{
rkTri1.Origin(),
rkTri1.Origin() + rkTri1.Edge0(),
rkTri1.Origin() + rkTri1.Edge1()
};
// process as if V0-triangle is stationary and V1-triangle is moving
Vector2<Real> kW = rkW1 - rkW0;
int iSide = 0; // 0 = NONE, -1 = LEFT, +1 = RIGHT
rfTFirst = (Real)0.0f;
rfTLast = Math<Real>::MAX_REAL;
_Configuration<Real> kCfg0, kCfg1, kTCfg0, kTCfg1;
int iI0, iI1, iI2;
Vector2<Real> kD;
Real fSpeed;
// process edges of V0-triangle
for (iI0 = 1, iI1 = 2, iI2 = 0; iI2 < 3; iI0 = iI1, iI1 = iI2, iI2++)
{
// test axis V0[i1] + t*perp(V0[i2]-V0[i1]), perp(x,y) = (y,-x)
kD.X() = akV0[iI2].Y() - akV0[iI1].Y();
kD.Y() = akV0[iI1].X() - akV0[iI2].X();
fSpeed = kD.Dot(kW);
kCfg0.ComputeTwo(akV0,kD,iI0,iI1,iI2);
kCfg1.ComputeThree(akV1,kD,akV0[iI1]);
if ( _Configuration<Real>::NoIntersect(kCfg0,kCfg1,fTMax,fSpeed,iSide,
kTCfg0,kTCfg1,rfTFirst,rfTLast) )
{
return false;
}
}
// process edges of V1-triangle
for (iI0 = 1, iI1 = 2, iI2 = 0; iI2 < 3; iI0 = iI1, iI1 = iI2, iI2++)
{
// test axis V1[i1] + t*perp(V1[i2]-V1[i1]), perp(x,y) = (y,-x)
kD.X() = akV1[iI2].Y() - akV1[iI1].Y();
kD.Y() = akV1[iI1].X() - akV1[iI2].X();
fSpeed = kD.Dot(kW);
kCfg1.ComputeTwo(akV1,kD,iI0,iI1,iI2);
kCfg0.ComputeThree(akV0,kD,akV1[iI1]);
if ( _Configuration<Real>::NoIntersect(kCfg0,kCfg1,fTMax,fSpeed,iSide,
kTCfg0,kTCfg1,rfTFirst,rfTLast) )
{
return false;
}
}
// move triangles to first contact
Vector2<Real> akMoveV0[3], akMoveV1[3];
for (int i = 0; i < 3; i++)
{
akMoveV0[i] = akV0[i] + rfTFirst*rkW0;
akMoveV1[i] = akV1[i] + rfTFirst*rkW1;
};
_Configuration<Real>::GetIntersection(kTCfg0,kTCfg1,iSide,akMoveV0,
akMoveV1,riQuantity,akVertex);
return riQuantity > 0;
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
// explicit instantiation
//----------------------------------------------------------------------------
namespace Wml
{
template WML_ITEM bool TestIntersection<float> (
const Triangle2<float>&, const Triangle2<float>&);
template WML_ITEM bool FindIntersection<float> (
const Triangle2<float>&, const Triangle2<float>&, int&,
Vector2<float>[6]);
template WML_ITEM bool TestIntersection<float> (float,
const Triangle2<float>&, const Vector2<float>&,
const Triangle2<float>&, const Vector2<float>&, float&, float&);
template WML_ITEM bool FindIntersection<float> (float,
const Triangle2<float>&, const Vector2<float>&,
const Triangle2<float>&, const Vector2<float>&, float&, float&, int&,
Vector2<float>[6]);
template WML_ITEM bool TestIntersection<double> (
const Triangle2<double>&, const Triangle2<double>&);
template WML_ITEM bool FindIntersection<double> (
const Triangle2<double>&, const Triangle2<double>&, int&,
Vector2<double>[6]);
template WML_ITEM bool TestIntersection<double> (double,
const Triangle2<double>&, const Vector2<double>&,
const Triangle2<double>&, const Vector2<double>&, double&, double&);
template WML_ITEM bool FindIntersection<double> (double,
const Triangle2<double>&, const Vector2<double>&,
const Triangle2<double>&, const Vector2<double>&, double&, double&, int&,
Vector2<double>[6]);
}
//----------------------------------------------------------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -