[an error occurred while processing this directive]
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-==-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // // // Project: Talina Gaming System (TgS) (∂) // File: TgS Collision - Box AA-Box AA.cpp // Author: Andrew Aye (EMail: andrew.aye@gmail.com, Web: http://www.andrewaye.com) // Version: 3.11 // // ------------------------------------------------------------------------------------------------------------------------------ // // // Copyright: © 2002-2008, Andrew Aye. All Rights Reserved. // // This software is free for non-commercial use. Redistribution and use in source and binary forms, with or without modification, // are permitted provided that the following conditions are met: // Redistributions of source code must retain this copyright notice, this list of conditions and the following disclaimers. // Redistributions in binary form must reproduce this copyright notice, this list of conditions and the following // disclaimers in the documentation and other materials provided with the distribution. // // Neither the names of the copyright owner nor the names of its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // The intellectual property rights of the algorithms used reside with Andrew Aye. You may not use this software, in whole or // in part, in support of any commercial product without the express written consent of the author. // // There is no warranty or other guarantee of fitness of this software for any purpose. It is provided solely "as is". // // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-==-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // namespace TGS { // START TGS /////////////////////////////////////////////////////////////////////////////////////////////////////// namespace COL { // START COL /////////////////////////////////////////////////////////////////////////////////////////////////////// // ============================================================================================================================== // // ---- F_DistSq ---------------------------------------------------------------------------------------------------------------- // // Input: tgBA0, tgBA1: Box, Axis-Aligned primitive // Return: Minimal distance between the two primitives or negative type max if they intersect or are invalid. // ------------------------------------------------------------------------------------------------------------------------------ // template <typename TYPE, int DIM> TYPE F_DistSq( CR_(BOXAA,DIM) tgBA0, CR_(BOXAA,DIM) tgBA1 ) { TYPE tyDistSq = TYPE(0.0); if (tgBA1.Query_MaxX() < tgBA0.Query_MinX()) { tyDistSq += (tgBA0.Query_MinX() - tgBA1.Query_MaxX())*(tgBA0.Query_MinX() - tgBA1.Query_MaxX()); } else if (tgBA0.Query_MaxX() < tgBA1.Query_MinX()) { tyDistSq += (tgBA1.Query_MinX() - tgBA0.Query_MaxX())*(tgBA1.Query_MinX() - tgBA0.Query_MaxX()); }; if (tgBA1.Query_MaxY() < tgBA0.Query_MinY()) { tyDistSq += (tgBA0.Query_MinY() - tgBA1.Query_MaxY())*(tgBA0.Query_MinY() - tgBA1.Query_MaxY()); } else if (tgBA0.Query_MaxY() < tgBA1.Query_MinY()) { tyDistSq += (tgBA1.Query_MinY() - tgBA0.Query_MaxY())*(tgBA1.Query_MinY() - tgBA0.Query_MaxY()); }; if (tgBA1.Query_MaxZ() < tgBA0.Query_MinZ()) { tyDistSq += (tgBA0.Query_MinZ() - tgBA1.Query_MaxZ())*(tgBA0.Query_MinZ() - tgBA1.Query_MaxZ()); } else if (tgBA0.Query_MaxZ() < tgBA1.Query_MinZ()) { tyDistSq += (tgBA1.Query_MinZ() - tgBA0.Query_MaxZ())*(tgBA1.Query_MinZ() - tgBA0.Query_MaxZ()); }; return (tyDistSq <= TYPE(0.0) ? -LIMITS<TYPE>::MAX : tyDistSq); }; template TgFLOAT32 F_DistSq( CR_TgF4BOXAA, CR_TgF4BOXAA ); // ============================================================================================================================== // // ---- F_ClosestSq ------------------------------------------------------------------------------------------------------------- // // Input: tgBA0, tgBA1: Box, Axis-Aligned primitive // Output: tvBA0, tvBA1: Point of closest proximity on the box, axis-aligned #1 and #2 respectively // Return: Minimal distance between the two primitives or negative type max if they intersect or are invalid. // ------------------------------------------------------------------------------------------------------------------------------ // template <typename TYPE, int DIM> TYPE F_ClosestSq( PC_(VECTOR,DIM) ptvBA0, PC_(VECTOR,DIM) ptvBA1, CR_(BOXAA,DIM) tgBA0, CR_(BOXAA,DIM) tgBA1 ) { TYPE tyX0,tyX1, tyY0,tyY1, tyZ0,tyZ1; TYPE tyDistSq = TYPE(0.0); // First (X) co-ordinate value. if (tgBA1.Query_MaxX() < tgBA0.Query_MinX()) { tyDistSq += (tgBA0.Query_MinX() - tgBA1.Query_MaxX())*(tgBA0.Query_MinX() - tgBA1.Query_MaxX()); tyX0 = tgBA0.Query_MinX(); tyX1 = tgBA1.Query_MaxX(); } else if (tgBA0.Query_MaxX() < tgBA1.Query_MinX()) { tyDistSq += (tgBA1.Query_MinX() - tgBA0.Query_MaxX())*(tgBA1.Query_MinX() - tgBA0.Query_MaxX()); tyX0 = tgBA0.Query_MaxX(); tyX1 = tgBA1.Query_MinX(); } else { register TYPE tyT; tyT = P::FSEL( tgBA0.Query_MinX() - tgBA1.Query_MinX(), tgBA0.Query_MinX(), tgBA1.Query_MinX() ); tyT += P::FSEL( tgBA1.Query_MaxX() - tgBA0.Query_MaxX(), tgBA0.Query_MaxX(), tgBA1.Query_MaxX() ); tyT *= TYPE(0.5); tyX0 = tyT; tyX1 = tyT; }; // Second (Y) co-ordinate value. if (tgBA1.Query_MaxY() < tgBA0.Query_MinY()) { tyDistSq += (tgBA0.Query_MinY() - tgBA1.Query_MaxY())*(tgBA0.Query_MinY() - tgBA1.Query_MaxY()); tyY0 = tgBA0.Query_MinY(); tyY1 = tgBA1.Query_MaxY(); } else if (tgBA0.Query_MaxY() < tgBA1.Query_MinY()) { tyDistSq += (tgBA1.Query_MinY() - tgBA0.Query_MaxY())*(tgBA1.Query_MinY() - tgBA0.Query_MaxY()); tyY0 = tgBA0.Query_MaxY(); tyY1 = tgBA1.Query_MinY(); } else { register TYPE tyT; tyT = P::FSEL( tgBA0.Query_MinY() - tgBA1.Query_MinY(), tgBA0.Query_MinY(), tgBA1.Query_MinY() ); tyT += P::FSEL( tgBA1.Query_MaxY() - tgBA0.Query_MaxY(), tgBA0.Query_MaxY(), tgBA1.Query_MaxY() ); tyT *= TYPE(0.5); tyY0 = tyT; tyY1 = tyT; }; // Third (Z) co-ordinate value. if (tgBA1.Query_MaxZ() < tgBA0.Query_MinZ()) { tyDistSq += (tgBA0.Query_MinZ() - tgBA1.Query_MaxZ())*(tgBA0.Query_MinZ() - tgBA1.Query_MaxZ()); tyZ0 = tgBA0.Query_MinZ(); tyZ1 = tgBA1.Query_MaxZ(); } else if (tgBA0.Query_MaxZ() < tgBA1.Query_MinZ()) { tyDistSq += (tgBA1.Query_MinZ() - tgBA0.Query_MaxZ())*(tgBA1.Query_MinZ() - tgBA0.Query_MaxZ()); tyZ0 = tgBA0.Query_MaxZ(); tyZ1 = tgBA1.Query_MinZ(); } else { register TYPE tyT; tyT = P::FSEL( tgBA0.Query_MinZ() - tgBA1.Query_MinZ(), tgBA0.Query_MinZ(), tgBA1.Query_MinZ() ); tyT += P::FSEL( tgBA1.Query_MaxZ() - tgBA0.Query_MaxZ(), tgBA0.Query_MaxZ(), tgBA1.Query_MaxZ() ); tyT *= TYPE(0.5); tyZ0 = tyT; tyZ1 = tyT; }; *ptvBA0 = MATH::F_SETP<TYPE,DIM>( tyX0,tyY0,tyZ0 ); *ptvBA1 = MATH::F_SETP<TYPE,DIM>( tyX1,tyY1,tyZ1 ); return (tyDistSq <= TYPE(0.0) ? -LIMITS<TYPE>::MAX : tyDistSq); }; template TgFLOAT32 F_ClosestSq( PC_TgF4VECTOR, PC_TgF4VECTOR, CR_TgF4BOXAA, CR_TgF4BOXAA ); // ============================================================================================================================== // // ---- F_Contact_Penetrate ----------------------------------------------------------------------------------------------------- // // Input: tgPacket: The current series of contact points for this query-series, and contact generation parameters. // Input: tgBA0: Box, Axis-Aligned primitive // Input: tgBA1: Box, Axis-Aligned primitive - contact points are generated on this primitive // Output: tgPacket: Points of penetration between the two primitives are added to it // Return: Result Code // ------------------------------------------------------------------------------------------------------------------------------ // template <typename TYPE, int DIM> TgRESULT F_Contact_Penetrate( PC_(CONTACT_PACKET,DIM) ptgPacket, CR_(BOXAA,DIM) tgBA0, CR_(BOXAA,DIM) tgBA1 ) { TgBLOCK_FCN_NOOBJ(ETgFAC_COLLISION, 0, ETgTEST_PENETRATE, (((TgUINT)ETgBOXAA<<16)|(TgUINT)ETgBOXAA)) TgASSERT((TgSIZE)ptgPacket->m_iStride >= sizeof( P_(CONTACT,DIM) )) TgASSERT(tgBA1.Is_Valid() && tgBA0.Is_Valid()) if (0 == ptgPacket->m_niMaxContact || ptgPacket->m_niContact >= ptgPacket->m_niMaxContact || NULL == ptgPacket->m_ptgContact) { return (TgE_FAIL); }; register TgINT iAxis = -1; register TYPE tyT, tyDepth = -LIMITS<TYPE>::MAX; // First (X) co-ordinate value. tyT = tgBA1.Query_MinX() - tgBA0.Query_MaxX(); if (tyT > TYPE(0.0)) { return (TgE_NOINTERSECT); }; if (tyT > tyDepth) { tyDepth = tyT; iAxis = 0; }; tyT = tgBA0.Query_MinX() - tgBA1.Query_MaxX(); if (tyT > TYPE(0.0)) { return (TgE_NOINTERSECT); }; if (tyT > tyDepth) { tyDepth = tyT; iAxis = 1; }; // First (Y) co-ordinate value. tyT = tgBA1.Query_MinY() - tgBA0.Query_MaxY(); if (tyT > TYPE(0.0)) { return (TgE_NOINTERSECT); }; if (tyT > tyDepth) { tyDepth = tyT; iAxis = 2; }; tyT = tgBA0.Query_MinY() - tgBA1.Query_MaxY(); if (tyT > TYPE(0.0)) { return (TgE_NOINTERSECT); }; if (tyT > tyDepth) { tyDepth = tyT; iAxis = 3; }; // First (Z) co-ordinate value. tyT = tgBA1.Query_MinZ() - tgBA0.Query_MaxZ(); if (tyT > TYPE(0.0)) { return (TgE_NOINTERSECT); }; if (tyT > tyDepth) { tyDepth = tyT; iAxis = 4; }; tyT = tgBA0.Query_MinZ() - tgBA1.Query_MaxZ(); if (tyT > TYPE(0.0)) { return (TgE_NOINTERSECT); }; if (tyT > tyDepth) { tyDepth = tyT; iAxis = 5; }; // T_(VECTOR,DIM) tvD0,tvD1, tvP0, tvNM; switch (iAxis) { case 0: case 1: { register TYPE tyY0 = P::FSEL( tgBA1.Query_MinY() - tgBA0.Query_MinY(), tgBA1.Query_MinY(), tgBA0.Query_MinY() ); register TYPE tyZ0 = P::FSEL( tgBA1.Query_MinZ() - tgBA0.Query_MinZ(), tgBA1.Query_MinZ(), tgBA0.Query_MinZ() ); register TYPE tyY1 = P::FSEL( tgBA0.Query_MaxY() - tgBA1.Query_MaxY(), tgBA1.Query_MaxY(), tgBA0.Query_MaxY() ); register TYPE tyZ1 = P::FSEL( tgBA0.Query_MaxZ() - tgBA1.Query_MaxZ(), tgBA1.Query_MaxZ(), tgBA0.Query_MaxZ() ); tvD0 = MATH::F_SETV<TYPE,DIM>( TYPE(0.0), tyY1 - tyY0, TYPE(0.0) ); tvD1 = MATH::F_SETV<TYPE,DIM>( TYPE(0.0), TYPE(0.0), tyZ1 - tyZ0 ); tvP0 = MATH::F_SETP<TYPE,DIM>( 0 == iAxis ? tgBA1.Query_MinX() : tgBA1.Query_MaxX(), tyY0, tyZ0 ); tvNM = MATH::F_SETV<TYPE,DIM>( 0 == iAxis ? TYPE(1.0) : TYPE(-1.0), TYPE(0.0), TYPE(0.0) ); break; }; case 2: case 3: { register TYPE tyX0 = P::FSEL( tgBA1.Query_MinX() - tgBA0.Query_MinX(), tgBA1.Query_MinX(), tgBA0.Query_MinX() ); register TYPE tyZ0 = P::FSEL( tgBA1.Query_MinZ() - tgBA0.Query_MinZ(), tgBA1.Query_MinZ(), tgBA0.Query_MinZ() ); register TYPE tyX1 = P::FSEL( tgBA0.Query_MaxX() - tgBA1.Query_MaxX(), tgBA1.Query_MaxX(), tgBA0.Query_MaxX() ); register TYPE tyZ1 = P::FSEL( tgBA0.Query_MaxZ() - tgBA1.Query_MaxZ(), tgBA1.Query_MaxZ(), tgBA0.Query_MaxZ() ); tvD0 = MATH::F_SETV<TYPE,DIM>( tyX1 - tyX0, TYPE(0.0), TYPE(0.0) ); tvD1 = MATH::F_SETV<TYPE,DIM>( TYPE(0.0), TYPE(0.0), tyZ1 - tyZ0 ); tvP0 = MATH::F_SETP<TYPE,DIM>( tyX0, 2 == iAxis ? tgBA1.Query_MinY() : tgBA1.Query_MaxY(), tyZ0 ); tvNM = MATH::F_SETV<TYPE,DIM>( TYPE(0.0), 2 == iAxis ? TYPE(1.0) : TYPE(-1.0), TYPE(0.0) ); break; }; case 4: case 5: { register TYPE tyX0 = P::FSEL( tgBA1.Query_MinX() - tgBA0.Query_MinX(), tgBA1.Query_MinX(), tgBA0.Query_MinX() ); register TYPE tyY0 = P::FSEL( tgBA1.Query_MinY() - tgBA0.Query_MinY(), tgBA1.Query_MinY(), tgBA0.Query_MinY() ); register TYPE tyX1 = P::FSEL( tgBA0.Query_MaxX() - tgBA1.Query_MaxX(), tgBA1.Query_MaxX(), tgBA0.Query_MaxX() ); register TYPE tyY1 = P::FSEL( tgBA0.Query_MaxY() - tgBA1.Query_MaxY(), tgBA1.Query_MaxY(), tgBA0.Query_MaxY() ); tvD0 = MATH::F_SETV<TYPE,DIM>( tyX1 - tyX0, TYPE(0.0), TYPE(0.0) ); tvD1 = MATH::F_SETV<TYPE,DIM>( TYPE(0.0), tyY1 - tyY0, TYPE(0.0) ); tvP0 = MATH::F_SETP<TYPE,DIM>( tyX0, tyY0, 4 == iAxis ? tgBA1.Query_MinZ() : tgBA1.Query_MaxZ() ); tvNM = MATH::F_SETV<TYPE,DIM>( TYPE(0.0), TYPE(0.0), 4 == iAxis ? TYPE(1.0) : TYPE(-1.0) ); break; }; default: COUT_NOOBJ( ERROR, TgT("%-16.16s(%-48.48s): [BA][BA] Algorithm - Illegal separation axis id.\n"), TgT("Collision"), TgT("F_Contact_Penetrate") ); return (TgE_FAIL); }; P_(CONTACT,DIM) ptgContact; // Point 1 ptgContact = (P_(CONTACT,DIM))((PC_TgUINT08)ptgPacket->m_ptgContact + ptgPacket->m_niContact*ptgPacket->m_iStride); ptgContact->m_tvPos = tvP0; ptgContact->m_tvNormal = tvNM; ptgContact->m_tyT0 = TYPE(0.0); ptgContact->m_tyDepth = -tyDepth; ++ptgPacket->m_niContact; // Point 2 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( tvP0, tvD0 ); ptgContact->m_tvNormal = tvNM; ptgContact->m_tyT0 = TYPE(0.0); ptgContact->m_tyDepth = -tyDepth; ++ptgPacket->m_niContact; // Point 3 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( tvP0, tvD1 ); ptgContact->m_tvNormal = tvNM; ptgContact->m_tyT0 = TYPE(0.0); ptgContact->m_tyDepth = -tyDepth; ++ptgPacket->m_niContact; // Point 4 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_ADD( tvP0, tvD0 ), tvD1 ); ptgContact->m_tvNormal = tvNM; ptgContact->m_tyT0 = TYPE(0.0); ptgContact->m_tyDepth = -tyDepth; ++ptgPacket->m_niContact; return (TgS_OK); }; template TgRESULT F_Contact_Penetrate( PC_TgF4CONTACT_PACKET, CR_TgF4BOXAA, CR_TgF4BOXAA ); // ============================================================================================================================== // }; // END COL ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// }; // END TGS //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////[an error occurred while processing this directive]