#if !defined(_TGS_COLLISION_PLANE_SEGMENT_INL_)
#define _TGS_COLLISION_PLANE_SEGMENT_INL_
#pragma once
namespace TGS {
namespace COL {
template <typename TYPE, int DIM> TgFORCEINLINE
TYPE F_DistSq( CR_(PLANE,DIM) tgPN0, CR_(SEGMENT,DIM) tgSG0 )
{
const TYPE tyDist = F_Sign_Dist( tgPN0, tgSG0.Query_Origin() );
const TYPE tyD1_N = MATH::F_DOT(tgPN0.Query_Normal(),tgSG0.Query_DirN());
const TYPE tyTA = P::FSEL( tyDist+tyD1_N, (tyDist+tyD1_N)*(tyDist+tyD1_N), -LIMITS<TYPE>::MAX );
return (P::FSEL( tyDist, P::FSEL( tyD1_N, tyDist*tyDist , tyTA ), -LIMITS<TYPE>::MAX ));
};
template <typename TYPE, int DIM> TgFORCEINLINE
TYPE F_Dist( CR_(PLANE,DIM) tgPN0, CR_(SEGMENT,DIM) tgSG0 )
{
const TYPE tyDist = F_Sign_Dist( tgPN0, tgSG0.Query_Origin() );
const TYPE tyD1_N = MATH::F_DOT(tgPN0.Query_Normal(),tgSG0.Query_DirN());
const TYPE tyTA = P::FSEL( tyDist+tyD1_N, tyDist+tyD1_N, -LIMITS<TYPE>::MAX );
return (P::FSEL( tyDist, P::FSEL( tyD1_N, tyDist , tyTA ), -LIMITS<TYPE>::MAX ));
};
template <typename TYPE, int DIM> TgFORCEINLINE
TYPE F_ClosestSq( PC_(VECTOR,DIM) ptvPN0, PC_(VECTOR,DIM) ptvSG0, CR_(PLANE,DIM) tgPN0, CR_(SEGMENT,DIM) tgSG0 )
{
TYPE tyDist = F_Sign_Dist( tgPN0, tgSG0.Query_Origin() );
const TYPE tyD1_N = MATH::F_DOT(tgPN0.Query_Normal(),tgSG0.Query_DirN());
const TYPE tyTA = P::FSEL( tyDist + tyD1_N, tyDist + tyD1_N, TYPE(-1.0) );
const TYPE tySG0 = P::FSEL( tyD1_N, TYPE(0.0), TYPE(1.0) );
tyDist = P::FSEL( tyDist, P::FSEL( tyD1_N, tyDist , tyTA ), TYPE(-1.0) );
*ptvPN0 = MATH::F_SUB( tgSG0.Query_Origin(), MATH::F_MUL( tyDist, tgPN0.Query_Normal() ) );
*ptvSG0 = MATH::F_ADD( tgSG0.Query_Origin(), MATH::F_MUL( tySG0, tgSG0.Query_DirN() ) );
return (P::FSEL( tyDist, tyDist*tyDist, -LIMITS<TYPE>::MAX ));
};
template <typename TYPE, int DIM> TgFORCEINLINE
TYPE F_Closest( PC_(VECTOR,DIM) ptvPN0, PC_(VECTOR,DIM) ptvSG0, CR_(PLANE,DIM) tgPN0, CR_(SEGMENT,DIM) tgSG0 )
{
TYPE tyDist = F_Sign_Dist( tgPN0, tgSG0.Query_Origin() );
const TYPE tyD1_N = MATH::F_DOT(tgPN0.Query_Normal(),tgSG0.Query_DirN());
const TYPE tyTA = P::FSEL( tyDist + tyD1_N, tyDist + tyD1_N, TYPE(-1.0) );
const TYPE tySG0 = P::FSEL( tyD1_N, TYPE(0.0), TYPE(1.0) );
tyDist = P::FSEL( tyDist, P::FSEL( tyD1_N, tyDist , tyTA ), TYPE(-1.0) );
*ptvPN0 = MATH::F_SUB( tgSG0.Query_Origin(), MATH::F_MUL( tyDist, tgPN0.Query_Normal() ) );
*ptvSG0 = MATH::F_ADD( tgSG0.Query_Origin(), MATH::F_MUL( tySG0, tgSG0.Query_DirN() ) );
return (P::FSEL( tyDist, tyDist, -LIMITS<TYPE>::MAX ));
};
template <typename TYPE, int DIM> TgFORCEINLINE
TYPE F_ClosestSq( PC_(VECTOR,DIM) ptvPN0, TYPE *ptySG0, CR_(PLANE,DIM) tgPN0, CR_(SEGMENT,DIM) tgSG0 )
{
TYPE tyDist = F_Sign_Dist( tgPN0, tgSG0.Query_Origin() );
const TYPE tyD1_N = MATH::F_DOT(tgPN0.Query_Normal(),tgSG0.Query_DirN());
const TYPE tyTA = P::FSEL( tyDist + tyD1_N, tyDist + tyD1_N, TYPE(-1.0) );
tyDist = P::FSEL( tyDist, P::FSEL( tyD1_N, tyDist , tyTA ), TYPE(-1.0) );
*ptvPN0 = MATH::F_SUB( tgSG0.Query_Origin(), MATH::F_MUL( tyDist, tgPN0.Query_Normal() ) );
*ptySG0 = P::FSEL( tyD1_N, TYPE(0.0), TYPE(1.0) );
return (P::FSEL( tyDist, tyDist*tyDist, -LIMITS<TYPE>::MAX ));
};
template <typename TYPE, int DIM> TgFORCEINLINE
TYPE F_Closest( PC_(VECTOR,DIM) ptvPN0, TYPE *ptySG0, CR_(PLANE,DIM) tgPN0, CR_(SEGMENT,DIM) tgSG0 )
{
TYPE tyDist = F_Sign_Dist( tgPN0, tgSG0.Query_Origin() );
const TYPE tyD1_N = MATH::F_DOT(tgPN0.Query_Normal(),tgSG0.Query_DirN());
const TYPE tyTA = P::FSEL( tyDist + tyD1_N, tyDist + tyD1_N, TYPE(-1.0) );
tyDist = P::FSEL( tyDist, P::FSEL( tyD1_N, tyDist , tyTA ), TYPE(-1.0) );
*ptvPN0 = MATH::F_SUB( tgSG0.Query_Origin(), MATH::F_MUL( tyDist, tgPN0.Query_Normal() ) );
*ptySG0 = P::FSEL( tyD1_N, TYPE(0.0), TYPE(1.0) );
return (P::FSEL( tyDist, tyDist, -LIMITS<TYPE>::MAX ));
};
template <typename TYPE, int DIM> TgFORCEINLINE
TgBOOL F_Contact_Test( CR_(PLANE,DIM) tgPN0, CR_(SEGMENT,DIM) tgSG0 )
{
const TYPE tyDist = F_Sign_Dist( tgPN0, tgSG0.Query_Origin() );
const TYPE tyD1_N = MATH::F_DOT(tgPN0.Query_Normal(),tgSG0.Query_DirN());
return (tyDist > TYPE(0.0) && (tyD1_N >= TYPE(0.0) || tyDist > -tyD1_N));
};
template <typename TYPE, int DIM> TgFORCEINLINE
TgRESULT F_Contact_Intersect( TYPE *ptySG0, CR_(PLANE,DIM) tgPN0, CR_(SEGMENT,DIM) tgSG0 )
{
TgASSERT(tgPN0.Is_Valid() && tgSG0.Is_Valid())
const TYPE tyDist = F_Sign_Dist( tgPN0, tgSG0.Query_Origin() );
const TYPE tyD1_N = tgPN0.Query_Normal()*tgSG0.Query_DirN();
if (Near_Zero( tyD1_N ) || !( (tyDist > TYPE(0.0)) ^ (tyD1_N > TYPE(0.0)) ) || P::ABS( tyDist ) > P::ABS( tyD1_N ))
{
return (TgE_NOINTERSECT);
};
*ptySG0 = -tyDist / tyD1_N;
return (TgS_OK);
};
template <typename TYPE, int DIM> TgFORCEINLINE
TgRESULT F_Contact_Intersect( PC_(CONTACT_PACKET,DIM) ptgPacket, CR_(PLANE,DIM) tgPN0, CR_(SEGMENT,DIM) tgSG0 )
{
TgASSERT((TgSIZE)ptgPacket->m_iStride >= sizeof( P_(CONTACT,DIM) ))
TgASSERT(tgPN0.Is_Valid() && tgSG0.Is_Valid())
if (0 == ptgPacket->m_niMaxContact || ptgPacket->m_niContact >= ptgPacket->m_niMaxContact || NULL == ptgPacket->m_ptgContact)
{
return (TgE_FAIL);
};
const TYPE tyDist = F_Sign_Dist( tgPN0, tgSG0.Query_Origin() );
const TYPE tyD1_N = MATH::F_DOT(tgPN0.Query_Normal(),tgSG0.Query_DirN());
if (Near_Zero( tyD1_N ) || !( (tyDist > TYPE(0.0)) ^ (tyD1_N > TYPE(0.0)) ) || P::ABS( tyDist ) > P::ABS( tyD1_N ))
{
return (TgE_NOINTERSECT);
};
const TYPE tyT0 = -tyDist / tyD1_N;
P_(CONTACT,DIM) ptgContact;
ptgContact = (P_(CONTACT,DIM))((PC_TgUINT08)ptgPacket->m_ptgContact + ptgPacket->m_niContact*ptgPacket->m_iStride);
ptgContact->m_tvPos = MATH::F_ADD( tgSG0.Query_Origin(), MATH::F_MUL( tyT0, tgSG0.Query_DirN() ) );
ptgContact->m_tvNormal = MATH::F_MUL( P::FSEL( tyDist, TYPE(1.0), TYPE(-1.0) ), tgPN0.Query_Normal() );
ptgContact->m_tyT0 = tyT0;
ptgContact->m_tyDepth = TYPE(0.0);
++ptgPacket->m_niContact;
return (TgS_OK);
};
template <typename TYPE, int DIM> TgFORCEINLINE
TgRESULT F_Clip( TYPE *ptySG0, TYPE *ptySG1, CR_(PLANE,DIM) tgPN0, CR_(SEGMENT,DIM) tgSG0 )
{
return (TTgCLP_PNLN<TYPE,DIM,1,1>::DO( ptySG0,ptySG1, tgPN0, tgSG0.Query_Origin(),tgSG0.Query_DirN() ));
};
template <typename TYPE, int DIM> TgFORCEINLINE
TgRESULT F_Clip( PC_(CLIP_LIST,DIM) ptgCL, CR_(PLANE,DIM) tgPN0, CR_(SEGMENT,DIM) tgSG0 )
{
return (TTgCLP_PNLN<TYPE,DIM,1,1>::DO( ptgCL, tgPN0, tgSG0.Query_Origin(),tgSG0.Query_DirN() ));
};
};
};
#endif