Home

Resume

Blog

Teikitu


/* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-==-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
/*  »Project«   Teikitu Gaming System (TgS) (∂)
    »File«      TgS Collision - F - Box-Box.c_inc
    »Keywords«  Collision;Distance;Closest;Intersect;Penetrate;Sweep;Box;
    »Author«    Andrew Aye (EMail: mailto:andrew.aye@gmail.com, Web: http://www.andrewaye.com)
    »Version«   4.51 / »GUID« A9981407-3EC9-42AF-8B6F-8BE6DD919615                                                                                                        */
/*   -------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
/*  Copyright: © 2002-2017, 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:
        Redistribution of source code must retain this copyright notice, this list of conditions and the following disclaimers.
        Redistribution 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.
    The name of the author may not 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".                                                   */
/* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-==-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
/* == Collision ========================================================================================================================================================= */

/* -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-. */
/*  File Local Functions                                                                                                                                                  */
/* -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-. */

static TgBOOL                               V(tgCO_F_BX_Penetrate_Axis_Seperation_BX)( V(PC_STg2_CO_Axis_Result), V(CPC_TgBOX), V(CPC_TgBOX) );
static TgRESULT                             V(tgCO_F_BX_Penetrate_Box_Axis_BX)( V(PC_STg2_CO_Packet), V(PC_STg2_CO_Axis_Result), V(CPC_TgBOX), V(CPC_TgBOX) );




/* -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-. */
/*  Public Functions                                                                                                                                                      */
/* -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-. */

/* -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-. */
/*  File Local Functions                                                                                                                                                  */
/* -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-. */

/* ---- V(tgCO_F_BX_Penetrate_Axis_Seperation_BX) ----------------------------------------------------------------------------------------------------------------------- */
/* Input:  sBX0, sBX1: Box primitives                                                                                                                                     */
/* Output: sAxS: Structure holds the resulting axis separation information necessary to create a contact set.                                                             */
/* Return: False if a separating axis exists, true otherwise                                                                                                              */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
static TgBOOL V(tgCO_F_BX_Penetrate_Axis_Seperation_BX)( V(PC_STg2_CO_Axis_Result) psAxS, V(CPC_TgBOX) psBX0, V(CPC_TgBOX) psBX1 )
{
    TYPE                                fMinBox0, fMaxBox0, fMinBox1, fMaxBox1;
    TgBOOL                              bUseAxis[3] = { TgTRUE, TgTRUE, TgTRUE };
    TgSINT32                            iIndex;
    TgUINT32                            iBox0, iBox1;

    /* -- Axis: Box Face/Plane Normals -- */

    for (iIndex = 0; iIndex < 3; ++iIndex)
    {
        /* Determine the extents of the primitives along the chosen axis. */

        V(C_TgVEC)                          vAxisUnit0 = psBX0->m.m.avAxis[iIndex];
        const TYPE                          fB0_AU = V(F_DOT)(&psBX0->m.m.vOrigin, &vAxisUnit0);

        fMinBox0 = fB0_AU - psBX0->m_vExtent.m_aData[iIndex];
        fMaxBox0 = fB0_AU + psBX0->m_vExtent.m_aData[iIndex];
        V(tgGM_BX_Project)(&fMinBox1, &fMaxBox1, psBX1, &vAxisUnit0);

        if (fMaxBox1 < fMinBox0 || fMinBox1 > fMaxBox0) /* Separation Test. */
        {
            return (TgFALSE);
        };

        {   /* Selection of the best (minimal depth) axis. */
            const TYPE                          fMinDepth = fMaxBox1 - fMinBox0;
            const TYPE                          fMaxDepth = fMaxBox0 - fMinBox1;
            C_TgBOOL                            bNegAxis = fMinDepth > fMaxDepth;

            if ((bNegAxis ? fMaxDepth : fMinDepth) < psAxS->m_fDepth)
            {
                psAxS->m_vNormal = bNegAxis ? vAxisUnit0 : V(F_NEG)(&vAxisUnit0);
                psAxS->m_fDepth = bNegAxis ? fMaxDepth : fMinDepth;
                psAxS->m_iAxis = bNegAxis ? iIndex + 3 : iIndex;
            };
        };

        /*  Check this unit axis of box 0 against the three axis of box 1.  If there is a match then we mark this axis to be ignored during the cross product phase. */

        if (
            F(tgCM_NR1)(V(F_DOT)(psBX1->m.m.avAxis + 0, &vAxisUnit0)) ||
            F(tgCM_NR1)(V(F_DOT)(psBX1->m.m.avAxis + 1, &vAxisUnit0)) ||
            F(tgCM_NR1)(V(F_DOT)(psBX1->m.m.avAxis + 2, &vAxisUnit0))
        )
        {
            bUseAxis[iIndex] = TgFALSE;
        };

        /* Determine the extents of the primitives along the chosen axis. */

        {
            V(C_TgVEC)                          vAxisUnit1 = psBX1->m.m.avAxis[iIndex];
            const TYPE                          fB1_AU = V(F_DOT)(&psBX1->m.m.vOrigin, &vAxisUnit1);

            V(tgGM_BX_Project)(&fMinBox0, &fMaxBox0, psBX0, &vAxisUnit1);
            fMinBox1 = fB1_AU - psBX1->m_vExtent.m_aData[iIndex];
            fMaxBox1 = fB1_AU + psBX1->m_vExtent.m_aData[iIndex];

            if (fMaxBox1 < fMinBox0 || fMinBox1 > fMaxBox0) /* Separation Test. */
            {
                return (TgFALSE);
            }
            else
            {   /* Selection of the best (minimal depth) axis. */
                const TYPE                          fMinDepth = fMaxBox1 - fMinBox0;
                const TYPE                          fMaxDepth = fMaxBox0 - fMinBox1;
                C_TgBOOL                            bNegAxis = fMinDepth > fMaxDepth;

                if ((bNegAxis ? fMaxDepth : fMinDepth) < psAxS->m_fDepth)
                {
                    psAxS->m_vNormal = bNegAxis ? vAxisUnit1 : V(F_NEG)(&vAxisUnit1);
                    psAxS->m_fDepth = bNegAxis ? fMaxDepth : fMinDepth;
                    psAxS->m_iAxis = bNegAxis ? iIndex + 9 : iIndex + 6;
                };
            };
        };
    };

    /* -- Axis: Axis-Box Cross Product -- */

    for (iBox0 = 0; iBox0 < 3; ++iBox0)
    {
        if (!bUseAxis[iBox0])
        {
            continue;
        };

        for (iBox1 = 0; iBox1 < 3; ++iBox1)
        {
            /* Axis is created by taking the cross product of the triangle edge and a box axis. */
            TYPE                                fAxis;
            V(C_TgVEC)                          vAxis = V(F_UCX_LEN)(&fAxis, psBX1->m.m.avAxis + iBox1, psBX0->m.m.avAxis + iBox0);

            if (F(tgCM_NR0)(fAxis)) /* Sanity/Parallel check for the resulting vector. */
            {
                continue;
            };

            V(tgGM_BX_Project)(&fMinBox0, &fMaxBox0, psBX0, &vAxis);
            V(tgGM_BX_Project)(&fMinBox1, &fMaxBox1, psBX1, &vAxis);

            if (fMaxBox1 < fMinBox0 || fMinBox1 > fMaxBox0) /* Separation Test. */
            {
                return (TgFALSE);
            }
            else
            {   /* Selection of the best (minimal depth) axis. */
                const TYPE                          fMinDepth = fMaxBox1 - fMinBox0;
                const TYPE                          fMaxDepth = fMaxBox0 - fMinBox1;
                C_TgBOOL                            bNegAxis = fMinDepth > fMaxDepth;

                if ((bNegAxis ? fMaxDepth : fMinDepth) < psAxS->m_fDepth)
                {
                    psAxS->m_vNormal = bNegAxis ? vAxis : V(F_NEG)(&vAxis);
                    psAxS->m_fDepth = bNegAxis ? fMaxDepth : fMinDepth;
                    psAxS->m_iAxis = iBox0 * 3 + iBox1 + (bNegAxis ? 21 : 12);
                };
            };
        };
    };

    return (TgTRUE);
}


/* ---- V(tgCO_F_BX_Penetrate_Box_Axis_BX) --------------------------------------------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
static TgRESULT V(tgCO_F_BX_Penetrate_Box_Axis_BX)(
    V(PC_STg2_CO_Packet) UNUSED_PARAM psPacket, V(PC_STg2_CO_Axis_Result) psAxS, V(CPC_TgBOX) psBX0, V(CPC_TgBOX) UNUSED_PARAM psBX1)
{
    V(STg2_CO_Axis_Project)             sConfig;

    V(tgCO_F_BX_Axis_ProjInfo)(&sConfig, &psAxS->m_vNormal, psBX0);

    switch (sConfig.m_iMinID)
    {
        case 1:
        { /* Vertex-Face Contact */

            return (KTgS_OK);
        };
        case 2:
        { /* Edge-Face Contact */

            return (KTgS_OK);
        };
        case 4:
        { /* Face-Face Contact */

            return (KTgS_OK);
        };
        default:
            TgS_NO_DEFAULT( return (KTgE_FAIL) );
    };
}