[an error occurred while processing this directive]
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-==-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= //
//
//  Project:   Talina Gaming System (TgS) (∂)
//  File:      TgS Collision - Triangle-Point.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".
//
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-==-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= //


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

//
// Triangle Definition: T0(α,β) = P0 + α•E0 + β•E1 | α ε [ 0, 1], β ε [ 0, 1], (α + β) ε [0, 1]
//
// Derivation:
//
//
//         .    .              .    .   
//          . G .               . G .   NOTE: Keep in mind that in regions C, E and G, an obtuse angle can lead
//           .  .                .  .            to having significant projections along the other edge.
//            . .                 . .      E0
//             ..                  ..     .
//              .2                  .  F .
//              |\                  |\  .
//              | \                 | \.
//          B   |  \   F         B  | /.  E
//              | A \               |/  .
//         .....|____\..... E0      .O   .
//             O.     .1           ..     .
//              .      .          . .  D   .
//          C   .   D   .   E    .  .         
//              .        .      . C .         
//              .                   .
//             E1                  E1
//
//     These regions define the closest feature of the triangle when contained in their area.  The point is projected onto the
//    triangle plane, and the region that contains the point is determined.  It is then a simple matter to calculate the resulting
//    distance to the triangle for the point.
//

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




namespace TGS { // START TGS ///////////////////////////////////////////////////////////////////////////////////////////////////////
namespace COL { // START COL ///////////////////////////////////////////////////////////////////////////////////////////////////////

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

// ---- F_ClosestSq ------------------------------------------------------------------------------------------------------------- //
// Input:  tgET0: Edge triangle primitive
// Input:  tvS0: Point
// Output: _tyET0, _tyET1: Parametric parameters to generate point of minimal distance on the triangle
// Return: Minimal distance between the two primitives or negative type max if they intersect or are invalid.
// ------------------------------------------------------------------------------------------------------------------------------ //

template <typename TYPE, int DIM>
TYPE F_ClosestSq( TYPE *ptyET0, TYPE *ptyET1, CR_(ETRI,DIM) tgET0, M_(VECTOR,DIM) tvS0 )
{
    TgASSERT(tgET0.Is_Valid() && MATH::F_Is_Point_Valid(tvS0));

    T_(VECTOR,DIM)                      tvX0 = MATH::F_SUB( tvS0, tgET0.Query_Point0() );
    const TYPE                          tyX0_X0 = MATH::F_LSQ( tvX0 );

    if (tyX0_X0 <= LIMITS<TYPE>::EPSILON)
    {
        // Quick Out - the point is within tolerance of triangle origin.

        *ptyET0 = TYPE(0.0);
        *ptyET1 = TYPE(0.0);

        return (tyX0_X0);
    };

    const TYPE                          tyE0_E0 = MATH::F_LSQ( tgET0.Query_Edge0() );
    const TYPE                          tyE2_E2 = MATH::F_LSQ( tgET0.Query_Edge2() );

    if (tyE0_E0 <= LIMITS<TYPE>::EPSILON || tyE2_E2 <= LIMITS<TYPE>::EPSILON)
    {   // Degenerate triangle - One or both of the edges has a near-zero length
        return (-LIMITS<TYPE>::MAX);
    };

    const TYPE                          tyE0_E2 = -MATH::F_DOT(tgET0.Query_Edge0(),tgET0.Query_Edge2());
    const TYPE                          tyDet = P::ABS(tyE0_E0*tyE2_E2 - tyE0_E2*tyE0_E2);

    if (tyDet <= LIMITS<TYPE>::EPSILON)
    {   // Degenerate triangle - Edges are co-linear (zero-area triangle)
        return (-LIMITS<TYPE>::MAX);
    };

    const TYPE                          tyX0_E0 = MATH::F_DOT(tgET0.Query_Edge0(),tvX0);
    const TYPE                          tyX0_E2 = -MATH::F_DOT(tgET0.Query_Edge2(),tvX0);

    const TYPE                          tyPM0 = tyE2_E2*tyX0_E0 - tyE0_E2*tyX0_E2;
    const TYPE                          tyPM1 = tyE0_E0*tyX0_E2 - tyE0_E2*tyX0_E0;

    TYPE                                tyET0,tyET1;

    // Categorize the point according to how its contained by the edges, and the sum of the edges.

    if (tyPM0 + tyPM1 <= tyDet)
    {
        if (tyPM1 >= TYPE(0.0))
        {
            tyET0 = P::FSEL( tyPM0, tyPM0 / tyDet, TYPE(0.0) );
            tyET1 = P::FSEL( tyPM0, tyPM1 / tyDet, INZ_Limit(tyX0_E2, tyE2_E2) );
        }
        else
        {   
            tyET0 = INZ_Limit(tyX0_E0, tyE0_E0);
            tyET1 = (tyPM0 >= TYPE(0.0) || tyX0_E0 > TYPE(0.0)) ? TYPE(0.0) : INZ_Limit(tyX0_E2, tyE2_E2);
        };
    }
    else
    {
        const TYPE                          tyE1_X1 = MATH::F_DOT( tgET0.Query_Edge1(), MATH::F_SUB( tvS0, tgET0.Query_Point1() ) );
        const TYPE                          tyE1_X2 = MATH::F_DOT( tgET0.Query_Edge1(), MATH::F_SUB( tgET0.Query_Point2(), tvS0 ) );
        const TYPE                          tyE1_E1 = MATH::F_LSQ( tgET0.Query_Edge1() );

        if (tyPM1 >= TYPE(0.0))
        {
            tyET0 = INZ_Limit(tyE1_X2,tyE1_E1);
            tyET1 = (tyPM0 < TYPE(0.0) && tyE1_X2 <= TYPE(0.0)) ? INZ_Limit(tyX0_E2,tyE2_E2) : INZ_Limit(tyE1_X1,tyE1_E1);
        }
        else
        {
            tyET1 = INZ_Limit(tyE1_X1,tyE1_E1);
            tyET0 = tyE1_X1 > TYPE(0.0) ? INZ_Limit(tyE1_X2,tyE1_E1) : INZ_Limit(tyX0_E0,tyE0_E0);
        };
    };

    *ptyET0 = tyET0;
    *ptyET1 = tyET1;

    C_(VECTOR,DIM)                      tvK0 = MATH::F_MUL( tyET0, tgET0.Query_Edge0() );
    C_(VECTOR,DIM)                      tvK1 = MATH::F_MUL( tyET1, tgET0.Query_Edge2() );

    return (MATH::F_LSQ( MATH::F_SUB( tvS0, MATH::F_SUB( MATH::F_ADD( tgET0.Query_Origin(), tvK0 ), tvK1 ) ) ));
};

template TgFLOAT32 F_ClosestSq( P_TgFLOAT32, P_TgFLOAT32, CR_TgF4ETRI, M_TgF4VECTOR );


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

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