[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]