📄 wmlintrbox3box3.cpp
字号:
fR = afAD1[1]*aafC[0][0]-afAD1[0]*aafC[1][0];
if ( fR < -fR01 )
return false;
}
// axis C0+t*A2xB1
fR = afAD0[1]*aafC[0][1]-afAD0[0]*aafC[1][1];
fR0 = afEA[0]*aafAbsC[1][1] + afEA[1]*aafAbsC[0][1];
fR1 = afEB[0]*aafAbsC[2][2] + afEB[2]*aafAbsC[2][0];
fR01 = fR0 + fR1;
if ( fR > fR01 )
{
fR = afAD1[1]*aafC[0][1]-afAD1[0]*aafC[1][1];
if ( fR > fR01 )
return false;
}
else if ( fR < -fR01 )
{
fR = afAD1[1]*aafC[0][1]-afAD1[0]*aafC[1][1];
if ( fR < -fR01 )
return false;
}
// axis C0+t*A2xB2
fR = afAD0[1]*aafC[0][2]-afAD0[0]*aafC[1][2];
fR0 = afEA[0]*aafAbsC[1][2] + afEA[1]*aafAbsC[0][2];
fR1 = afEB[0]*aafAbsC[2][1] + afEB[1]*aafAbsC[2][0];
fR01 = fR0 + fR1;
if ( fR > fR01 )
{
fR = afAD1[1]*aafC[0][2]-afAD1[0]*aafC[1][2];
if ( fR > fR01 )
return false;
}
else if ( fR < -fR01 )
{
fR = afAD1[1]*aafC[0][2]-afAD1[0]*aafC[1][2];
if ( fR < -fR01 )
return false;
}
// At this point none of the 15 axes separate the boxes. It is still
// possible that they are separated as viewed in any plane orthogonal
// to the relative direction of motion W. In the worst case, the two
// projected boxes are hexagons. This requires three separating axis
// tests per box.
Vector3<Real> kWxD0 = kW.Cross(kD0);
Real afWA[3], afWB[3];
// axis C0 + t*WxA0
afWA[1] = kW.Dot(akA[1]);
afWA[2] = kW.Dot(akA[2]);
fR = Math<Real>::FAbs(akA[0].Dot(kWxD0));
fR0 = afEA[1]*Math<Real>::FAbs(afWA[2]) +
afEA[2]*Math<Real>::FAbs(afWA[1]);
fR1 =
afEB[0]*Math<Real>::FAbs(aafC[1][0]*afWA[2] - aafC[2][0]*afWA[1]) +
afEB[1]*Math<Real>::FAbs(aafC[1][1]*afWA[2] - aafC[2][1]*afWA[1]) +
afEB[2]*Math<Real>::FAbs(aafC[1][2]*afWA[2] - aafC[2][2]*afWA[1]);
fR01 = fR0 + fR1;
if ( fR > fR01 )
return false;
// axis C0 + t*WxA1
afWA[0] = kW.Dot(akA[0]);
fR = Math<Real>::FAbs(akA[1].Dot(kWxD0));
fR0 = afEA[2]*Math<Real>::FAbs(afWA[0]) +
afEA[0]*Math<Real>::FAbs(afWA[2]);
fR1 =
afEB[0]*Math<Real>::FAbs(aafC[2][0]*afWA[0] - aafC[0][0]*afWA[2]) +
afEB[1]*Math<Real>::FAbs(aafC[2][1]*afWA[0] - aafC[0][1]*afWA[2]) +
afEB[2]*Math<Real>::FAbs(aafC[2][2]*afWA[0] - aafC[0][2]*afWA[2]);
fR01 = fR0 + fR1;
if ( fR > fR01 )
return false;
// axis C0 + t*WxA2
fR = Math<Real>::FAbs(akA[2].Dot(kWxD0));
fR0 = afEA[0]*Math<Real>::FAbs(afWA[1]) +
afEA[1]*Math<Real>::FAbs(afWA[0]);
fR1 =
afEB[0]*Math<Real>::FAbs(aafC[0][0]*afWA[1] - aafC[1][0]*afWA[0]) +
afEB[1]*Math<Real>::FAbs(aafC[0][1]*afWA[1] - aafC[1][1]*afWA[0]) +
afEB[2]*Math<Real>::FAbs(aafC[0][2]*afWA[1] - aafC[1][2]*afWA[0]);
fR01 = fR0 + fR1;
if ( fR > fR01 )
return false;
// axis C0 + t*WxB0
afWB[1] = kW.Dot(akB[1]);
afWB[2] = kW.Dot(akB[2]);
fR = Math<Real>::FAbs(akB[0].Dot(kWxD0));
fR0 =
afEA[0]*Math<Real>::FAbs(aafC[0][1]*afWB[2] - aafC[0][2]*afWB[1]) +
afEA[1]*Math<Real>::FAbs(aafC[1][1]*afWB[2] - aafC[1][2]*afWB[1]) +
afEA[2]*Math<Real>::FAbs(aafC[2][1]*afWB[2] - aafC[2][2]*afWB[1]);
fR1 = afEB[1]*Math<Real>::FAbs(afWB[2]) +
afEB[2]*Math<Real>::FAbs(afWB[1]);
fR01 = fR0 + fR1;
if ( fR > fR01 )
return false;
// axis C0 + t*WxB1
afWB[0] = kW.Dot(akB[0]);
fR = Math<Real>::FAbs(akB[1].Dot(kWxD0));
fR0 =
afEA[0]*Math<Real>::FAbs(aafC[0][2]*afWB[0] - aafC[0][0]*afWB[2]) +
afEA[1]*Math<Real>::FAbs(aafC[1][2]*afWB[0] - aafC[1][0]*afWB[2]) +
afEA[2]*Math<Real>::FAbs(aafC[2][2]*afWB[0] - aafC[2][0]*afWB[2]);
fR1 = afEB[2]*Math<Real>::FAbs(afWB[0]) +
afEB[0]*Math<Real>::FAbs(afWB[2]);
fR01 = fR0 + fR1;
if ( fR > fR01 )
return false;
// axis C0 + t*WxB2
fR = Math<Real>::FAbs(akB[2].Dot(kWxD0));
fR0 =
afEA[0]*Math<Real>::FAbs(aafC[0][0]*afWB[1] - aafC[0][1]*afWB[0]) +
afEA[1]*Math<Real>::FAbs(aafC[1][0]*afWB[1] - aafC[1][1]*afWB[0]) +
afEA[2]*Math<Real>::FAbs(aafC[2][0]*afWB[1] - aafC[2][1]*afWB[0]);
fR1 = afEB[0]*Math<Real>::FAbs(afWB[1]) +
afEB[1]*Math<Real>::FAbs(afWB[0]);
fR01 = fR0 + fR1;
if ( fR > fR01 )
return false;
return true;
}
//----------------------------------------------------------------------------
template <class Real>
bool Wml::TestIntersection (Real fTime, int iNumSteps,
const Box3<Real>& rkBox0, const Vector3<Real>& rkVel0,
const Vector3<Real>& rkRotCen0, const Vector3<Real>& rkRotAxis0,
const Box3<Real>& rkBox1, const Vector3<Real>& rkVel1,
const Vector3<Real>& rkRotCen1, const Vector3<Real>& rkRotAxis1)
{
// time step for the integration
Real fStep = fTime/Real(iNumSteps);
// initialize subinterval boxes
Box3<Real> kSubBox0, kSubBox1;
kSubBox0.Center() = rkBox0.Center();
kSubBox1.Center() = rkBox1.Center();
int i;
for (i = 0; i < 3; i++)
{
kSubBox0.Axis(i) = rkBox0.Axis(i);
kSubBox1.Axis(i) = rkBox1.Axis(i);
}
// integrate the differential equations using Euler's method
for (int iStep = 1; iStep <= iNumSteps; iStep++)
{
// compute box velocities and test boxes for intersection
Real fSubTime = fStep*Real(iStep);
Vector3<Real> kNewRotCen0 = rkRotCen0 + fSubTime*rkVel0;
Vector3<Real> kNewRotCen1 = rkRotCen1 + fSubTime*rkVel1;
Vector3<Real> kDiff0 = kSubBox0.Center() - kNewRotCen0;
Vector3<Real> kDiff1 = kSubBox1.Center() - kNewRotCen1;
Vector3<Real> kSubVel0 = fStep*(rkVel0 + rkRotAxis0.Cross(kDiff0));
Vector3<Real> kSubVel1 = fStep*(rkVel1 + rkRotAxis1.Cross(kDiff1));
if ( TestIntersection(fStep,kSubBox0,kSubVel0,kSubBox1,kSubVel1) )
return true;
// update the box centers
kSubBox0.Center() = kSubBox0.Center() + kSubVel0;
kSubBox1.Center() = kSubBox1.Center() + kSubVel1;
// update the box axes
for (i = 0; i < 3; i++)
{
kSubBox0.Axis(i) = kSubBox0.Axis(i) +
fStep*rkRotAxis0.Cross(kSubBox0.Axis(i));
kSubBox1.Axis(i) = kSubBox1.Axis(i) +
fStep*rkRotAxis1.Cross(kSubBox1.Axis(i));
}
// Use Gram-Schmidt to orthonormalize the updated axes. NOTE: If
// T/N is small and N is small, you can remove this expensive step
// with the assumption that the updated axes are nearly orthonormal.
Vector3<Real>::Orthonormalize(kSubBox0.Axes());
Vector3<Real>::Orthonormalize(kSubBox1.Axes());
}
// NOTE: If the boxes do not intersect, then the application might
// want to move/rotate the boxes to their new locations. In this case
// you want to return the final values of kSubBox0 and kSubBox1 so that
// the application can set rkBox0 <- kSubBox0 and rkBox1 <- kSubBox1.
// Otherwise, the application would have to solve the differential
// equation again or compute the new box locations using the closed form
// solution for the rigid motion.
return false;
}
//----------------------------------------------------------------------------
template <class Real>
bool Wml::FindIntersection (const Box3<Real>& rkBox0,
const Vector3<Real>& rkVel0, const Box3<Real>& rkBox1,
const Vector3<Real>& rkVel1, Real& rfTFirst, Real fTMax, int& riQuantity,
Vector3<Real>* akP)
{
rfTFirst = (Real)0.0;
Real fTLast = Math<Real>::MAX_REAL;
// relative velocity of box1 relative to box0
Vector3<Real> kVel = rkVel1 - rkVel0;
int i0, i1;
ContactSide eSide = NONE;
ContactConfig<Real> kUC, kVC;
Vector3<Real> kAxis;
// box 0 normals
for (i0 = 0; i0 < 3; i0++)
{
kAxis = rkBox0.Axis(i0);
if ( !BoxAxisFind(kVel,kAxis,rkBox0,rkBox1,rfTFirst,fTLast,fTMax,
eSide,kUC,kVC) )
{
return false;
}
}
// box 1 normals
for (i1 = 0; i1 < 3; i1++)
{
kAxis = rkBox1.Axis(i1);
if ( !BoxAxisFind(kVel,kAxis,rkBox0,rkBox1,rfTFirst,fTLast,fTMax,
eSide,kUC,kVC) )
{
return false;
}
}
// box 0 edges cross box 1 edges
for (i0 = 0; i0 < 3; i0++)
{
for (i1 = 0; i1 < 3; i1++)
{
kAxis = rkBox0.Axis(i0).Cross(rkBox1.Axis(i1));
// Since all axes are unit length (assumed), then can
// just compare against a constant (not relative) epsilon
if ( kAxis.SquaredLength() <= Math<Real>::EPSILON )
{
// Simple separation, axis i0 and i1 are parallel
// If any two axes are parallel, then the only comparisons
// that need to be done are between the faces themselves,
// which have already been done. Therefore, if they haven't
// been separated yet, nothing else will. Quick out.
return true;
}
if ( !BoxAxisFind(kVel,kAxis,rkBox0,rkBox1,rfTFirst,fTLast,
fTMax,eSide,kUC,kVC) )
{
return false;
}
}
}
// velocity cross box 0 edges
for (i0 = 0; i0 < 3; i0++)
{
kAxis = kVel.Cross(rkBox0.Axis(i0));
if ( !BoxAxisFind(kVel,kAxis,rkBox0,rkBox1,rfTFirst,fTLast,fTMax,
eSide,kUC,kVC) )
{
return false;
}
}
// velocity cross box 1 edges
for (i1 = 0; i1 < 3; i1++)
{
kAxis = kVel.Cross(rkBox1.Axis(i1));
if ( !BoxAxisFind(kVel,kAxis,rkBox0,rkBox1,rfTFirst,fTLast,fTMax,
eSide,kUC,kVC) )
{
return false;
}
}
if ( rfTFirst <= (Real)0.0 || eSide == NONE )
return false;
FindContactSet(rkBox0,rkBox1,eSide,kUC,kVC,rkVel0,rkVel1,rfTFirst,
riQuantity,akP);
return true;
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
// explicit instantiation
//----------------------------------------------------------------------------
namespace Wml
{
template WML_ITEM bool TestIntersection<float> (const Box3<float>&,
const Box3<float>&);
template WML_ITEM bool TestIntersection<float> (float,
const Box3<float>&, const Vector3<float>&, const Box3<float>&,
const Vector3<float>&);
template WML_ITEM bool TestIntersection<float> (float, int,
const Box3<float>&, const Vector3<float>&, const Vector3<float>&,
const Vector3<float>&, const Box3<float>&, const Vector3<float>&,
const Vector3<float>&, const Vector3<float>&);
template WML_ITEM bool FindIntersection<float> (
const Box3<float>&, const Vector3<float>&, const Box3<float>&,
const Vector3<float>&, float&, float, int&, Vector3<float>*);
template WML_ITEM bool TestIntersection<double> (const Box3<double>&,
const Box3<double>&);
template WML_ITEM bool TestIntersection<double> (double,
const Box3<double>&, const Vector3<double>&, const Box3<double>&,
const Vector3<double>&);
template WML_ITEM bool TestIntersection<double> (double, int,
const Box3<double>&, const Vector3<double>&, const Vector3<double>&,
const Vector3<double>&, const Box3<double>&, const Vector3<double>&,
const Vector3<double>&, const Vector3<double>&);
template WML_ITEM bool FindIntersection<double> (
const Box3<double>&, const Vector3<double>&, const Box3<double>&,
const Vector3<double>&, double&, double, int&, Vector3<double>*);
}
//----------------------------------------------------------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -