[an error occurred while processing this directive]
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-==-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // // // Project: Talina Gaming System (TgS) (∂) // File: TgS Collision - Box AA-Sphere.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_Contact_Penetrate ----------------------------------------------------------------------------------------------------- // // Input: tgPacket: The current series of contact points for this query-series, and contact generation parameters. // Input: tgSP0: Sphere primitive // Input: tgBA0: 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_(SPHERE,DIM) tgSP0, CR_(BOXAA,DIM) tgBA0 ) { TgBLOCK_FCN_NOOBJ(ETgFAC_COLLISION, 0, ETgTEST_PENETRATE, (((TgUINT)ETgSPHERE<<16)|(TgUINT)ETgBOXAA)) TgASSERT((TgSIZE)ptgPacket->m_iStride >= sizeof( P_(CONTACT,DIM) )) TgASSERT(tgBA0.Is_Valid() && tgSP0.Is_Valid()) if (0 == ptgPacket->m_niMaxContact || ptgPacket->m_niContact >= ptgPacket->m_niMaxContact || NULL == ptgPacket->m_ptgContact) { return (TgE_FAIL); }; // Find the point of closest proximity on the box to the sphere's origin and create a normalized direction vector of the // difference between the two points. These are the potential contact points and normal. M_(VECTOR,DIM) tvS0 = tgSP0.Query_Origin(); T_(VECTOR,DIM) tvP1, tvNormal; P_(CONTACT,DIM) ptgContact; const TYPE tyX00 = tvS0.X() - tgBA0.Query_MinX(); const TYPE tyX01 = tgBA0.Query_MaxX() - tvS0.X(); const TYPE tyX10 = tvS0.Y() - tgBA0.Query_MinY(); const TYPE tyX11 = tgBA0.Query_MaxY() - tvS0.Y(); const TYPE tyX20 = tvS0.Z() - tgBA0.Query_MinZ(); const TYPE tyX21 = tgBA0.Query_MaxZ() - tvS0.Z(); const TYPE tyX = P::FSEL( tyX00, P::FSEL( tyX01, tvP1.X(), tgBA0.Query_MaxX() ), tgBA0.Query_MinX() ); const TYPE tyY = P::FSEL( tyX10, P::FSEL( tyX11, tvP1.Y(), tgBA0.Query_MaxY() ), tgBA0.Query_MinY() ); const TYPE tyZ = P::FSEL( tyX20, P::FSEL( tyX21, tvP1.Z(), tgBA0.Query_MaxZ() ), tgBA0.Query_MinZ() ); tvP1 = MATH::F_SETP<TYPE,DIM>( tyX,tyY,tyZ ); tvNormal = MATH::F_SUB( tvP1, tgSP0.Query_Origin() ); ptgContact = (P_(CONTACT,DIM))((PC_TgUINT08)ptgPacket->m_ptgContact + ptgPacket->m_niContact*ptgPacket->m_iStride); if (MATH::F_LSQ( tvNormal ) > LIMITS<TYPE>::EPSILON) { TYPE tyNM; tvNormal = MATH::F_NORM( &tyNM, tvNormal ); if (tyNM > LIMITS<TYPE>::EPSILON) { // Sphere origin is not contained inside of the box, and therefore the potential contact values are correct. ptgContact->m_tvPos = tvP1; ptgContact->m_tvNormal = tvNormal; ptgContact->m_tyT0 = TYPE(0.0); ptgContact->m_tyDepth = tgSP0.Query_Radius() - tyNM; ++ptgPacket->m_niContact; return (TgS_OK); }; }; // Sphere origin is contained within the box itself - find the axis of minimum penetration. const TYPE tyX0 = P::FSEL( tyX01 - tyX00, tyX00, tyX01 ); const TYPE tyX1 = P::FSEL( tyX11 - tyX10, tyX10, tyX11 ); const TYPE tyX2 = P::FSEL( tyX21 - tyX20, tyX20, tyX21 ); const TYPE tyK0 = tyX1 - tyX0; const TYPE tyK1 = tyX2 - tyX0; const TYPE tyK2 = tyX2 - tyX1; const TYPE tyTX = P::FSEL( tyX01 - tyX00, tgBA0.Query_MinX(), tgBA0.Query_MaxX() ); const TYPE tyTY = P::FSEL( tyX11 - tyX10, tgBA0.Query_MinY(), tgBA0.Query_MaxY() ); const TYPE tyTZ = P::FSEL( tyX21 - tyX20, tgBA0.Query_MinZ(), tgBA0.Query_MaxZ() ); const TYPE tyKTX = P::FSEL( tyK0, P::FSEL( tyK1, tyTX, tvS0.X() ), tvS0.X() ); const TYPE tyKTY = P::FSEL( tyK0, tvS0.Y(), P::FSEL( tyK2, tyTY, tvS0.Y() ) ); const TYPE tyKTZ = P::FSEL( tyK0, P::FSEL( tyK1, tvS0.X(), tyTZ ), P::FSEL( tyK2, tvS0.Z(), tyTZ ) ); const TYPE tyNX = P::FSEL( tyX01 - tyX00, TYPE(1.0), TYPE(-1.0) ); const TYPE tyNY = P::FSEL( tyX11 - tyX10, TYPE(1.0), TYPE(-1.0) ); const TYPE tyNZ = P::FSEL( tyX21 - tyX20, TYPE(1.0), TYPE(-1.0) ); const TYPE tyKNX = P::FSEL( tyK0, P::FSEL( tyK1, tyNX, TYPE() ), TYPE() ); const TYPE tyKNY = P::FSEL( tyK0, TYPE(), P::FSEL( tyK2, tyNY, TYPE() ) ); const TYPE tyKNZ = P::FSEL( tyK0, P::FSEL( tyK1, TYPE(), tyNZ ), P::FSEL( tyK2, TYPE(), tyNZ ) ); ptgContact->m_tvPos = MATH::F_SETP<TYPE,DIM>( tyKTX,tyKTY,tyKTZ ); ptgContact->m_tvNormal = MATH::F_SETV<TYPE,DIM>( tyKNX,tyKNY,tyKNZ ); ptgContact->m_tyT0 = TYPE(0.0); ptgContact->m_tyDepth = tgSP0.Query_Radius() + P::FSEL( tyK0, P::FSEL( tyK1, tyX0, tyX2 ), P::FSEL( tyK2, tyX1, tyX2 ) ); ++ptgPacket->m_niContact; return (TgS_OK); }; template TgRESULT F_Contact_Penetrate( PC_TgF4CONTACT_PACKET, CR_TgF4SPHERE, CR_TgF4BOXAA ); // ============================================================================================================================== // }; // END COL ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// }; // END TGS //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////[an error occurred while processing this directive]