Files
EgtGeomKernel/CDeCapsTria.cpp
T
DarioS 3f2b6b2115 EgtGeomKernel :
- aggiunte prime funzione per verifica collisione con oggetto capsule
- piccoli aggiornamenti alle verifiche di collisione.
2022-05-16 07:51:57 +02:00

90 lines
3.4 KiB
C++

//----------------------------------------------------------------------------
// EgalTech 2022-2022
//----------------------------------------------------------------------------
// File : CDeCapsTria.cpp Data : 14.05.22 Versione : 2.4e2
// Contenuto : Implementazione della verifica di collisione tra
// Capsule (cilindro con estremità semisferiche) e Triangle3d.
//
//
// Modifiche :14.05.22 DS Creazione modulo.
//
//
//----------------------------------------------------------------------------
//--------------------------- Include ----------------------------------------
#include "stdafx.h"
#include "CDeCapsTria.h"
#include "CDeSpheTria.h"
#include "ProjPlane.h"
#include "/EgtDev/Include/EGkPolygon3d.h"
#include "/EgtDev/Include/EGkIntersLinePlane.h"
#include "/EgtDev/Include/EGkDistPointTria.h"
#include "/EgtDev/Include/EGkIntersLineSphere.h"
using namespace std ;
//----------------------------------------------------------------------------
bool
CDeSimpleCapsTria( const Point3d& ptP1, const Point3d& ptP2, double dR, const Triangle3d& trTria)
{
// vedi Ericson, Real-Time Collision Detection, pag. 226 (Nettle method)
// Dati della capsule come sfera che si muove
Point3d ptC = ptP1 ;
Vector3d vtDir = ptP2 - ptP1 ;
double dLen = vtDir.Len() ;
if ( dLen < EPS_SMALL)
return CDeSimpleSpheTria( Media( ptP1, ptP2), dR, trTria) ;
vtDir /= dLen ;
if ( vtDir * trTria.GetN() > 0) {
vtDir.Invert() ;
ptC = ptP2 ;
}
// Determinazione primo possibile punto di contatto della sfera con il piano
Point3d ptD = ptC - trTria.GetN() * dR ;
// Intersezione della linea di movimento di questo punto con il piano del triangolo
Point3d ptP ;
int nLpRes = IntersLinePlane( ptD, vtDir, 1, trTria.GetPlane(), ptP, false) ;
// Se non c'è intersezione passante
if ( nLpRes != ILPT_YES) {
// se il centro dista dal piano non meno del raggio, allora non c'è sicuramente collisione
double dDist = DistPointPlane( ptP, trTria.GetPlane()) ;
if ( abs( dDist) >= dR)
return false ;
// !!! DA FARE !!!!
// si deve intersecare l'asse del capsule con i cilindri centrati sui lati del triangolo
// se intersezione inferiore a dLen allora collisione
// altrimenti si deve intersecare l'asse del capsule con le sfere centrate sui vertici del triangolo
// se intersezione inferiore a dLen allora collisione
// per ora salto
return false ;
}
// Determino la posizione dell'intersezione rispetto al triangolo
DistPointTriangle dptDist( ptP, trTria) ;
// Se l'intersezione sta nel triangolo
double dSqDist ;
if ( dptDist.GetSqDist( dSqDist) && dSqDist < 4 * SQ_EPS_SMALL) {
double dPos = ( ptP - ptD) * vtDir ;
return ( dPos > -dR && dPos < dLen) ;
}
// Altrimenti, recupero il punto del triangolo più vicino all'intersezione
Point3d ptQ ;
if ( dptDist.GetMinDistPoint( ptQ)) {
Point3d ptI1, ptI2 ;
int nLsRes = IntersLineSphere( ptQ, -vtDir, ptC, dR, ptI1, ptI2) ;
if ( nLsRes != ILST_SEC)
return false ;
double dPos = ( ptQ - ptI1) * vtDir ;
return ( dPos > -dR && dPos < dLen) ;
}
return false ;
}
//----------------------------------------------------------------------------
bool
CDeCapsTria( const Point3d& ptP1, const Point3d& ptP2, double dR, double dSafeDist, const Triangle3d& trTria)
{
return CDeSimpleCapsTria( ptP1, ptP2, dR + max( 0., dSafeDist), trTria) ;
}