namespace TGS {
namespace COL {
template <typename TYPE, int DIM>
TgBOOL F_Axis_Seperation( PC_(AXIS_RESULT,DIM) ptgAxS, CR_(STRI,DIM) tgST0, CR_(BOX,DIM) tgBX0 )
{
TYPE tyMinBox, tyMaxBox, tyMinTri, tyMaxTri;
tyMinTri = MATH::F_DOT(tgST0.Query_Origin(),tgST0.Query_Normal());
tgBX0.Project( &tyMinBox, &tyMaxBox, tgST0.Query_Normal() );
if (tyMaxBox < tyMinTri || tyMinBox > tyMinTri)
{
return (TgFALSE);
};
ptgAxS->m_tvNormal = tgST0.Query_Normal();
ptgAxS->m_tyDepth = tyMinTri - tyMinBox;
ptgAxS->m_iAxis = 1;
TgBOOL bTriIsCoPlanarToFace = TgFALSE;
for (TgUINT iIndex = 0; iIndex < 3; ++iIndex)
{
C_(VECTOR,DIM) &tvAxis = tgBX0.Query_AxisUnit( iIndex );
if (Near_One( MATH::F_DOT( tgST0.Query_Normal(), tvAxis ) ))
{
bTriIsCoPlanarToFace = TgTRUE;
continue;
};
const TYPE tyBO_AU = MATH::F_DOT( tgBX0.Query_Origin(), tvAxis );
tgST0.Project( &tyMinTri, &tyMaxTri, tvAxis );
tyMinBox = tyBO_AU - tgBX0.Query_Extent( iIndex );
tyMaxBox = tyBO_AU + tgBX0.Query_Extent( iIndex );
if (tyMaxBox < tyMinTri || tyMinBox > tyMaxTri)
{
return (TgFALSE);
};
const TYPE tyMinDepth = tyMaxBox - tyMinTri;
const TYPE tyMaxDepth = tyMaxTri - tyMinBox;
C_TgBOOL bNegAxis = tyMinDepth > tyMaxDepth;
if ((bNegAxis ? tyMaxDepth : tyMinDepth) < ptgAxS->m_tyDepth)
{
ptgAxS->m_tvNormal = bNegAxis ? tvAxis : MATH::F_NEG( tvAxis );
ptgAxS->m_tyDepth = (bNegAxis ? tyMaxDepth : tyMinDepth);
ptgAxS->m_iAxis = iIndex + (bNegAxis ? 5 : 2);
};
};
if (!bTriIsCoPlanarToFace)
{
for (TgINT iTriIndex = 0; iTriIndex < 3; ++iTriIndex)
{
for (TgINT iBoxIndex = 0; iBoxIndex < 3; ++iBoxIndex)
{
TYPE tyAxisLen;
T_(VECTOR,DIM) tvAxis;
tyAxisLen = MATH::F_UCX( &tvAxis, tgBX0.Query_AxisUnit( iBoxIndex ), tgST0.Query_Edge( iTriIndex ) );
if (Near_Zero( tyAxisLen ))
{
continue;
};
if (
Near_One( MATH::F_DOT( tgBX0.Query_AxisUnit0(), tvAxis ) ) ||
Near_One( MATH::F_DOT( tgBX0.Query_AxisUnit1(), tvAxis ) ) ||
Near_One( MATH::F_DOT( tgBX0.Query_AxisUnit2(), tvAxis ) ) ||
Near_One( MATH::F_DOT( tgST0.Query_Normal(), tvAxis ) )
) {
continue;
};
tgST0.Project( &tyMinTri, &tyMaxTri, tvAxis );
tgBX0.Project( &tyMinBox, &tyMaxBox, tvAxis );
if (tyMaxBox < tyMinTri || tyMinBox < tyMaxTri)
{
return (TgFALSE);
};
if (!tgST0.Test_Edge( iTriIndex ))
{
continue;
};
const TYPE tyMinDepth = tyMaxBox - tyMinTri;
const TYPE tyMaxDepth = tyMaxTri - tyMinBox;
C_TgBOOL bNegAxis = tyMinDepth > tyMaxDepth;
if ((bNegAxis ? tyMaxDepth : tyMinDepth) < ptgAxS->m_tyDepth)
{
ptgAxS->m_tvNormal = bNegAxis ? tvAxis : MATH::F_NEG( tvAxis );
ptgAxS->m_tyDepth = bNegAxis ? tyMaxDepth : tyMinDepth;
ptgAxS->m_iAxis = iTriIndex * 3 + iBoxIndex + 8;
};
};
};
}
else
{
for (TgINT iTriIndex = 0; iTriIndex < 3; ++iTriIndex)
{
C_(VECTOR,DIM) &tvAxis = tgST0.Query_EdgePlane( iTriIndex ).Query_Normal();
if (
Near_One( MATH::F_DOT( tgBX0.Query_AxisUnit0(), tvAxis ) ) ||
Near_One( MATH::F_DOT( tgBX0.Query_AxisUnit1(), tvAxis ) ) ||
Near_One( MATH::F_DOT( tgBX0.Query_AxisUnit2(), tvAxis ) )
) {
continue;
};
tgST0.Project( &tyMinTri, &tyMaxTri, tvAxis );
tgBX0.Project( &tyMinBox, &tyMaxBox, tvAxis );
if (tyMaxBox < tyMinTri || tyMinBox < tyMaxTri)
{
return (TgFALSE);
};
if (!tgST0.Test_Edge( iTriIndex ))
{
continue;
};
const TYPE tyMinDepth = tyMaxBox - tyMinTri;
const TYPE tyMaxDepth = tyMaxTri - tyMinBox;
C_TgBOOL bNegAxis = tyMinDepth > tyMaxDepth;
if (bNegAxis ? tyMaxDepth : tyMinDepth < ptgAxS->m_tyDepth)
{
ptgAxS->m_tvNormal = bNegAxis ? tvAxis : MATH::F_NEG( tvAxis );
ptgAxS->m_tyDepth = bNegAxis ? tyMaxDepth : tyMinDepth;
ptgAxS->m_iAxis = iTriIndex + 21;
};
};
};
return (TgTRUE);
};
template TgBOOL F_Axis_Seperation( PC_TgF4AXIS_RESULT, CR_TgF4STRI, CR_TgF4BOX );
template <typename TYPE, int DIM>
TgRESULT F_Axis_Seperation( PC_(AXIS_INFO,DIM) ptgNFO, const TYPE tyLimitT, CR_(STRI,DIM) tgST0, CR_(BOX,DIM) tgBX0, CR_(DELTA,DIM) tgDT )
{
typedef TTgAXIS_INFO<TYPE,DIM> TgAXIS_INFO;
T_(AXIS_TEST,DIM) tgAxTest;
TYPE tySkipT = -LIMITS<TYPE>::MAX;
TgINT iResult;
tgAxTest.m_tyLimitT = tyLimitT;
tgAxTest.m_tyMinT = -LIMITS<TYPE>::MAX;
tgAxTest.m_tyMaxT = LIMITS<TYPE>::MAX;
const TYPE tyS0_NM = MATH::F_DOT( tgST0.Query_Origin(), tgST0.Query_Normal() );
tgAxTest.m_tyMin0 = tyS0_NM;
tgAxTest.m_tyMax0 = tyS0_NM;
tgBX0.Project( &tgAxTest.m_tyMin1, &tgAxTest.m_tyMax1, tgST0.Query_Normal() );
tgAxTest.m_tySpeed = MATH::F_DOT( tgDT.m_tvDT, tgST0.Query_Normal() );
iResult = F_Test_Seperating_Axis( &tgAxTest );
switch (iResult) {
case 1:
ptgNFO->m_eSide = (tgAxTest.m_tyMax1 < tgAxTest.m_tyMin0) ? TgAXIS_INFO::NEGATIVE : TgAXIS_INFO::POSITIVE;
ptgNFO->m_tvNormal = tgST0.Query_Normal();
ptgNFO->m_tyMinT = tgAxTest.m_tyMinT;
case 0:
break;
case -1:
return (TgE_NOINTERSECT);
};
TgASSERT( (ptgNFO->m_eSide != TgAXIS_INFO::NEGATIVE) )
TgBOOL bTriIsCoPlanarToFace = TgFALSE;
for (TgUINT iIndex = 0; iIndex < 3; ++iIndex)
{
C_(VECTOR,DIM) &tvAxis = tgBX0.Query_AxisUnit( iIndex );
if (Near_One( MATH::F_DOT(tgST0.Query_Normal(),tvAxis) ))
{
bTriIsCoPlanarToFace = TgTRUE;
continue;
};
const TYPE tyBO_AU = MATH::F_DOT( tgBX0.Query_Origin(), tvAxis );
tgST0.Project( &tgAxTest.m_tyMin0, &tgAxTest.m_tyMax0, tvAxis );
tgAxTest.m_tyMin1 = tyBO_AU - tgBX0.Query_Extent( iIndex );
tgAxTest.m_tyMax1 = tyBO_AU + tgBX0.Query_Extent( iIndex );
tgAxTest.m_tySpeed = MATH::F_DOT( tvAxis, tgDT.m_tvDT );
iResult = F_Test_Seperating_Axis( &tgAxTest );
switch (iResult) {
case 1:
ptgNFO->m_eSide = (tgAxTest.m_tyMax1 < tgAxTest.m_tyMin0) ? TgAXIS_INFO::NEGATIVE : TgAXIS_INFO::POSITIVE;
ptgNFO->m_tvNormal = tvAxis;
ptgNFO->m_tyMinT = tgAxTest.m_tyMinT;
case 0:
break;
case -1:
return (TgE_NOINTERSECT);
};
};
T_(VECTOR,DIM) tvAxis;
if (!bTriIsCoPlanarToFace)
{
for (TgINT iTriIndex = 0; iTriIndex < 3; ++iTriIndex)
{
for (TgINT iBoxIndex = 0; iBoxIndex < 3; ++iBoxIndex)
{
TYPE tyAxisLen;
tyAxisLen = MATH::F_UCX( &tvAxis, tgBX0.Query_AxisUnit( iBoxIndex ), tgST0.Query_Edge( iTriIndex ) );
if (Near_Zero( tyAxisLen ))
{
continue;
};
if (
Near_One( MATH::F_DOT( tgBX0.Query_AxisUnit0(), tvAxis ) ) ||
Near_One( MATH::F_DOT( tgBX0.Query_AxisUnit1(), tvAxis ) ) ||
Near_One( MATH::F_DOT( tgBX0.Query_AxisUnit2(), tvAxis ) ) ||
Near_One( MATH::F_DOT( tgST0.Query_Normal(), tvAxis ) )
) {
continue;
};
tgST0.Project( &tgAxTest.m_tyMin0, &tgAxTest.m_tyMax0, tvAxis );
tgBX0.Project( &tgAxTest.m_tyMin1, &tgAxTest.m_tyMax1, tvAxis );
tgAxTest.m_tySpeed = MATH::F_DOT(tvAxis,tgDT.m_tvDT);
iResult = F_Test_Seperating_Axis( &tgAxTest );
switch (iResult) {
case 1:
if (!tgST0.Test_Edge( iTriIndex )) {
tySkipT = tySkipT > tgAxTest.m_tyMinT ? tySkipT : tgAxTest.m_tyMinT;
break;
};
ptgNFO->m_eSide = (tgAxTest.m_tyMax1 < tgAxTest.m_tyMin0) ? TgAXIS_INFO::NEGATIVE : TgAXIS_INFO::POSITIVE;
ptgNFO->m_tvNormal = tvAxis;
ptgNFO->m_tyMinT = tgAxTest.m_tyMinT;
case 0:
break;
case -1:
return (TgE_NOINTERSECT);
};
};
};
}
else
{
for (TgINT iTriIndex = 0; iTriIndex < 3; ++iTriIndex)
{
tvAxis = tgST0.Query_EdgePlane(iTriIndex).Query_Normal();
if (
Near_One( MATH::F_DOT( tgBX0.Query_AxisUnit0(), tvAxis ) ) ||
Near_One( MATH::F_DOT( tgBX0.Query_AxisUnit1(), tvAxis ) ) ||
Near_One( MATH::F_DOT( tgBX0.Query_AxisUnit2(), tvAxis ) )
) {
continue;
};
tgST0.Project( &tgAxTest.m_tyMin0, &tgAxTest.m_tyMax0, tvAxis );
tgBX0.Project( &tgAxTest.m_tyMin1, &tgAxTest.m_tyMax1, tvAxis );
tgAxTest.m_tySpeed = MATH::F_DOT(tvAxis,tgDT.m_tvDT);
iResult = F_Test_Seperating_Axis( &tgAxTest );
switch (iResult) {
case 1:
if (!tgST0.Test_Edge( iTriIndex )) {
tySkipT = tySkipT > tgAxTest.m_tyMinT ? tySkipT : tgAxTest.m_tyMinT;
break;
};
ptgNFO->m_eSide = (tgAxTest.m_tyMax1 < tgAxTest.m_tyMin0) ? TgAXIS_INFO::NEGATIVE : TgAXIS_INFO::POSITIVE;
ptgNFO->m_tvNormal = tvAxis;
ptgNFO->m_tyMinT = tgAxTest.m_tyMinT;
case 0:
break;
case -1:
return (TgE_NOINTERSECT);
};
};
};
for (TgINT iBoxIndex = 0; iBoxIndex < 3; ++iBoxIndex)
{
TYPE tyAxisLen;
T_(VECTOR,DIM) tvAxis;
tyAxisLen = MATH::F_UCX( &tvAxis, tgDT.m_tvDT, tgBX0.Query_AxisUnit( iBoxIndex ) );
if (Near_Zero( tyAxisLen ))
{
continue;
};
if (
Near_One( MATH::F_DOT(tgBX0.Query_AxisUnit0(),tvAxis) ) ||
Near_One( MATH::F_DOT(tgBX0.Query_AxisUnit1(),tvAxis) ) ||
Near_One( MATH::F_DOT(tgBX0.Query_AxisUnit2(),tvAxis) ) ||
Near_One( MATH::F_DOT(tgST0.Query_Normal(),tvAxis) )
) {
continue;
};
tgST0.Project( &tgAxTest.m_tyMin0, &tgAxTest.m_tyMax0, tvAxis );
tgBX0.Project( &tgAxTest.m_tyMin1, &tgAxTest.m_tyMax1, tvAxis );
tgAxTest.m_tySpeed = MATH::F_DOT(tvAxis,tgDT.m_tvDT);
iResult = F_Test_Seperating_Axis( &tgAxTest );
switch (iResult) {
case 1:
ptgNFO->m_eSide = (tgAxTest.m_tyMax1 < tgAxTest.m_tyMin0) ? TgAXIS_INFO::NEGATIVE : TgAXIS_INFO::POSITIVE;
ptgNFO->m_tvNormal = tvAxis;
ptgNFO->m_tyMinT = tgAxTest.m_tyMinT;
case 0:
break;
case -1:
return (TgE_NOINTERSECT);
};
};
if (tySkipT >= tgAxTest.m_tyMinT)
{
return (TgE_NOINTERSECT);
};
return (TgS_OK);
};
template TgRESULT F_Axis_Seperation( PC_TgF4AXIS_INFO, C_TgFLOAT32, CR_TgF4STRI, CR_TgF4BOX, CR_TgF4DELTA );
template <typename TYPE, int DIM>
TgRESULT F_Contact_Penetrate( PC_(CONTACT_PACKET,DIM) ptgPacket, CR_(STRI,DIM) tgST0, CR_(BOX,DIM) tgBX0 )
{
TgBLOCK_FCN_NOOBJ(ETgFAC_COLLISION, 0, ETgTEST_PENETRATE, (((TgUINT)ETgTRIANGLE<<16)|(TgUINT)ETgBOX))
TgASSERT((TgSIZE)ptgPacket->m_iStride >= sizeof( P_(CONTACT,DIM) ))
TgASSERT(tgST0.Is_Valid() && tgBX0.Is_Valid())
if (0 == ptgPacket->m_niMaxContact || ptgPacket->m_niContact >= ptgPacket->m_niMaxContact || NULL == ptgPacket->m_ptgContact)
{
return (TgE_FAIL);
};
if (MATH::F_DOT( tgST0.Query_Normal(), MATH::F_SUB( tgBX0.Query_Origin(), tgST0.Query_Origin() )) < TYPE(0.0))
{
return (TgE_NOINTERSECT);
};
TTgAXIS_RESULT<TYPE,DIM> tgAxS;
if (!F_Axis_Seperation( &tgAxS, tgST0,tgBX0 ))
{
return (TgE_NOINTERSECT);
};
TgASSERT( Near_One( MATH::F_LSQ(tgAxS.m_tvNormal) ) && tgAxS.m_tyDepth >= TYPE(0.0) )
C_TgINT niContact = ptgPacket->m_niContact;
P_(CONTACT,DIM) ptgContact;
if (tgAxS.m_iAxis == 1 || tgAxS.m_iAxis >= 21)
{
C_TgINT iIdx = tgAxS.m_iAxis - 21;
C_(VECTOR,DIM) tvK0 = MATH::F_NEG( tgST0.Query_EdgePlane( iIdx ).Query_Normal() );
C_(VECTOR,DIM) tvNormal = iIdx >= 0 ? tvK0 : tgST0.Query_Normal();
for (TgINT iVert = 0; iVert < 3; ++iVert)
{
if (!tgST0.Test_Point( iVert ))
{
continue;
};
C_(VECTOR,DIM) &tvVert = tgST0.Query_Point( iVert );
if (!tgBX0.Is_Contained( tvVert ))
{
continue;
};
if (ptgPacket->m_niContact >= ptgPacket->m_niMaxContact)
{
return (TgS_MAXCONTACTS);
};
ptgContact = (P_(CONTACT,DIM))((PC_TgUINT08)ptgPacket->m_ptgContact + ptgPacket->m_niContact*ptgPacket->m_iStride);
TYPE tyT0, tyT1;
C_TgRESULT tgResult = TTgCLP_BXLN<TYPE,DIM,1,0>::DO( &tyT0,&tyT1, tgBX0, tvVert,MATH::F_NEG( tvNormal ) );
TgASSERT(P::ABS( tyT0 ) <= LIMITS<TYPE>::EPSILON)
const TYPE tyT = (TgFAILED(tgResult) || tyT1 < TYPE(0.0)) ? TYPE(0.0) : tyT1;
ptgContact->m_tvPos = MATH::F_SUB( tvVert, MATH::F_MUL( tyT, tvNormal ) );
ptgContact->m_tvNormal = tvNormal;
ptgContact->m_tyT0 = TYPE(0.0);
ptgContact->m_tyDepth = tyT;
++ptgPacket->m_niContact;
TgFEBUG_COLLISION_TRIANGLE( iDBG_TriID, ETgFEBUG_COLLISION_COLLIDED );
};
for (TgINT iFlag = 0; iFlag < 8; ++iFlag)
{
const TYPE tyE0 = 0 != (iFlag & 1) ? tgBX0.Query_Extent0() : -tgBX0.Query_Extent0();
const TYPE tyE1 = 0 != (iFlag & 2) ? tgBX0.Query_Extent1() : -tgBX0.Query_Extent1();
const TYPE tyE2 = 0 != (iFlag & 4) ? tgBX0.Query_Extent2() : -tgBX0.Query_Extent2();
T_(VECTOR,DIM) tvCS;
tvCS = tgBX0.Calc_Point( tyE0,tyE1,tyE2 );
const TYPE tyDistN = MATH::F_DOT( MATH::F_SUB( tvCS, tgST0.Query_Origin() ), tgST0.Query_Normal() );
if (tyDistN >= TYPE(0.0))
{
continue;
};
TYPE tyDist[3];
tyDist[0] = F_Dist( tgST0.Query_EdgePlane0(), tvCS );
tyDist[1] = F_Dist( tgST0.Query_EdgePlane1(), tvCS );
tyDist[2] = F_Dist( tgST0.Query_EdgePlane2(), tvCS );
if (tyDist[0] >= -LIMITS<TYPE>::EPSILON && tyDist[1] >= -LIMITS<TYPE>::EPSILON && tyDist[2] >= -LIMITS<TYPE>::EPSILON)
{
if (ptgPacket->m_niContact >= ptgPacket->m_niMaxContact)
{
return (TgS_MAXCONTACTS);
};
ptgContact = (P_(CONTACT,DIM))((PC_TgUINT08)ptgPacket->m_ptgContact + ptgPacket->m_niContact*ptgPacket->m_iStride);
ptgContact->m_tvPos = tvCS;
ptgContact->m_tyT0 = TYPE(0.0);
if (tgAxS.m_iAxis >= 21)
{
TYPE tyT0, tyT1;
TgINT iCode = 0;
C_TgRESULT tgResult = TTgCLF_STLN<TYPE,DIM,1,0>::DO( &tyT0,&tyT1, &iCode, tgST0, tvCS,tvNormal );
TgASSERT(P::ABS( tyT0 ) <= LIMITS<TYPE>::EPSILON)
ptgContact->m_tyDepth = (TgFAILED(tgResult) || 3 != (iCode & 3) || tyT1 < TYPE(0.0)) ? TYPE(0.0) : tyT1;
}
else
{
ptgContact->m_tyDepth = -tyDistN;
};
ptgContact->m_tvNormal = tvNormal;
++ptgPacket->m_niContact;
TgFEBUG_COLLISION_TRIANGLE( iDBG_TriID, ETgFEBUG_COLLISION_COLLIDED );
continue;
};
for (TgINT iAxis = 0; iAxis < 3; ++iAxis)
{
C_(VECTOR,DIM) tvK0 = tgST0.Query_EdgePlane0().Query_Normal();
C_(VECTOR,DIM) tvK1 = tgST0.Query_EdgePlane1().Query_Normal();
C_(VECTOR,DIM) tvK2 = tgST0.Query_EdgePlane2().Query_Normal();
const TYPE tyBX_EN0 = MATH::F_DOT( tvK0, tgBX0.Query_AxisUnit( iAxis ) );
const TYPE tyBX_EN1 = MATH::F_DOT( tvK1, tgBX0.Query_AxisUnit( iAxis ) );
const TYPE tyBX_EN2 = MATH::F_DOT( tvK2, tgBX0.Query_AxisUnit( iAxis ) );
TYPE tyBX_EN[3];
T_(VECTOR,DIM) tvS2;
tyBX_EN[0] = 0 == (iFlag & (1<<iAxis)) ? tyBX_EN0 : -tyBX_EN0;
tyBX_EN[1] = 0 == (iFlag & (1<<iAxis)) ? tyBX_EN1 : -tyBX_EN1;
tyBX_EN[2] = 0 == (iFlag & (1<<iAxis)) ? tyBX_EN2 : -tyBX_EN2;
for (TgINT iEdge = 0; iEdge < 3; ++iEdge)
{
if (!tgST0.Test_Edge(iEdge) || P::ABS( tyBX_EN[iEdge] ))
{
continue;
};
const TYPE tyInt = -tyDist[iEdge] / tyBX_EN[iEdge];
if (tyInt < TYPE(0.0) || tyInt > TYPE(2.0)*tgBX0.Query_Extent( iAxis ))
{
continue;
};
const TYPE tyK0 = 0 == (iFlag & (1<<iAxis)) ? tyInt : -tyInt;
tvS2 = MATH::F_ADD( tvCS, MATH::F_MUL( tgBX0.Query_AxisUnit( iAxis ), tyK0 ) );
C_(VECTOR,DIM) tvK3 = MATH::F_SUB( tvS2, tgST0.Query_Origin() );
TYPE tyDepth = -MATH::F_DOT( tvK3, tgST0.Query_Normal() );
if (tyDepth < -LIMITS<TYPE>::EPSILON)
{
continue;
};
if (
(F_Dist( tgST0.Query_EdgePlane( (iEdge+1) % 3 ), tvS2 )) < -LIMITS<TYPE>::EPSILON ||
(F_Dist( tgST0.Query_EdgePlane( (iEdge+2) % 3 ), tvS2 )) < -LIMITS<TYPE>::EPSILON
) {
continue;
};
if (ptgPacket->m_niContact >= ptgPacket->m_niMaxContact)
{
return (TgS_MAXCONTACTS);
};
ptgContact = (P_(CONTACT,DIM))((PC_TgUINT08)ptgPacket->m_ptgContact + ptgPacket->m_niContact*ptgPacket->m_iStride);
ptgContact->m_tvPos = tvS2;
ptgContact->m_tvNormal = tvNormal;
ptgContact->m_tyT0 = TYPE(0.0);
if (iIdx >= 0)
{
if (iIdx != iEdge)
{
TYPE tyT0, tyT1;
TgINT iCode = 0;
C_TgRESULT tgResult = TTgCLF_STLN<TYPE,DIM,1,0>::DO( &tyT0,&tyT1, &iCode, tgST0, tvS2,tvNormal );
TgASSERT(P::ABS( tyT0 ) <= LIMITS<TYPE>::EPSILON)
ptgContact->m_tyDepth = (TgFAILED(tgResult) || 3 != (iCode & 3) || tyT1 < TYPE(0.0)) ? TYPE(0.0) : tyT1;
}
else
{
ptgContact->m_tyDepth = TYPE(0.0);
};
}
else
{
ptgContact->m_tyDepth = tyDepth < TYPE(0.0) ? TYPE(0.0) : tyDepth;
};
++ptgPacket->m_niContact;
TgFEBUG_COLLISION_TRIANGLE( iDBG_TriID, ETgFEBUG_COLLISION_COLLIDED );
};
};
};
return (niContact == ptgPacket->m_niContact ? TgE_NOINTERSECT : TgS_OK);
};
if (tgAxS.m_iAxis >= 8)
{
C_TgINT iTriIdx = (tgAxS.m_iAxis - 8) / 3;
C_TgINT iBoxIdx0 = (tgAxS.m_iAxis - 8) % 3;
TTgSEGMENT<TYPE,DIM> tgBXE, tgCTE;
T_(VECTOR,DIM) tvBXP, tvCTP;
C_TgINT iIdx1 = (iBoxIdx0 + 1) % 3, iIdx2 = (iBoxIdx0 + 1) % 3;
const TYPE tyBX1_N = MATH::F_DOT( tgBX0.Query_AxisUnit( iIdx1 ), tgAxS.m_tvNormal );
const TYPE tyBX2_N = MATH::F_DOT( tgBX0.Query_AxisUnit( iIdx2 ), tgAxS.m_tvNormal );
const TYPE tyK0 = tyBX1_N > TYPE(0.0) ? tgBX0.Query_Extent( iIdx1 ) : -tgBX0.Query_Extent( iIdx1 );
const TYPE tyK1 = tyBX2_N > TYPE(0.0) ? tgBX0.Query_Extent( iIdx2 ) : -tgBX0.Query_Extent( iIdx2 );
C_(VECTOR,DIM) tvK0 = MATH::F_MUL( tyK0, tgBX0.Query_AxisUnit( iIdx1 ) );
C_(VECTOR,DIM) tvK1 = MATH::F_MUL( tyK1, tgBX0.Query_AxisUnit( iIdx2 ) );
C_(VECTOR,DIM) tvK2 = MATH::F_MUL( tgBX0.Query_Extent( iBoxIdx0 ), tgBX0.Query_AxisUnit( iBoxIdx0 ) );
T_(VECTOR,DIM) tvP0;
tvP0 = MATH::F_ADD( MATH::F_ADD( tvK0, tvK1 ), MATH::F_SUB( tgBX0.Query_Origin(), tvK2 ) );
tgBXE.Set_Origin( tvP0 );
tgBXE.Set_DirN( MATH::F_MUL( TYPE(2.0)*tgBX0.Query_Extent( iBoxIdx0 ), tgBX0.Query_AxisUnit( iBoxIdx0 ) ) );
tgCTE.Set_Origin( tgST0.Query_Point( iTriIdx ) );
tgCTE.Set_DirN( tgST0.Query_Edge( iTriIdx ) );
const TYPE tyDistSq = F_ClosestSq( &tvBXP,&tvCTP, tgBXE,tgCTE );
ptgContact = (P_(CONTACT,DIM))((PC_TgUINT08)ptgPacket->m_ptgContact + ptgPacket->m_niContact*ptgPacket->m_iStride);
ptgContact->m_tvPos = tvBXP;
ptgContact->m_tvNormal = tgAxS.m_tvNormal;
ptgContact->m_tyT0 = TYPE(0.0);
ptgContact->m_tyDepth = P::SQRT( tyDistSq );
TgASSERT(Near_Zero( tyDistSq - tgAxS.m_tyDepth*tgAxS.m_tyDepth ));
TgASSERT(MATH::F_DOT( tgAxS.m_tvNormal, MATH::F_SUB( tvBXP, tvCTP ) ) < TYPE(0.0));
++ptgPacket->m_niContact;
TgFEBUG_COLLISION_TRIANGLE( iDBG_TriID, ETgFEBUG_COLLISION_COLLIDED );
return (TgS_OK);
}
TgASSERT(tgAxS.m_iAxis > 1)
const TYPE tyAX_NM = MATH::F_DOT(tgAxS.m_tvNormal,tgST0.Query_Normal());
if (!Near_Zero( tyAX_NM ))
{
for (TgINT iFlag = 0; iFlag < 8; ++iFlag)
{
const TYPE tyE0 = 0 != (iFlag & 1) ? tgBX0.Query_Extent0() : -tgBX0.Query_Extent0();
const TYPE tyE1 = 0 != (iFlag & 2) ? tgBX0.Query_Extent1() : -tgBX0.Query_Extent1();
const TYPE tyE2 = 0 != (iFlag & 4) ? tgBX0.Query_Extent2() : -tgBX0.Query_Extent2();
T_(VECTOR,DIM) tvCS;
tvCS = tgBX0.Calc_Point( tyE0,tyE1,tyE2 );
C_(VECTOR,DIM) tvK0 = MATH::F_SUB( tvCS, tgST0.Query_Origin() );
const TYPE tyDistN = MATH::F_DOT( tvK0, tgST0.Query_Normal() );
if (tyDistN >= TYPE(0.0))
{
continue;
};
const TYPE tyDepth = P::ABS(tyDistN / tyAX_NM);
C_(VECTOR,DIM) tvK1 = MATH::F_MUL( tyAX_NM ? tyDepth : -tyDepth, tgAxS.m_tvNormal );
C_(VECTOR,DIM) tvP0 = MATH::F_ADD( tvCS, tvK1 );
if (!tgST0.Is_Contained( tvP0 ))
{
continue;
};
if (ptgPacket->m_niContact >= ptgPacket->m_niMaxContact)
{
return (TgS_MAXCONTACTS);
};
ptgContact = (P_(CONTACT,DIM))((PC_TgUINT08)ptgPacket->m_ptgContact + ptgPacket->m_niContact*ptgPacket->m_iStride);
ptgContact->m_tvPos = tvCS;
ptgContact->m_tvNormal = tgAxS.m_tvNormal;
ptgContact->m_tyT0 = TYPE(0.0);
ptgContact->m_tyDepth = tyDepth;
++ptgPacket->m_niContact;
TgFEBUG_COLLISION_TRIANGLE( iDBG_TriID, ETgFEBUG_COLLISION_COLLIDED );
};
};
TgASSERT(!Near_One( MATH::F_DOT(tgAxS.m_tvNormal,tgST0.Query_Normal()) ))
TTgCLIP_LIST<TYPE,DIM> tgClipList;
C_TgINT iFlag = ~(1 << (tgAxS.m_iAxis - 2));
C_TgRESULT tgResult = F_Clip( &tgClipList, tgBX0, iFlag, tgST0.Query_PT() );
TgASSERT(TgSUCCEEDED(tgResult))
const TYPE tyExtent = tgBX0.Query_Extent( (tgAxS.m_iAxis - 2) % 3 );
TYPE tyRadSq;
tyRadSq = tgBX0.Query_Extent0()*tgBX0.Query_Extent0();
tyRadSq += tgBX0.Query_Extent1()*tgBX0.Query_Extent1();
tyRadSq += tgBX0.Query_Extent2()*tgBX0.Query_Extent2();
for (TgINT iResult = 0; iResult < tgClipList.m_niPoint; iResult++)
{
C_(VECTOR,DIM) tvRelPoint = MATH::F_SUB( tgClipList.m_ptvPoint[iResult], tgBX0.Query_Origin() );
if (!Near_Zero( MATH::F_LSQ( tvRelPoint ) - tyRadSq ))
{
if (!tgST0.Test_Edge0() && F_Dist( tgST0.Query_EdgePlane0(), tgClipList.m_ptvPoint[iResult] ) < ptgPacket->m_tySnapTol)
{
continue;
};
if (!tgST0.Test_Edge1() && F_Dist( tgST0.Query_EdgePlane1(), tgClipList.m_ptvPoint[iResult] ) < ptgPacket->m_tySnapTol)
{
continue;
};
if (!tgST0.Test_Edge2() && F_Dist( tgST0.Query_EdgePlane2(), tgClipList.m_ptvPoint[iResult] ) < ptgPacket->m_tySnapTol)
{
continue;
};
};
if (ptgPacket->m_niContact >= ptgPacket->m_niMaxContact)
{
return (TgS_MAXCONTACTS);
};
ptgContact = (P_(CONTACT,DIM))((PC_TgUINT08)ptgPacket->m_ptgContact + ptgPacket->m_niContact*ptgPacket->m_iStride);
const TYPE tyDepth = tyExtent + MATH::F_DOT(tvRelPoint,tgAxS.m_tvNormal);
ptgContact->m_tvPos = MATH::F_SUB( tgClipList.m_ptvPoint[iResult], MATH::F_MUL( tyDepth, tgAxS.m_tvNormal ) );
ptgContact->m_tvNormal = tgAxS.m_tvNormal;
ptgContact->m_tyT0 = TYPE(0.0);
ptgContact->m_tyDepth = tyDepth < TYPE(0.0) ? TYPE(0.0) : tyDepth;
++ptgPacket->m_niContact;
TgFEBUG_COLLISION_TRIANGLE( iDBG_TriID, ETgFEBUG_COLLISION_COLLIDED );
};
return (niContact == ptgPacket->m_niContact ? TgE_NOINTERSECT : TgS_OK);
};
template TgRESULT F_Contact_Penetrate( PC_TgF4CONTACT_PACKET, CR_TgF4STRI, CR_TgF4BOX );
template <typename TYPE, int DIM>
TgRESULT F_Contact_Sweep( PC_(CONTACT_PACKET,DIM) ptgPacket, TYPE *ptyPM, CR_(STRI,DIM) tgST0, CR_(BOX,DIM) tgBX0, CR_(DELTA,DIM) tgDT )
{
TgBLOCK_FCN_NOOBJ(ETgFAC_COLLISION, 0, ETgTEST_SWEEP, (((TgUINT)ETgTRIANGLE<<16)|(TgUINT)ETgBOX))
TgASSERT((TgSIZE)ptgPacket->m_iStride >= sizeof( P_(CONTACT,DIM) ))
TgASSERT(tgST0.Is_Valid() && tgBX0.Is_Valid())
if (0 == ptgPacket->m_niMaxContact || ptgPacket->m_niContact >= ptgPacket->m_niMaxContact || NULL == ptgPacket->m_ptgContact)
{
return (TgE_FAIL);
};
TgFEBUG_COLLISION_TRIANGLE_CREATEID(iDBG_TriID, tgST1, ETgFEBUG_COLLISION_ENTERFCN);
TTgAXIS_INFO<TYPE,DIM> tgNFO;
tgNFO.m_eSide = TTgAXIS_INFO<TYPE,DIM>::UNKNOWN;
tgNFO.m_tyMinT = LIMITS<TYPE>::MAX;
C_TgRESULT tgResult = F_Axis_Seperation( &tgNFO, *ptyPM + ptgPacket->m_tySweepTol, tgST0, tgBX0, tgDT );
if (TgFAILED(tgResult))
{
TgASSERT(TgE_NOINTERSECT == tgResult)
return (tgResult);
};
TgASSERT((tgNFO.m_eSide != TTgAXIS_INFO<TYPE,DIM>::UNKNOWN))
if (tgNFO.m_eSide == TTgAXIS_INFO<TYPE,DIM>::PENETRATED || tgNFO.m_tyMinT < TYPE(0.0))
{
if (*ptyPM > ptgPacket->m_tySweepTol)
{
ptgPacket->m_niContact = 0;
};
*ptyPM = TYPE(0.0);
C_TgBOOL bPenetrate = TgTRUE == ptgPacket->m_bReport_Penetration;
if (bPenetrate && (TgS_MAXCONTACTS == F_Contact_Penetrate( ptgPacket, tgST0,tgBX0 )))
{
return (TgE_PREPENETRATION_MAXCONTACTS);
};
return (TgE_PREPENETRATION);
};
if (tgNFO.m_tyMinT > *ptyPM + ptgPacket->m_tySweepTol)
{
return (TgE_NOINTERSECT);
};
C_(VECTOR,DIM) tvOffset = MATH::F_MUL( tgNFO.m_tyMinT, tgDT.m_tvDT );
T_(AXIS_PROJECT,DIM) tgP0, tgP1;
P_(CONTACT,DIM) ptgContact;
F_Axis_ProjInfo( &tgP0, tgNFO.m_tvNormal, tgST0.Query_PT() );
F_Axis_ProjInfo( &tgP1, tgNFO.m_tvNormal, tgBX0 );
C_TgINT niVertD0 = (tgNFO.m_eSide == T_(AXIS_INFO,DIM)::NEGATIVE) ? tgP0.m_niMinDepth : tgP0.m_niMaxDepth;
PC_(VECTOR,DIM) atvVert0 = (tgNFO.m_eSide == T_(AXIS_INFO,DIM)::NEGATIVE) ? tgP0.m_atvMinVert : tgP0.m_atvMaxVert;
C_TgINT niVertD1 = (tgNFO.m_eSide == T_(AXIS_INFO,DIM)::NEGATIVE) ? tgP1.m_niMaxDepth : tgP1.m_niMinDepth;
PC_(VECTOR,DIM) atvVert1 = (tgNFO.m_eSide == T_(AXIS_INFO,DIM)::NEGATIVE) ? tgP1.m_atvMaxVert : tgP1.m_atvMinVert;
C_(VECTOR,DIM) tvK0 = MATH::F_NEG( tgNFO.m_tvNormal );
C_(VECTOR,DIM) tvNormal = (tgNFO.m_eSide == T_(AXIS_INFO,DIM)::NEGATIVE) ? tvK0 : tgNFO.m_tvNormal;
C_TgINT iFeatureID = (tgNFO.m_eSide == T_(AXIS_INFO,DIM)::NEGATIVE) ? tgP0.m_iMinID : tgP0.m_iMaxID;
if (1 == niVertD0)
{
if (((iFeatureID >= 0) & (iFeatureID <= 2)) && !tgST0.Test_Point( iFeatureID ))
{
return (TgE_NOINTERSECT);
};
if (tgNFO.m_tyMinT < *ptyPM - ptgPacket->m_tySweepTol)
{
ptgPacket->m_niContact = 0;
*ptyPM = tgNFO.m_tyMinT;
};
ptgContact = (P_(CONTACT,DIM))((PC_TgUINT08)ptgPacket->m_ptgContact + ptgPacket->m_niContact*ptgPacket->m_iStride);
ptgContact->m_tvPos = atvVert0[0];
ptgContact->m_tvNormal = tvNormal;
ptgContact->m_tyT0 = tgNFO.m_tyMinT;
ptgContact->m_tyDepth = TYPE(0.0);
++ptgPacket->m_niContact;
TgFEBUG_COLLISION_TRIANGLE(iDBG_TriID, ETgFEBUG_COLLISION_COLLIDED);
return (TgS_OK);
};
if (niVertD1 == 1)
{
if (tgNFO.m_tyMinT < *ptyPM - ptgPacket->m_tySweepTol)
{
ptgPacket->m_niContact = 0;
*ptyPM = tgNFO.m_tyMinT;
};
ptgContact = (P_(CONTACT,DIM))((PC_TgUINT08)ptgPacket->m_ptgContact + ptgPacket->m_niContact*ptgPacket->m_iStride);
ptgContact->m_tvPos = MATH::F_ADD( tvOffset, atvVert1[0] );
ptgContact->m_tvNormal = tvNormal;
ptgContact->m_tyT0 = tgNFO.m_tyMinT;
ptgContact->m_tyDepth = TYPE(0.0);
++ptgPacket->m_niContact;
TgFEBUG_COLLISION_TRIANGLE(iDBG_TriID, ETgFEBUG_COLLISION_COLLIDED);
return (TgS_OK);
};
if (niVertD0 == 2 || niVertD1 == 2)
{
if (((0 != (iFeatureID & 4)) & (niVertD0 == 2)) && !tgST0.Test_Edge( iFeatureID - 4 ))
{
return (TgE_NOINTERSECT);
};
T_(VECTOR,DIM) tvRN0 = T_(VECTOR,DIM)::ZERO, tvRN1 = T_(VECTOR,DIM)::ZERO;
TgINT iResult = -1;
T_(SEGMENT,DIM) tgTriE;
TYPE tyT0, tyT1;
tgTriE.Set_DirN( MATH::F_SUB( atvVert0[1], atvVert0[0] ) );
tgTriE.Set_Origin( atvVert0[0] );
if (niVertD1 == 4)
{
T_(RECTANGLE,DIM) tgBoxFace;
tgBoxFace.Set_Origin( MATH::F_ADD( atvVert1[0], tvOffset ) );
tgBoxFace.Set_Edge0( MATH::F_SUB( atvVert1[1], atvVert1[0] ) );
tgBoxFace.Set_Edge1( MATH::F_SUB( atvVert1[2], atvVert1[0] ) );
if (TgSUCCEEDED(F_Clip( &tyT0,&tyT1, tgBoxFace,tgTriE )))
{
tvRN0 = MATH::F_ADD( tgTriE.Query_Origin(), MATH::F_MUL( tyT0, tgTriE.Query_DirN() ) );
tvRN1 = MATH::F_ADD( tgTriE.Query_Origin(), MATH::F_MUL( tyT1, tgTriE.Query_DirN() ) );
iResult = MATH::F_LSQ( MATH::F_SUB( tvRN0, tvRN1 ) ) > LIMITS<TYPE>::ROOTEPSILON ? 2 : 1;
};
}
else
{
T_(SEGMENT,DIM) tgBoxE;
tgBoxE.Set_DirN( MATH::F_SUB( atvVert1[1], atvVert1[0] ) );
tgBoxE.Set_Origin( MATH::F_ADD( tvOffset, atvVert1[0] ) );
if (niVertD0 == 2)
{
iResult = F_Internal_Intersect(
&tvRN0,&tvRN1, tgTriE.Query_Origin(),tgTriE.Query_DirN(), tgBoxE.Query_Origin(),tgBoxE.Query_DirN()
);
}
else
{
TgINT iCode;
C_TgRESULT tgResult = F_ClipF( &tyT0,&tyT1, &iCode, tgST0,tgBoxE );
TgASSERT(TgSUCCEEDED(tgResult))
if (0 == (iCode & 12))
{
return (TgE_NOINTERSECT);
};
const TYPE tyK0 = (0 != (iCode & 4)) ? tyT0 : tyT1;
tvRN0 = MATH::F_ADD( tgBoxE.Query_Origin(), MATH::F_MUL( tyK0, tgBoxE.Query_DirN() ) );
tvRN1 = MATH::F_ADD( tgBoxE.Query_Origin(), MATH::F_MUL( tyT1, tgBoxE.Query_DirN() ) );
iResult = (12 == (iCode & 12)) && MATH::F_LSQ( MATH::F_SUB( tvRN0, tvRN1 ) ) > LIMITS<TYPE>::ROOTEPSILON ? 2 : 1;
};
};
if (tgNFO.m_tyMinT < *ptyPM - ptgPacket->m_tySweepTol)
{
ptgPacket->m_niContact = 0;
*ptyPM = tgNFO.m_tyMinT;
};
switch (iResult) {
case 2:
ptgContact = (P_(CONTACT,DIM))((PC_TgUINT08)ptgPacket->m_ptgContact + ptgPacket->m_niContact*ptgPacket->m_iStride);
ptgContact->m_tvPos = tvRN1;
ptgContact->m_tvNormal = tvNormal;
ptgContact->m_tyT0 = tgNFO.m_tyMinT;
ptgContact->m_tyDepth = TYPE(0.0);
++ptgPacket->m_niContact;
case 1:
if (ptgPacket->m_niContact >= ptgPacket->m_niMaxContact)
{
return (TgS_MAXCONTACTS);
};
ptgContact = (P_(CONTACT,DIM))((PC_TgUINT08)ptgPacket->m_ptgContact + ptgPacket->m_niContact*ptgPacket->m_iStride);
ptgContact->m_tvPos = tvRN0;
ptgContact->m_tvNormal = tvNormal;
ptgContact->m_tyT0 = tgNFO.m_tyMinT;
ptgContact->m_tyDepth = TYPE(0.0);
++ptgPacket->m_niContact;
TgFEBUG_COLLISION_TRIANGLE(iDBG_TriID, ETgFEBUG_COLLISION_COLLIDED);
break;
default:
TgASSERT(TgFALSE);
};
return (iResult > 0 ? TgS_OK : TgE_NOINTERSECT);
};
C_(VECTOR,DIM) tvE0 = MATH::F_SUB( atvVert1[1], atvVert1[0] );
C_(VECTOR,DIM) tvE1 = MATH::F_SUB( atvVert1[2], atvVert1[0] );
const TYPE tyE0_E0 = MATH::F_LSQ( tvE0 );
const TYPE tyE1_E1 = MATH::F_LSQ( tvE1 );
C_(VECTOR,DIM) tvS0 = MATH::F_ADD( atvVert1[0], tvOffset );
TgINT iCode, niPoint = 0;
T_(VECTOR,DIM) atvContact[12];
TYPE tyT0, tyT1;
for (TgINT iVert = 0; iVert < 3; ++iVert)
{
C_(VECTOR,DIM) tvDS = MATH::F_SUB( tgST0.Query_Point( iVert ), tvS0 );
const TYPE tyDS_E0 = MATH::F_DOT(tvDS,tvE0);
const TYPE tyDS_E1 = MATH::F_DOT(tvDS,tvE1);
if (!tgST0.Test_Point( iVert ) || tyDS_E0 < TYPE(0.0) || tyDS_E1 < TYPE(0.0) || tyDS_E0 > tyE0_E0 || tyDS_E1 > tyE1_E1)
{
continue;
};
atvContact[niPoint++] = tgST0.Query_Point( iVert );
};
TTgCLF_STLN<TYPE,DIM,1,1>::DO( &tyT0,&tyT1, &iCode, tgST0, tvS0,tvE0 );
if (0 != (iCode & 4))
{
atvContact[niPoint++] = MATH::F_ADD( tvS0, MATH::F_MUL( tyT0, tvE0 ) );
};
if (0 != (iCode & 8))
{
atvContact[niPoint++] = MATH::F_ADD( tvS0, MATH::F_MUL( tyT1, tvE0 ) );
};
TTgCLF_STLN<TYPE,DIM,1,1>::DO( &tyT0,&tyT1, &iCode, tgST0, tvS0,tvE1 );
if (0 != (iCode & 4))
{
atvContact[niPoint++] = MATH::F_ADD( tvS0, MATH::F_MUL( tyT0, tvE1 ) );
};
if (0 != (iCode & 8))
{
atvContact[niPoint++] = MATH::F_ADD( tvS0, MATH::F_MUL( tyT1, tvE1 ) );
};
TTgCLF_STLN<TYPE,DIM,1,1>::DO( &tyT0,&tyT1, &iCode, tgST0, MATH::F_ADD( tvS0, tvE1 ), tvE0 );
if (0 != (iCode & 4))
{
atvContact[niPoint++] = MATH::F_ADD( MATH::F_ADD( tvS0, tvE1 ), MATH::F_MUL( tyT0, tvE0 ) );
};
if (0 != (iCode & 8))
{
atvContact[niPoint++] = MATH::F_ADD( MATH::F_ADD( tvS0, tvE1 ), MATH::F_MUL( tyT1, tvE0 ) );
};
TTgCLF_STLN<TYPE,DIM,1,1>::DO( &tyT0,&tyT1, &iCode, tgST0, MATH::F_ADD( tvS0, tvE0 ), tvE1 );
if (0 != (iCode & 4))
{
atvContact[niPoint++] = MATH::F_ADD( MATH::F_ADD( tvS0, tvE0 ), MATH::F_MUL( tyT0, tvE1 ) );
};
if (0 != (iCode & 8))
{
atvContact[niPoint++] = MATH::F_ADD( MATH::F_ADD( tvS0, tvE0 ), MATH::F_MUL( tyT1, tvE1 ) );
};
TgASSERT( niPoint > 0 );
if (tgNFO.m_tyMinT < *ptyPM - ptgPacket->m_tySweepTol)
{
ptgPacket->m_niContact = 0;
*ptyPM = tgNFO.m_tyMinT;
};
for (TgINT iIdx = 0; iIdx < niPoint; ++iIdx)
{
TgINT iTest = 0;
for (; iTest < iIdx && !Near_Zero( MATH::F_LSQ( MATH::F_SUB( atvContact[iTest], atvContact[iIdx] ) ) ); ++iTest);
if (iTest != iIdx)
{
continue;
};
if (ptgPacket->m_niContact >= ptgPacket->m_niMaxContact)
{
return (TgS_MAXCONTACTS);
};
ptgContact = (P_(CONTACT,DIM))((PC_TgUINT08)ptgPacket->m_ptgContact + ptgPacket->m_niContact*ptgPacket->m_iStride);
ptgContact->m_tvPos = atvContact[iIdx];
ptgContact->m_tvNormal = tvNormal;
ptgContact->m_tyT0 = tgNFO.m_tyMinT;
ptgContact->m_tyDepth = TYPE(0.0);
++ptgPacket->m_niContact;
};
TgFEBUG_COLLISION_TRIANGLE(iDBG_TriID, ETgFEBUG_COLLISION_COLLIDED);
return (TgS_OK);
};
template TgRESULT F_Contact_Sweep( PC_TgF4CONTACT_PACKET, P_TgFLOAT32, CR_TgF4STRI, CR_TgF4BOX, CR_TgF4DELTA );
};
};