// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-==-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= //
//  »Project«   Talina Gaming System (TgS) (∂)
//  »File«      TgS Common - Geometry 3D - Sphere.i_inc
//  »Author«    Andrew Aye (EMail: mailto:andrew.aye@gmail.com, Web: http://www.andrewaye.com)
//  »Version«   4.0
// ------------------------------------------------------------------------------------------------------------------------------ //
//  Copyright: © 2002-2010, 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".
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-==-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= //

TgINLINE TgVOID V(tgGM_Constructor_SP)( V(PCU_TgSPHERE) ptgSP0 )
{
    V(tgGM_Reset_SP)( ptgSP0 );
}


TgINLINE TgVOID V(tgGM_Reset_SP)( V(PCU_TgSPHERE) ptgSP0 )
{
    ptgSP0->m_tvOrigin = V(F_SETP_ELEM)( MKL(0.0), MKL(0.0), MKL(0.0) );
    ptgSP0->m_tyRadius = MKL(0.0);
    ptgSP0->m_tyRadiusSq = MKL(0.0);
}


TgINLINE TgBOOL V(tgGM_Is_Valid_SP)( V(CPCU_TgSPHERE) ptgSP1 )
{
    if (!V(F_Is_Point_Valid)( &ptgSP1->m_tvOrigin ) || F(tgCM_NaN)( ptgSP1->m_tyRadius ) || F(tgCM_NaN)( ptgSP1->m_tyRadiusSq ))
    {
        return (TgFALSE);
    };

    return (TgTRUE);
}


TgINLINE V(TgVEC) V(tgGM_Support_Point_SP)( V(CPCU_TgSPHERE) ptgSP1, V(CPCU_TgVEC) ptvDN )
{
    TgGEOM_ASSERT_PARAM(V(tgGM_Is_Valid_SP)( ptgSP1 ) && V(F_Is_Vector_Valid)( ptvDN ) && F(tgCM_NR1)( V(F_LSQ)( ptvDN ) ));

    return (V(F_MAD_SVV)(ptgSP1->m_tyRadius, ptvDN, &ptgSP1->m_tvOrigin));
}


TgINLINE TYPE V(tgGM_Volume_SP)( V(CPCU_TgSPHERE) ptgSP1 )
{
    TgGEOM_ASSERT_PARAM(V(tgGM_Is_Valid_SP)( ptgSP1 ));
    return (MKL(2.0)*F(TgKT_TWO_PI)*ptgSP1->m_tyRadiusSq*ptgSP1->m_tyRadius/MKL(3.0));
}


TgINLINE TYPE V(tgGM_Area_SP)( V(CPCU_TgSPHERE) ptgSP1 )
{
    TgGEOM_ASSERT_PARAM(V(tgGM_Is_Valid_SP)( ptgSP1 ));
    return (MKL(2.0)*F(TgKT_TWO_PI)*ptgSP1->m_tyRadiusSq);
}


TgINLINE TgVOID V(tgGM_BA_SP)( V(PCU_TgBOXAA) ptgBA0, V(CPCU_TgSPHERE) ptgSP1 )
{
    TgGEOM_ASSERT_PARAM(V(tgGM_Is_Valid_SP)( ptgSP1 ));

    V(tgGM_Init_SP_BA)( ptgBA0, &ptgSP1->m_tvOrigin, ptgSP1->m_tyRadius );
}


TgINLINE TgVOID V(tgGM_Sweep_BA_SP)( V(PCU_TgBOXAA) ptgBA0, V(CPCU_TgSPHERE) ptgSP1, V(CPCU_TgVEC) ptvDT )
{
    TgGEOM_ASSERT_PARAM(V(F_Is_Vector_Valid)( ptvDT ));

    V(tgGM_BA_SP)( ptgBA0, ptgSP1 );
    V(tgGM_Sweep_BA)( ptgBA0, ptvDT );
}


TgINLINE TgVOID V(tgGM_Project_SP)( PCU_TYPE ptyMin, PCU_TYPE ptyMax, V(CPCU_TgSPHERE) ptgSP1, V(CPCU_TgVEC) ptvDN )
{
    const TYPE                          tyS0_AX = V(F_DOT_VV)( &ptgSP1->m_tvOrigin, ptvDN );

    TgGEOM_ASSERT_PARAM(V(tgGM_Is_Valid_SP)( ptgSP1 ) && V(F_Is_Vector_Valid)( ptvDN ) && F(tgCM_NR1)( V(F_LSQ)( ptvDN ) ));

    *ptyMin = tyS0_AX - ptgSP1->m_tyRadius;
    *ptyMax = tyS0_AX + ptgSP1->m_tyRadius;
}


TgINLINE TgBOOL V(tgGM_Is_Contained_SP)( V(CPCU_TgSPHERE) ptgSP1, V(CPCU_TgVEC) ptvS0 )
{
    V(C_TgVEC)                          tvX0 = V(F_SUB_VV)( ptvS0, &ptgSP1->m_tvOrigin );

    TgGEOM_ASSERT_PARAM(V(tgGM_Is_Valid_SP)( ptgSP1 ) && V(F_Is_Vector_Valid)( ptvS0 ));

    return (V(F_LSQ)( &tvX0 ) < ptgSP1->m_tyRadiusSq);
}


TgINLINE TgVOID V(tgGM_TX_SP)( V(PCU_TgSPHERE) ptgSP0, M34(CPCU_TgMAT) ptmM0 )
{
    TgGEOM_ASSERT_PARAM(!M34(F_NaN)( ptmM0 ));

    ptgSP0->m_tvOrigin = V(F_TX_P_34)( ptmM0, &ptgSP0->m_tvOrigin );
}


TgINLINE TgVOID V(tgGM_Copy_TX_SP)( V(PCU_TgSPHERE) ptgSP0, V(CPCU_TgSPHERE) ptgSP1, M34(CPCU_TgMAT) ptmM0 )
{
    TgGEOM_ASSERT_PARAM(V(tgGM_Is_Valid_SP)( ptgSP1 ) && !M34(F_NaN)( ptmM0 ));

    ptgSP0->m_tvOrigin = V(F_TX_P_34)( ptmM0, &ptgSP1->m_tvOrigin );
    ptgSP0->m_tyRadius = ptgSP1->m_tyRadius;
    ptgSP0->m_tyRadiusSq = ptgSP1->m_tyRadiusSq;
}


TgINLINE TgVOID V(tgGM_Init_SP)( V(PCU_TgSPHERE) ptgSP0, V(CPCU_TgVEC) ptvS0, const TYPE tyRad )
{
    V(tgGM_Set_Origin_SP)( ptgSP0, ptvS0 );
    V(tgGM_Set_Radius_SP)( ptgSP0, tyRad );
}


TgINLINE TgVOID V(tgGM_Copy_SP)( V(PCU_TgSPHERE) ptgSP0, V(CPCU_TgSPHERE) ptgSP1 )
{
    TgGEOM_ASSERT_PARAM(V(tgGM_Is_Valid_SP)( ptgSP1 ));

    ptgSP0->m_tvOrigin = ptgSP1->m_tvOrigin;
    ptgSP0->m_tyRadius = ptgSP1->m_tyRadius;
    ptgSP0->m_tyRadiusSq = ptgSP1->m_tyRadiusSq;
}


TgINLINE TgVOID V(tgGM_Set_Origin_SP)( V(PCU_TgSPHERE) ptgSP0, V(CPCU_TgVEC) ptvS0 )
{
    TgGEOM_ASSERT_PARAM(V(F_Is_Point_Valid)( ptvS0 ));

    ptgSP0->m_tvOrigin = *ptvS0;
}


TgINLINE TgVOID V(tgGM_Set_Radius_SP)( V(PCU_TgSPHERE) ptgSP0, const TYPE tyRad )
{
    TgGEOM_ASSERT_PARAM(!F(tgCM_NaN)( tyRad ) && tyRad > MKL(0.0));

    ptgSP0->m_tyRadius = tyRad;
    ptgSP0->m_tyRadiusSq = tyRad*tyRad;
}


TgINLINE V(CP_TgVEC) V(tgGM_Query_Origin_SP)( V(CPCU_TgSPHERE) ptgSP1 )
{
    return (&ptgSP1->m_tvOrigin);
}

TgINLINE TYPE V(tgGM_Query_Radius_SP)( V(CPCU_TgSPHERE) ptgSP1 )
{
    return (ptgSP1->m_tyRadius);
}


TgINLINE TYPE V(tgGM_Query_Radius_Sq_SP)( V(CPCU_TgSPHERE) ptgSP1 )
{
    return (ptgSP1->m_tyRadiusSq);
}


//TgINLINE TgVOID V(tgGM_M_TX_SP)( V(PCU_TgSPHERE) ptgSP0, M34(CPCU_TgMAT) ptmM0 )
//{
//    TgGEOM_ASSERT_PARAM(!M34(F_NaN)( ptmM0 ));
//    ptgSP0->m_tvOrigin = V(tgGM_M_TX)( ptmM0, ptgSP0->m_tvOrigin );
//};
//
//
//TgINLINE TgVOID V(tgGM_M_TX_SP)( V(PCU_TgSPHERE) ptgSP0, V(CPCU_TgSPHERE) ptgSP1, M34(CPCU_TgMAT) ptmM0 )
//{
//    TgGEOM_ASSERT_PARAM(V(tgGM_Is_Valid_SP)( ptgSP1 ) && !M34(F_NaN)( ptmM0 ));
//
//    ptgSP0->m_tvOrigin = V(tgGM_M_TX)( ptmM0, ptgSP1->m_tvOrigin );
//    ptgSP0->m_tyRadius = ptgSP1->m_tyRadius;
//    ptgSP0->m_tyRadiusSq = ptgSP1->m_tyRadiusSq;
//};