TgRESULT V(tgCO_F_Penetrate_VT_SP)( V(PCU_STg2_CO_Packet) psPacket, V(CPCU_TgVEC) pvS0, V(CPCU_TgSPHERE) psSP0 )
{
V(TgVEC) vNormal, vT0;
TYPE fNM;
V(P_STg2_CO_Contact) psContact;
TgASSERT_PARAM((TgSIZE)psPacket->m_iStride >= sizeof( V(P_STg2_CO_Contact) ));
TgASSERT_PARAM(V(tgGM_Is_Valid_SP)( psSP0 ) && V(F_Is_Point_Valid)( pvS0 ));
if (0 == psPacket->m_niMaxContact || psPacket->m_niContact >= psPacket->m_niMaxContact || NULL == psPacket->m.psContact)
{
return (TgE_FAIL);
};
vNormal = V(F_SUB_VV)( &psSP0->m_vOrigin, pvS0 );
fNM = V(F_LSQ)( &vNormal );
if (fNM > psSP0->m_fRadiusSq)
{
return (ETgE_NO_INTERSECT);
};
if (fNM <= F(KTgEPS))
{
vNormal = V(F_SETV_ELEM)( MKL(0.0), MKL(1.0), MKL(0.0) );
fNM = MKL(0.0);
}
else
{
vNormal = V(F_NORM_LEN)( &fNM, &vNormal );
};
psContact = (V(P_STg2_CO_Contact))(psPacket->m.piContact + psPacket->m_niContact*psPacket->m_iStride);
vT0 = V(F_MUL_SV)( psSP0->m_fRadius, &vNormal );
psContact->m_vS0 = V(F_SUB_VV)( &psSP0->m_vOrigin, &vT0 );
psContact->m_vN0 = vNormal;
psContact->m_fT0 = MKL(0.0);
psContact->m_fDepth = psSP0->m_fRadius - fNM;
++psPacket->m_niContact;
return (TgS_OK);
}
TgRESULT V(tgCO_F_Sweep_SP_VT)(
V(PCU_STg2_CO_Packet) psPacket, PCU_TYPE pfPM, V(CPCU_TgSPHERE) psSP0, V(CPCU_TgVEC) pvS0, V(CPCU_TgDELTA) psDT )
{
TgSINT32 niContact = psPacket->m_niContact;
const TYPE fT = *pfPM;
V(TgDELTA) tgNegDT;
V(P_STg2_CO_Contact) psContact;
TgSINT32 iIdx;
TgRESULT tgResult;
V(TgVEC) vT0;
tgNegDT.m_vUDT = V(F_NEG)( &psDT->m_vUDT );
tgNegDT.m_vDT = V(F_NEG)( &psDT->m_vDT );
tgNegDT.m_fDT = psDT->m_fDT;
tgNegDT.m_fDT_DT = psDT->m_fDT_DT;
tgNegDT.m_fInv_DT = psDT->m_fInv_DT;
tgResult = V(tgCO_F_Sweep_VT_SP)( psPacket, pfPM, pvS0, psSP0, &tgNegDT );
if (tgResult == ETgE_PREPENETRATION)
{
for (iIdx = niContact; iIdx < psPacket->m_niContact; ++iIdx)
{
psContact = (V(P_STg2_CO_Contact))(psPacket->m.piContact + iIdx*psPacket->m_iStride);
vT0 = V(F_MUL_VS)( &psContact->m_vN0, psContact->m_fDepth );
psContact->m_vS0 = V(F_ADD_VV)( &psContact->m_vS0, &vT0 );
psContact->m_vN0 = V(F_NEG)( &psContact->m_vN0 );
};
return (tgResult);
}
if (TgFAILED( tgResult ))
{
return (tgResult);
};
iIdx = (*pfPM < fT - psPacket->m_fSweepTol ? 0 : niContact);
TgASSERT(iIdx < psPacket->m_niContact);
for (; iIdx < psPacket->m_niContact; ++iIdx)
{
psContact = (V(P_STg2_CO_Contact))(psPacket->m.piContact + iIdx*psPacket->m_iStride);
vT0 = V(F_MUL_SV)( psContact->m_fT0, &psDT->m_vDT );
psContact->m_vS0 = V(F_ADD_VV)( &psContact->m_vS0, &vT0 );
psContact->m_vN0 = V(F_NEG)( &psContact->m_vN0 );
};
return (tgResult);
}
TgRESULT V(tgCO_F_Sweep_VT_SP)(
V(PCU_STg2_CO_Packet) psPacket, PCU_TYPE pfPM, V(CPCU_TgVEC) pvS0, V(CPCU_TgSPHERE) psSP0, V(CPCU_TgDELTA) psDT )
{
V(TgVEC) vDS = V(F_SUB_VV)( pvS0, &psSP0->m_vOrigin );
TYPE fDS_DS = V(F_LSQ)( &vDS );
TgASSERT_PARAM( V(tgGM_Is_Valid_DT)( psDT ) && V(tgGM_Is_Valid_SP)( psSP0 ) && V(F_Is_Point_Valid)( pvS0 ) );
TgASSERT_PARAM((TgSIZE)psPacket->m_iStride >= sizeof( V(P_STg2_CO_Contact) ));
if (fDS_DS <= psSP0->m_fRadiusSq)
{
if (*pfPM > psPacket->m_fSweepTol)
{
psPacket->m_niContact = 0;
};
*pfPM = MKL(0.0);
if ((TgTRUE == psPacket->m_bReport_Penetration) && ETgE_MAX_CONTACTS == V(tgCO_F_Penetrate_VT_SP)( psPacket, pvS0,psSP0 ))
{
return (ETgE_MAX_CONTACTS);
};
return (ETgE_PREPENETRATION);
}
else
{
TYPE fK0 = psDT->m_fDT - F(KTgEPS);
const TYPE fDS_UDT = V(F_DOT_VV)( &vDS, &psDT->m_vUDT );
fK0 = F(tgPM_FSEL)( fK0, fDS_UDT - F(KTgEPS), MKL(-1.0) );
fK0 = F(tgPM_FSEL)( fK0, psSP0->m_fRadius + *pfPM*psDT->m_fDT - fDS_UDT, MKL(-1.0) );
fK0 = F(tgPM_FSEL)( fK0, psSP0->m_fRadiusSq - fDS_DS + fDS_UDT*fDS_UDT, MKL(-1.0) );
fK0 = F(tgPM_FSEL)( fK0, fDS_UDT - F(tgPM_SQRT)( fK0 ), MKL(-1.0) );
if (fK0 > (*pfPM + psPacket->m_fSweepTol)*psDT->m_fDT)
{
return (ETgE_NO_INTERSECT);
}
else
{
const TYPE fT0 = fK0 / psDT->m_fDT;
V(C_TgVEC) vK0 = V(F_MUL_SV)( fK0, &psDT->m_vUDT );
V(C_TgVEC) vS1 = V(F_ADD_VV)( &psSP0->m_vOrigin, &vK0 );
V(C_TgVEC) vK1 = V(F_SUB_VV)( &vS1, pvS0 );
V(C_TgVEC) vNormal = V(F_NORM)( &vK1 );
V(C_TgVEC) vK2 = V(F_MUL_VS)( &vNormal, psSP0->m_fRadius );
V(P_STg2_CO_Contact) psContact;
if (fT0 < *pfPM - psPacket->m_fSweepTol)
{
psPacket->m_niContact = 0;
*pfPM = fT0;
};
psContact = (V(P_STg2_CO_Contact))(psPacket->m.piContact + psPacket->m_niContact*psPacket->m_iStride);
psContact->m_vS0 = V(F_SUB_VV)( &vS1, &vK2 );
psContact->m_vN0 = vNormal;
psContact->m_fT0 = fT0;
psContact->m_fDepth = MKL(0.0);
++psPacket->m_niContact;
return (TgS_OK);
};
};
}