namespace TGS {
namespace COL {
template <typename TYPE, int DIM>
TYPE F_Closest( TYPE *ptyB0, TYPE *ptyB1, TYPE *ptyB2, PC_(VECTOR,DIM) ptvPN0, CR_(BOX,DIM) tgBX0, CR_(PLANE,DIM) tgPN0 )
{
TgASSERT(tgBX0.Is_Valid() && tgPN0.Is_Valid())
C_(VECTOR,DIM) tvNM = tgPN0.Query_Normal();
TYPE tyDist = F_Dist( tgPN0, tgBX0.Query_Origin() );
const TYPE tyX0_N = MATH::F_DOT(tgBX0.Query_AxisUnit0(),tvNM);
const TYPE tyX1_N = MATH::F_DOT(tgBX0.Query_AxisUnit1(),tvNM);
const TYPE tyX2_N = MATH::F_DOT(tgBX0.Query_AxisUnit2(),tvNM);
*ptyB0 = tyX0_N < -TTgEPSILON ? tgBX0.Query_Extent0() : (tyX0_N > TTgEPSILON ? -tgBX0.Query_Extent0() : TYPE(0.0));
*ptyB1 = tyX1_N < -TTgEPSILON ? tgBX0.Query_Extent1() : (tyX1_N > TTgEPSILON ? -tgBX0.Query_Extent1() : TYPE(0.0));
*ptyB2 = tyX2_N < -TTgEPSILON ? tgBX0.Query_Extent2() : (tyX2_N > TTgEPSILON ? -tgBX0.Query_Extent2() : TYPE(0.0));
tyDist += *ptyB0*tyX0_N + *ptyB1*tyX1_N + *ptyB2*tyX2_N;
*ptvPN0 = MATH::F_SETP<TYPE,DIM>( *ptyB0 - tyDist*tvNM(0), *ptyB1 - tyDist*tvNM(1), *ptyB2 - tyDist*tvNM(2) );
return (P::FSEL( tyDist, tyDist, -LIMITS<TYPE>::MAX ));
};
template TgFLOAT32 F_Closest( P_TgFLOAT32, P_TgFLOAT32, P_TgFLOAT32, PC_TgF4VECTOR, CR_TgF4BOX, CR_TgF4PLANE );
template <typename TYPE, int DIM>
TgRESULT F_Contact_Penetrate( PC_(CONTACT_PACKET,DIM) ptgPacket, CR_(PLANE,DIM) tgPN0, CR_(BOX,DIM) tgBX0 )
{
TgBLOCK_FCN_NOOBJ(ETgFAC_COLLISION, 0, ETgTEST_PENETRATE, (((TgUINT)ETgPLANE<<16)|(TgUINT)ETgBOX))
TgASSERT((TgSIZE)ptgPacket->m_iStride >= sizeof( P_(CONTACT,DIM) ))
TgASSERT(tgBX0.Is_Valid() && tgPN0.Is_Valid())
TgTYPE_PREFIX( TYPE );
TgTYPE_DECLARE( T_(VECTOR,DIM), TgVECTOR );
if (0 == ptgPacket->m_niMaxContact || ptgPacket->m_niContact >= ptgPacket->m_niMaxContact || NULL == ptgPacket->m_ptgContact)
{
return (TgE_FAIL);
};
const TYPE tyDist = F_Dist( tgPN0, tgBX0.Query_Origin() );
C_(VECTOR,DIM) tvE0 = MATH::F_MUL( tgBX0.Query_AxisUnit0(), tgBX0.Query_Extent0() );
C_(VECTOR,DIM) tvE1 = MATH::F_MUL( tgBX0.Query_AxisUnit1(), tgBX0.Query_Extent1() );
C_(VECTOR,DIM) tvE2 = MATH::F_MUL( tgBX0.Query_AxisUnit2(), tgBX0.Query_Extent2() );
const TYPE tyX0_N = MATH::F_DOT( tgPN0.Query_Normal(), tvE0 );
const TYPE tyX1_N = MATH::F_DOT( tgPN0.Query_Normal(), tvE1 );
const TYPE tyX2_N = MATH::F_DOT( tgPN0.Query_Normal(), tvE2 );
const TYPE tyABS_X0_N = P::FSEL( tyX0_N, tyX0_N, -tyX0_N );
const TYPE tyABS_X1_N = P::FSEL( tyX1_N, tyX1_N, -tyX1_N );
const TYPE tyABS_X2_N = P::FSEL( tyX2_N, tyX2_N, -tyX2_N );
TYPE tyMin0, tyMin1, tyMin2;
T_(VECTOR,DIM) tvMin0, tvMin1, tvMin2;
if (tyABS_X0_N <= tyABS_X1_N)
{
if (tyABS_X1_N <= tyABS_X2_N)
{
tyMin0 = tyABS_X0_N;
tyMin1 = tyABS_X1_N;
tyMin2 = tyABS_X2_N;
tvMin0 = (tyX0_N > TYPE(0.0) ? tvE0 : MATH::F_NEG( tvE0 ) );
tvMin1 = (tyX1_N > TYPE(0.0) ? tvE1 : MATH::F_NEG( tvE1 ) );
tvMin2 = (tyX2_N > TYPE(0.0) ? tvE2 : MATH::F_NEG( tvE2 ) );
}
else if (tyABS_X0_N <= tyABS_X2_N)
{
tyMin0 = tyABS_X0_N;
tyMin1 = tyABS_X2_N;
tyMin2 = tyABS_X1_N;
tvMin0 = (tyX0_N > TYPE(0.0) ? tvE0 : MATH::F_NEG( tvE0 ) );
tvMin1 = (tyX2_N > TYPE(0.0) ? tvE2 : MATH::F_NEG( tvE2 ) );
tvMin2 = (tyX1_N > TYPE(0.0) ? tvE1 : MATH::F_NEG( tvE1 ) );
}
else
{
tyMin0 = tyABS_X2_N;
tyMin1 = tyABS_X0_N;
tyMin2 = tyABS_X1_N;
tvMin0 = (tyX2_N > TYPE(0.0) ? tvE2 : MATH::F_NEG( tvE2 ) );
tvMin1 = (tyX0_N > TYPE(0.0) ? tvE0 : MATH::F_NEG( tvE0 ) );
tvMin2 = (tyX1_N > TYPE(0.0) ? tvE1 : MATH::F_NEG( tvE1 ) );
};
}
else
{
if (tyABS_X2_N <= tyABS_X1_N)
{
tyMin0 = tyABS_X2_N;
tyMin1 = tyABS_X1_N;
tyMin2 = tyABS_X0_N;
tvMin0 = (tyX2_N > TYPE(0.0) ? tvE2 : MATH::F_NEG( tvE2 ) );
tvMin1 = (tyX1_N > TYPE(0.0) ? tvE1 : MATH::F_NEG( tvE1 ) );
tvMin2 = (tyX0_N > TYPE(0.0) ? tvE0 : MATH::F_NEG( tvE0 ) );
}
else if (tyABS_X2_N <= tyABS_X0_N)
{
tyMin0 = tyABS_X1_N;
tyMin1 = tyABS_X2_N;
tyMin2 = tyABS_X0_N;
tvMin0 = (tyX1_N > TYPE(0.0) ? tvE1 : MATH::F_NEG( tvE1 ) );
tvMin1 = (tyX2_N > TYPE(0.0) ? tvE2 : MATH::F_NEG( tvE2 ) );
tvMin2 = (tyX0_N > TYPE(0.0) ? tvE0 : MATH::F_NEG( tvE0 ) );
}
else
{
tyMin0 = tyABS_X1_N;
tyMin1 = tyABS_X0_N;
tyMin2 = tyABS_X2_N;
tvMin0 = (tyX1_N > TYPE(0.0) ? tvE1 : MATH::F_NEG( tvE1 ) );
tvMin1 = (tyX0_N > TYPE(0.0) ? tvE0 : MATH::F_NEG( tvE0 ) );
tvMin2 = (tyX2_N > TYPE(0.0) ? tvE2 : MATH::F_NEG( tvE2 ) );
};
};
C_(VECTOR,DIM) tvPlnN = tgPN0.Query_Normal();
const TYPE tyDepth = tyMin2 - tyDist;
if (tyDepth + tyMin0 + tyMin1 > TYPE(0.0))
{
return (TgE_NOINTERSECT);
};
C_(VECTOR,DIM) tvPnt = MATH::F_SUB( tgBX0.Query_Origin(), tvMin2 );
P_(CONTACT,DIM) ptgContact;
ptgContact = (P_(CONTACT,DIM))((PC_TgUINT08)ptgPacket->m_ptgContact + ptgPacket->m_niContact*ptgPacket->m_iStride);
ptgContact->m_tvPos = MATH::F_SUB( MATH::F_SUB( tvPnt, tvMin0 ), tvMin1 );
ptgContact->m_tvNormal = tvPlnN;
ptgContact->m_tyT0 = TYPE(0.0);
ptgContact->m_tyDepth = tyDepth + tyMin0 + tyMin1;
++ptgPacket->m_niContact;
if (tyDepth - tyMin0 + tyMin1 <= TYPE(0.0))
{
return (TgS_OK);
};
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 = MATH::F_SUB( MATH::F_ADD( tvPnt, tvMin0 ), tvMin1 );
ptgContact->m_tvNormal = tvPlnN;
ptgContact->m_tyT0 = TYPE(0.0);
ptgContact->m_tyDepth = tyDepth - tyMin0 + tyMin1;
++ptgPacket->m_niContact;
if (tyDepth + tyMin0 - tyMin1 <= TYPE(0.0))
{
return (TgS_OK);
};
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 = MATH::F_ADD( MATH::F_SUB( tvPnt, tvMin0 ), tvMin1 );
ptgContact->m_tvNormal = tvPlnN;
ptgContact->m_tyT0 = TYPE(0.0);
ptgContact->m_tyDepth = tyDepth + tyMin0 - tyMin1;
++ptgPacket->m_niContact;
if (tyDepth - tyMin0 - tyMin1 <= TYPE(0.0))
{
return (TgS_OK);
};
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 = MATH::F_SUB( MATH::F_SUB( tvPnt, tvMin0 ), tvMin1 );
ptgContact->m_tvNormal = tvPlnN;
ptgContact->m_tyT0 = TYPE(0.0);
ptgContact->m_tyDepth = tyDepth + tyMin0 + tyMin1;
++ptgPacket->m_niContact;
return (TgS_OK);
};
template TgRESULT F_Contact_Penetrate( PC_TgF4CONTACT_PACKET, CR_TgF4PLANE, CR_TgF4BOX );
};
};