[an error occurred while processing this directive]
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-==-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= //
//
//  Project:   Talina Gaming System (TgS) (∂)
//  File:      TgS Collision - Cylinder-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:  tgCY0: Cylinder 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_(CYLINDER,DIM) tgCY1 )
{
    TgBLOCK_FCN_NOOBJ(ETgFAC_COLLISION, 0, ETgTEST_PENETRATE, (((TgUINT)ETgSPHERE<<16)|(TgUINT)ETgCYLINDER))

    TgASSERT((TgSIZE)ptgPacket->m_iStride >= sizeof( P_(CONTACT,DIM) ))
    TgASSERT(tgCY1.Is_Valid() && tgSP0.Is_Valid())

    if (0 == ptgPacket->m_niMaxContact || ptgPacket->m_niContact >= ptgPacket->m_niMaxContact || NULL == ptgPacket->m_ptgContact)
    {
        return (TgE_FAIL);
    };

    T_(VECTOR,DIM)                      tvDS = MATH::F_SUB( tgCY1.Query_Origin(), tgSP0.Query_Origin() );

    // Separating Axis - Cylindrical Principal Axis.

    const TYPE                          tyDS_AX = MATH::F_DOT(tvDS,tgCY1.Query_AxisUnit());
    TYPE                                tyDepth;
        
    tyDepth = tgCY1.Query_Extent() + tgSP0.Query_Radius() - P::ABS(tyDS_AX);

    if (tyDepth < TYPE(0.0))
    {
        return (TgE_NOINTERSECT);
    };

    T_(VECTOR,DIM)                      tvNormal;

    tvNormal = tyDS_AX < TYPE(0.0) ? MATH::F_NEG( tgCY1.Query_AxisUnit() ) : tgCY1.Query_AxisUnit();

    // Separating Axis - Cylindrical Radial Axis.

    TYPE                                tyRT, tyTest;
    C_(VECTOR,DIM)                      tvK0 = MATH::F_MUL( tyDS_AX, tgCY1.Query_AxisUnit() );
    T_(VECTOR,DIM)                      tvRT = MATH::F_NORM( &tyRT, MATH::F_SUB( tvDS, tvK0 ) );
    
    tyTest = tgCY1.Query_Radius() + tgSP0.Query_Radius() - tyRT;

    if (tyTest < TYPE(0.0))
    {
        return (TgE_NOINTERSECT);
    }

    if (tyTest < tyDepth)
    {
        tyDepth = tyTest;
        tvNormal = tvRT;
    };

    // Separating Axis - Minimal Axis Connecting Cylindrical Ring and Sphere Centre.
    //  Dev Note: The origin of the sphere is restricted to being outside of the cylinder.  This biases the contact away from rim
    // collisions, and prevents having to do directional analysis to determine the contact depth.

    if (P::ABS(tyDS_AX) > tgCY1.Query_Extent() && tyRT > tgCY1.Query_Radius())
    {
        T_(VECTOR,DIM)                      tvRIM;

        tvDS = MATH::F_NORM( tvDS );
        tvRIM = MATH::F_NORM( &tyTest, MATH::F_SUB( tgCY1.Calc_Support_Point( MATH::F_NEG( tvDS ) ), tgSP0.Query_Origin() ) );

        tyTest = tgSP0.Query_Radius() - tyTest;

        if (tyTest < TYPE(0.0))
        {
            return (TgE_NOINTERSECT);
        };

        if (tyTest < tyDepth)
        {
            tyDepth = tyTest;
            tvNormal = tvRIM;
        };
    };

    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( tgSP0.Query_Origin(), MATH::F_MUL( tvNormal, tgSP0.Query_Radius() - tyDepth ) );
    ptgContact->m_tvNormal = tvNormal;
    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_TgF4SPHERE, CR_TgF4CYLINDER );


// ============================================================================================================================== //

}; // END COL //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
}; // END TGS //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
[an error occurred while processing this directive]