Home

Resume

Blog

Teikitu


/* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-==-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
/*  »Project«   Teikitu Gaming System (TgS) (∂)
    »File«      TgS Collision - F - Box [Axis Separation].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 ========================================================================================================================================================= */

/* ---- V(tgCO_F_BX_Axis_ProjInfo) -------------------------------------------------------------------------------------------------------------------------------------- */
/* Input:  pvAxis: Axis of separation being tested                                                                                                                        */
/* Input:  psBX0: Box primitive                                                                                                                                           */
/* Output: tgConfig: Holds the resulting information for the axis separation tests for this primitive                                                                     */
/*   Their are a few different ways, depending on relative orientation, that a box's vertices can be mapped onto a line (axis.)                                           */
/*  First, if the axis is identical to one of the box's axes then the four points on each face that is normal to the line will be                                         */
/*  projected only onto one unique point ( two in total for the entire box ).  The second way would be if the line is parallel to                                         */
/*  one of the box's faces.  The four vertices defining the face to which the line is parallel would each map to a unique point.                                          */
/*  However, the other four points would map one to one to the existing projections since the edge formed between the two faces                                           */
/*  is normal to the line in question (by definition).  The last case has the line being in arbitrary orientation, non-collinear                                          */
/*  or co-planar to the box in any way.                                                                                                                                   */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
TgVOID V(tgCO_F_BX_Axis_ProjInfo)( V(PC_STg2_CO_Axis_Project) psConfig, V(CPC_TgVEC) pvAxis, V(CPC_TgBOX) psBX0 )
{
    /* Project the vertices onto the normal from the first triangle. */

    const TYPE                          fAX_X0 = V(F_DOT)(psBX0->m.m.avAxis + 0, pvAxis);
    const TYPE                          fAX_X1 = V(F_DOT)(psBX0->m.m.avAxis + 1, pvAxis);
    const TYPE                          fAX_X2 = V(F_DOT)(psBX0->m.m.avAxis + 2, pvAxis);
    const TYPE                          fABS_AX_EX0 = psBX0->m_vExtent.m.x*F(tgPM_ABS)(fAX_X0);
    const TYPE                          fABS_AX_EX1 = psBX0->m_vExtent.m.y*F(tgPM_ABS)(fAX_X1);
    const TYPE                          fABS_AX_EX2 = psBX0->m_vExtent.m.z*F(tgPM_ABS)(fAX_X2);

    /* This is a direct sort using the projections as the key. */

    switch ((F(tgCM_NR0)(fAX_X0) ? 0 : 1) + (F(tgCM_NR0)(fAX_X1) ? 0 : 2) + (F(tgCM_NR0)(fAX_X2) ? 0 : 4))
    {
        case 7:
        { /* Unique maximal and minimal vertices */

            V(C_TgVEC)                          vK0 = V(F_MUL_SV)(fABS_AX_EX0, psBX0->m.m.avAxis + 0);
            V(C_TgVEC)                          vK1 = V(F_MUL_SV)(fABS_AX_EX1, psBX0->m.m.avAxis + 1);
            V(C_TgVEC)                          vK2 = V(F_MUL_SV)(fABS_AX_EX2, psBX0->m.m.avAxis + 2);
            V(C_TgVEC)                          vK4 = V(F_ADD)(&vK0, &vK1);
            V(C_TgVEC)                          vK3 = V(F_ADD)(&vK4, &vK2);

            psConfig->m_avMinVert[0] = V(F_SUB)(&psBX0->m.m.vOrigin, &vK3);
            psConfig->m_avMaxVert[0] = V(F_ADD)(&psBX0->m.m.vOrigin, &vK3);
            psConfig->m_iMinID = 1;
            psConfig->m_iMaxID = 1;

            break;
        }

        case 6: /* Parallel to the x-axis normal-defined plane (perpendicular to x-axis). */

            if (fAX_X1 > MKL(0.0))
            {
                psConfig->m_avMinVert[0] = V(tgGM_BX_Calc_Point_Index)(psBX0, (fAX_X2 > MKL(0.0) ? 0 : 4));
                psConfig->m_avMinVert[1] = V(tgGM_BX_Calc_Point_Index)(psBX0, (fAX_X2 > MKL(0.0) ? 1 : 5));
                psConfig->m_avMaxVert[0] = V(tgGM_BX_Calc_Point_Index)(psBX0, (fAX_X2 > MKL(0.0) ? 6 : 2));
                psConfig->m_avMaxVert[1] = V(tgGM_BX_Calc_Point_Index)(psBX0, (fAX_X2 > MKL(0.0) ? 7 : 3));

            }
            else
            {
                psConfig->m_avMinVert[0] = V(tgGM_BX_Calc_Point_Index)(psBX0, (fAX_X2 > MKL(0.0) ? 2 : 6));
                psConfig->m_avMinVert[1] = V(tgGM_BX_Calc_Point_Index)(psBX0, (fAX_X2 > MKL(0.0) ? 3 : 7));
                psConfig->m_avMaxVert[0] = V(tgGM_BX_Calc_Point_Index)(psBX0, (fAX_X2 > MKL(0.0) ? 4 : 0));
                psConfig->m_avMaxVert[1] = V(tgGM_BX_Calc_Point_Index)(psBX0, (fAX_X2 > MKL(0.0) ? 5 : 1));
            };

            psConfig->m_iMinID = 2;
            psConfig->m_iMaxID = 2;

            break;

        case 5: /* Parallel to the y-axis normal-defined plane. */

            if (fAX_X0 > MKL(0.0))
            {
                psConfig->m_avMinVert[0] = V(tgGM_BX_Calc_Point_Index)(psBX0, (fAX_X2 > MKL(0.0) ? 0 : 4));
                psConfig->m_avMinVert[1] = V(tgGM_BX_Calc_Point_Index)(psBX0, (fAX_X2 > MKL(0.0) ? 2 : 6));
                psConfig->m_avMaxVert[0] = V(tgGM_BX_Calc_Point_Index)(psBX0, (fAX_X2 > MKL(0.0) ? 5 : 1));
                psConfig->m_avMaxVert[1] = V(tgGM_BX_Calc_Point_Index)(psBX0, (fAX_X2 > MKL(0.0) ? 7 : 3));

            }
            else
            {
                psConfig->m_avMinVert[0] = V(tgGM_BX_Calc_Point_Index)(psBX0, (fAX_X2 > MKL(0.0) ? 1 : 5));
                psConfig->m_avMinVert[1] = V(tgGM_BX_Calc_Point_Index)(psBX0, (fAX_X2 > MKL(0.0) ? 3 : 7));
                psConfig->m_avMaxVert[0] = V(tgGM_BX_Calc_Point_Index)(psBX0, (fAX_X2 > MKL(0.0) ? 4 : 0));
                psConfig->m_avMaxVert[1] = V(tgGM_BX_Calc_Point_Index)(psBX0, (fAX_X2 > MKL(0.0) ? 6 : 2));
            };

            psConfig->m_iMinID = 2;
            psConfig->m_iMaxID = 2;

            break;

        case 4: /* Separation axis is parallel to box z-axis. */

            psConfig->m_avMinVert[0] = V(tgGM_BX_Calc_Point_Index)(psBX0, (fAX_X2 > MKL(0.0) ? 0 : 4));
            psConfig->m_avMinVert[1] = V(tgGM_BX_Calc_Point_Index)(psBX0, (fAX_X2 > MKL(0.0) ? 1 : 5));
            psConfig->m_avMinVert[2] = V(tgGM_BX_Calc_Point_Index)(psBX0, (fAX_X2 > MKL(0.0) ? 2 : 6));
            psConfig->m_avMinVert[3] = V(tgGM_BX_Calc_Point_Index)(psBX0, (fAX_X2 > MKL(0.0) ? 3 : 7));
            psConfig->m_avMaxVert[0] = V(tgGM_BX_Calc_Point_Index)(psBX0, (fAX_X2 > MKL(0.0) ? 4 : 0));
            psConfig->m_avMaxVert[1] = V(tgGM_BX_Calc_Point_Index)(psBX0, (fAX_X2 > MKL(0.0) ? 5 : 1));
            psConfig->m_avMaxVert[2] = V(tgGM_BX_Calc_Point_Index)(psBX0, (fAX_X2 > MKL(0.0) ? 6 : 2));
            psConfig->m_avMaxVert[3] = V(tgGM_BX_Calc_Point_Index)(psBX0, (fAX_X2 > MKL(0.0) ? 7 : 3));

            psConfig->m_iMinID = 4;
            psConfig->m_iMaxID = 4;

            break;

        case 3: /* Parallel to the z-axis normal-defined plane. */

            if (fAX_X0 > MKL(0.0))
            {
                psConfig->m_avMinVert[0] = V(tgGM_BX_Calc_Point_Index)(psBX0, (fAX_X1 > MKL(0.0) ? 0 : 2));
                psConfig->m_avMinVert[1] = V(tgGM_BX_Calc_Point_Index)(psBX0, (fAX_X1 > MKL(0.0) ? 4 : 6));
                psConfig->m_avMaxVert[0] = V(tgGM_BX_Calc_Point_Index)(psBX0, (fAX_X1 > MKL(0.0) ? 3 : 1));
                psConfig->m_avMaxVert[1] = V(tgGM_BX_Calc_Point_Index)(psBX0, (fAX_X1 > MKL(0.0) ? 7 : 5));

            }
            else
            {
                psConfig->m_avMinVert[0] = V(tgGM_BX_Calc_Point_Index)(psBX0, (fAX_X1 > MKL(0.0) ? 1 : 3));
                psConfig->m_avMinVert[1] = V(tgGM_BX_Calc_Point_Index)(psBX0, (fAX_X1 > MKL(0.0) ? 5 : 7));
                psConfig->m_avMaxVert[0] = V(tgGM_BX_Calc_Point_Index)(psBX0, (fAX_X1 > MKL(0.0) ? 2 : 0));
                psConfig->m_avMaxVert[1] = V(tgGM_BX_Calc_Point_Index)(psBX0, (fAX_X1 > MKL(0.0) ? 6 : 4));
            };

            psConfig->m_iMinID = 2;
            psConfig->m_iMaxID = 2;

            break;

        case 2: /* Separation axis is parallel to box y-axis. */

            psConfig->m_avMinVert[0] = V(tgGM_BX_Calc_Point_Index)(psBX0, (fAX_X1 > MKL(0.0) ? 0 : 2));
            psConfig->m_avMinVert[1] = V(tgGM_BX_Calc_Point_Index)(psBX0, (fAX_X1 > MKL(0.0) ? 1 : 3));
            psConfig->m_avMinVert[2] = V(tgGM_BX_Calc_Point_Index)(psBX0, (fAX_X1 > MKL(0.0) ? 4 : 6));
            psConfig->m_avMinVert[3] = V(tgGM_BX_Calc_Point_Index)(psBX0, (fAX_X1 > MKL(0.0) ? 5 : 7));
            psConfig->m_avMaxVert[0] = V(tgGM_BX_Calc_Point_Index)(psBX0, (fAX_X1 > MKL(0.0) ? 2 : 0));
            psConfig->m_avMaxVert[1] = V(tgGM_BX_Calc_Point_Index)(psBX0, (fAX_X1 > MKL(0.0) ? 3 : 1));
            psConfig->m_avMaxVert[2] = V(tgGM_BX_Calc_Point_Index)(psBX0, (fAX_X1 > MKL(0.0) ? 6 : 4));
            psConfig->m_avMaxVert[3] = V(tgGM_BX_Calc_Point_Index)(psBX0, (fAX_X1 > MKL(0.0) ? 7 : 5));

            psConfig->m_iMinID = 4;
            psConfig->m_iMaxID = 4;

            break;

        case 1: /* Separation axis is parallel to box x-axis. */

            psConfig->m_avMinVert[0] = V(tgGM_BX_Calc_Point_Index)(psBX0, (fAX_X0 > MKL(0.0) ? 0 : 5));
            psConfig->m_avMinVert[1] = V(tgGM_BX_Calc_Point_Index)(psBX0, (fAX_X0 > MKL(0.0) ? 2 : 7));
            psConfig->m_avMinVert[2] = V(tgGM_BX_Calc_Point_Index)(psBX0, (fAX_X0 > MKL(0.0) ? 6 : 3));
            psConfig->m_avMinVert[3] = V(tgGM_BX_Calc_Point_Index)(psBX0, (fAX_X0 > MKL(0.0) ? 4 : 1));
            psConfig->m_avMaxVert[0] = V(tgGM_BX_Calc_Point_Index)(psBX0, (fAX_X0 > MKL(0.0) ? 5 : 0));
            psConfig->m_avMaxVert[1] = V(tgGM_BX_Calc_Point_Index)(psBX0, (fAX_X0 > MKL(0.0) ? 7 : 2));
            psConfig->m_avMaxVert[2] = V(tgGM_BX_Calc_Point_Index)(psBX0, (fAX_X0 > MKL(0.0) ? 3 : 6));
            psConfig->m_avMaxVert[3] = V(tgGM_BX_Calc_Point_Index)(psBX0, (fAX_X0 > MKL(0.0) ? 1 : 4));

            psConfig->m_iMinID = 4;
            psConfig->m_iMaxID = 4;

            break;

        default:
            TgS_NO_DEFAULT(return);
    };
}