EgtGeomKernel 1.5e1 :
- in TriMesh migliorato lo smooth delle normali - in TriMesh aggiunta generazione per rivoluzione - migliorati gestione e aggiornamento materiali.
This commit is contained in:
+322
-10
@@ -17,6 +17,7 @@
|
||||
#include "GeoObjFactory.h"
|
||||
#include "NgeWriter.h"
|
||||
#include "NgeReader.h"
|
||||
#include "DistPointLine.h"
|
||||
#include "Triangulate.h"
|
||||
#include "\EgtDev\Include\EGkStringUtils3d.h"
|
||||
#include "\EgtDev\Include\EGkPolyLine.h"
|
||||
@@ -225,8 +226,9 @@ bool
|
||||
SurfTriMesh::GetTriangleSmoothNormal( int nT, int nV, Vector3d& vtN) const
|
||||
{
|
||||
// recupero tutti i triangoli attorno al vertice
|
||||
bool bCirc ;
|
||||
INTVECTOR vT ;
|
||||
int nTria = GetAllTriaAroundVertex( m_vTria[nT].nIdVert[nV], vT) ;
|
||||
int nTria = GetAllTriaAroundVertex( m_vTria[nT].nIdVert[nV], vT, bCirc) ;
|
||||
if ( nTria < 1)
|
||||
return false ;
|
||||
|
||||
@@ -241,23 +243,44 @@ SurfTriMesh::GetTriangleSmoothNormal( int nT, int nV, Vector3d& vtN) const
|
||||
if ( nPos == -1)
|
||||
return false ;
|
||||
|
||||
// medio le normali, finché non incontro degli spigoli
|
||||
// medio le normali, finché non incontro degli spigoli
|
||||
vtN = m_vTria[nT].vtN ;
|
||||
const double COS_DEV_LIM = cos( 18 * DEGTORAD) ;
|
||||
const double COS_DEV_LIM = cos( 22.5 * DEGTORAD) ;
|
||||
// parto dal triangolo e vado in direzione positiva
|
||||
for ( int i = nPos + 1 ; i < int( vT.size()) ; ++ i) {
|
||||
int nLim = nPos ;
|
||||
for ( int i = NextIndAroundVertex( nPos, nTria, bCirc) ;
|
||||
i != nPos && i < int( vT.size()) ;
|
||||
i = NextIndAroundVertex( i, nTria, bCirc)) {
|
||||
if ( m_vTria[vT[nPos]].vtN * m_vTria[vT[i]].vtN >= COS_DEV_LIM)
|
||||
vtN += m_vTria[vT[i]].vtN ;
|
||||
else
|
||||
break ;
|
||||
nLim = i ;
|
||||
}
|
||||
// parto dal triangolo e vado in direzione negativa
|
||||
for ( int i = nPos - 1 ; i >= 0 ; -- i) {
|
||||
for ( int i = PrevIndAroundVertex( nPos, nTria, bCirc) ;
|
||||
i != nLim && i >= 0 ;
|
||||
i = PrevIndAroundVertex( i, nTria, bCirc)) {
|
||||
if ( m_vTria[vT[nPos]].vtN * m_vTria[vT[i]].vtN >= COS_DEV_LIM)
|
||||
vtN += m_vTria[vT[i]].vtN ;
|
||||
else
|
||||
break ;
|
||||
}
|
||||
|
||||
//// parto dal triangolo e vado in direzione positiva
|
||||
//for ( int i = nPos + 1 ; i < int( vT.size()) ; ++ i) {
|
||||
// if ( m_vTria[vT[nPos]].vtN * m_vTria[vT[i]].vtN >= COS_DEV_LIM)
|
||||
// vtN += m_vTria[vT[i]].vtN ;
|
||||
// else
|
||||
// break ;
|
||||
//}
|
||||
//// parto dal triangolo e vado in direzione negativa
|
||||
//for ( int i = nPos - 1 ; i >= 0 ; -- i) {
|
||||
// if ( m_vTria[vT[nPos]].vtN * m_vTria[vT[i]].vtN >= COS_DEV_LIM)
|
||||
// vtN += m_vTria[vT[i]].vtN ;
|
||||
// else
|
||||
// break ;
|
||||
//}
|
||||
vtN.Normalize() ;
|
||||
|
||||
return true ;
|
||||
@@ -486,7 +509,7 @@ SurfTriMesh::FindVertexInTria( int nV, int nT, int& nK) const
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
int
|
||||
SurfTriMesh::GetAllTriaAroundVertex( int nV, INTVECTOR& vT) const
|
||||
SurfTriMesh::GetAllTriaAroundVertex( int nV, INTVECTOR& vT, bool& bCirc) const
|
||||
{
|
||||
const int MAX_VT_SIZE = 512 ;
|
||||
|
||||
@@ -516,8 +539,10 @@ SurfTriMesh::GetAllTriaAroundVertex( int nV, INTVECTOR& vT) const
|
||||
} while ( nTa != nT && nTa != SVT_NULL && vT.size() < MAX_VT_SIZE) ;
|
||||
|
||||
// se sono ritornato al triangolo di partenza ho fatto un giro e concluso la ricerca
|
||||
if ( nTa == nT)
|
||||
if ( nTa == nT) {
|
||||
bCirc = true ;
|
||||
return int( vT.size()) ;
|
||||
}
|
||||
|
||||
// altrimenti, devo cercare i triangoli adiacenti con lo stesso vertice in CW
|
||||
nTa = nT ;
|
||||
@@ -534,9 +559,30 @@ SurfTriMesh::GetAllTriaAroundVertex( int nV, INTVECTOR& vT) const
|
||||
vT.insert( vT.begin(), nTa) ;
|
||||
} while ( nTa != nT && nTa != SVT_NULL && vT.size() < MAX_VT_SIZE) ;
|
||||
|
||||
bCirc = ( nTa == nT) ;
|
||||
return int( vT.size()) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
int
|
||||
SurfTriMesh::NextIndAroundVertex( int nInd, int nSize, bool bCirc) const
|
||||
{
|
||||
nInd = nInd + 1 ;
|
||||
if ( bCirc && nInd >= nSize)
|
||||
nInd = nInd % nSize ;
|
||||
return nInd ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
int
|
||||
SurfTriMesh::PrevIndAroundVertex( int nInd, int nSize, bool bCirc) const
|
||||
{
|
||||
nInd = nInd - 1 ;
|
||||
if ( bCirc && nInd < 0)
|
||||
nInd = ( nInd + nSize) % nSize ;
|
||||
return nInd ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
SurfTriMesh::AdjustAdjacencies( void)
|
||||
@@ -567,10 +613,11 @@ SurfTriMesh::AdjustAdjacencies( void)
|
||||
int nVf = m_vTria[i].nIdVert[Next(j)] ;
|
||||
// indice altro vertice in altro triangolo
|
||||
int k ;
|
||||
int nN ;
|
||||
int nN ;
|
||||
bool bCirc ;
|
||||
INTVECTOR vT ;
|
||||
// triangoli con il vertice all'inizio dello half-edge
|
||||
nN = GetAllTriaAroundVertex( nVi, vT) ;
|
||||
nN = GetAllTriaAroundVertex( nVi, vT, bCirc) ;
|
||||
for ( int l = 0 ; l < nN ; ++ l) {
|
||||
int nTi = vT[l] ;
|
||||
if ( nTi != i) {
|
||||
@@ -589,7 +636,7 @@ SurfTriMesh::AdjustAdjacencies( void)
|
||||
}
|
||||
}
|
||||
// triangoli con il vertice alla fine dello half-edge
|
||||
nN = GetAllTriaAroundVertex( nVf, vT) ;
|
||||
nN = GetAllTriaAroundVertex( nVf, vT, bCirc) ;
|
||||
for ( int l = 0 ; l < nN ; ++ l) {
|
||||
int nTf = vT[l] ;
|
||||
if ( nTf != i) {
|
||||
@@ -801,6 +848,271 @@ SurfTriMesh::CreateByExtrusion( const PolyLine& PL, const Vector3d& vtExtr)
|
||||
return AdjustTopology() ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
SurfTriMesh::CreateByRevolution( const PolyLine& PL, const Point3d& ptAx, const Vector3d& vtAx,
|
||||
double dAngRot, double dStepRot)
|
||||
{
|
||||
// verifico che l'asse di rotazione sia non nullo
|
||||
if ( vtAx.IsSmall())
|
||||
return false ;
|
||||
// verifico che l'angolo di rotazione sia significativo e non superi un giro
|
||||
if ( fabs( dAngRot) < EPS_ANG_SMALL)
|
||||
return false ;
|
||||
if ( fabs( dAngRot) > ANG_FULL)
|
||||
dAngRot = _copysign( ANG_FULL, dAngRot) ;
|
||||
// verifico se rotazione completa
|
||||
bool bFullRev = ( fabs( fabs( dAngRot) - ANG_FULL) < EPS_ANG_SMALL) ;
|
||||
// aggiusto il valore dell'angolo di step
|
||||
const double MIN_STEP_ROT = 1 ;
|
||||
const double MAX_STEP_ROT = 90 ;
|
||||
if ( fabs( dStepRot) < MIN_STEP_ROT)
|
||||
dStepRot = _copysign( MIN_STEP_ROT, dAngRot) ;
|
||||
else if ( fabs( dStepRot) > MAX_STEP_ROT)
|
||||
dStepRot = _copysign( MAX_STEP_ROT, dAngRot) ;
|
||||
else
|
||||
dStepRot = _copysign( dStepRot, dAngRot) ;
|
||||
// calcolo il numero di step
|
||||
int nStep = int( dAngRot / dStepRot) ;
|
||||
nStep = max( nStep, 1) ;
|
||||
dStepRot = dAngRot / nStep ;
|
||||
if ( bFullRev)
|
||||
-- nStep ;
|
||||
|
||||
// verifico che la polilinea non attraversi l'asse di rivoluzione o lo tocchi in punti interni
|
||||
if ( ! VeryfyPolylineForRevolution( PL, ptAx, vtAx)) {
|
||||
LOG_ERROR( GetEGkLogger(), "StmCreateByRevolution : polyline inside meets axis")
|
||||
return false ;
|
||||
}
|
||||
|
||||
// verifico se la polilinea è chiusa
|
||||
bool bClosed = PL.IsClosed() ;
|
||||
|
||||
// costruisco la mesh
|
||||
int nPointNbr = PL.GetPointNbr() ;
|
||||
if ( ! Init( ( 1 + nStep) * nPointNbr, ( 1 + nStep) * nPointNbr))
|
||||
return false ;
|
||||
|
||||
// inserisco il primo punto della polilinea e i suoi ruotati
|
||||
int nP = 0 ;
|
||||
int nV = -1 ;
|
||||
Point3d ptP ;
|
||||
// recupero il punto
|
||||
if ( ! PL.GetFirstPoint( ptP))
|
||||
return false ;
|
||||
++ nP ;
|
||||
// inserisco il primo vertice
|
||||
if ( AddVertex( ptP) == SVT_NULL)
|
||||
return false ;
|
||||
++ nV ;
|
||||
// verifico se il punto giace sull'asse
|
||||
bool bPrevOnAx = DistPointLine( ptP, ptAx, vtAx, 1, false).IsSmall() ;
|
||||
int nVPrevOnAx = nV ;
|
||||
// se non è sull'asse, inserisco le copie ruotate
|
||||
if ( ! bPrevOnAx) {
|
||||
for ( int i = 1 ; i <= nStep ; ++i) {
|
||||
ptP.Rotate( ptAx, vtAx, dStepRot * DEGTORAD) ;
|
||||
if ( AddVertex( ptP) == SVT_NULL)
|
||||
return false ;
|
||||
++ nV ;
|
||||
}
|
||||
}
|
||||
// ciclo sui punti della polilinea (per inserire vertice e suoi ruotati + 2 triangoli per ogni punto)
|
||||
int nIdV[4] ;
|
||||
while ( PL.GetNextPoint( ptP)) {
|
||||
// incremento numero punto
|
||||
++ nP ;
|
||||
// se polilinea aperta o non è l'ultimo punto
|
||||
if ( ! bClosed || nP < nPointNbr) {
|
||||
// aggiungo il primo vertice
|
||||
if ( AddVertex( ptP) == SVT_NULL)
|
||||
return false ;
|
||||
++ nV ;
|
||||
// verifico se il punto giace sull'asse
|
||||
bool bOnAx = DistPointLine( ptP, ptAx, vtAx, 1, false).IsSmall() ;
|
||||
// ciclo sugli step
|
||||
for ( int i = 1 ; i <= nStep ; ++i) {
|
||||
// se non è sull'asse, inserisco le copie ruotate
|
||||
if ( ! bOnAx) {
|
||||
ptP.Rotate( ptAx, vtAx, dStepRot * DEGTORAD) ;
|
||||
if ( AddVertex( ptP) == SVT_NULL)
|
||||
return false ;
|
||||
++ nV ;
|
||||
}
|
||||
// per i controlli già fatti non è possibile avere contemp. prec e corr su asse
|
||||
// se il precedente è sull'asse, aggiungo un solo triangolo
|
||||
if ( bPrevOnAx) {
|
||||
nIdV[0] = nVPrevOnAx ;
|
||||
nIdV[1] = nV ;
|
||||
nIdV[2] = nV - 1 ;
|
||||
if ( AddTriangle( nIdV) == SVT_NULL)
|
||||
return false ;
|
||||
}
|
||||
// se il corrente è sull'asse, aggiungo un solo triangolo
|
||||
else if ( bOnAx) {
|
||||
nIdV[0] = nV - ( nStep + 2) + i ;
|
||||
nIdV[1] = nIdV[0] + 1 ;
|
||||
nIdV[2] = nV ;
|
||||
if ( AddTriangle( nIdV) == SVT_NULL)
|
||||
return false ;
|
||||
}
|
||||
// altrimenti aggiungo due triangoli
|
||||
else {
|
||||
nIdV[0] = nV - ( nStep + 2) ;
|
||||
nIdV[1] = nIdV[0] + 1 ;
|
||||
nIdV[2] = nV ;
|
||||
nIdV[3] = nV - 1 ;
|
||||
if ( ! AddBiTriangle( nIdV))
|
||||
return false ;
|
||||
}
|
||||
}
|
||||
// se rivoluzione completa, aggiungo i due triangoli di chiusura
|
||||
if ( bFullRev) {
|
||||
// per i controlli già fatti non è possibile avere contemp. prec e corr su asse
|
||||
// se il precedente è sull'asse, aggiungo un solo triangolo
|
||||
if ( bPrevOnAx) {
|
||||
nIdV[0] = nVPrevOnAx ;
|
||||
nIdV[1] = nV - nStep ;
|
||||
nIdV[2] = nV ;
|
||||
if ( AddTriangle( nIdV) == SVT_NULL)
|
||||
return false ;
|
||||
}
|
||||
// se il corrente è sull'asse, aggiungo un solo triangolo
|
||||
else if ( bOnAx) {
|
||||
nIdV[0] = nV - 1 ;
|
||||
nIdV[1] = nV - ( nStep + 1) ;
|
||||
nIdV[2] = nV ;
|
||||
if ( AddTriangle( nIdV) == SVT_NULL)
|
||||
return false ;
|
||||
}
|
||||
// altrimenti aggiungo due triangoli
|
||||
else {
|
||||
nIdV[0] = nV - ( nStep + 1) ;
|
||||
nIdV[1] = nV - ( 2 * nStep + 1) ;
|
||||
nIdV[2] = nV - nStep ;
|
||||
nIdV[3] = nV ;
|
||||
if ( ! AddBiTriangle( nIdV))
|
||||
return false ;
|
||||
}
|
||||
}
|
||||
bPrevOnAx = false ;
|
||||
}
|
||||
// altrimenti ultimo punto di polilinea chiusa
|
||||
else {
|
||||
for ( int i = 1 ; i <= nStep ; ++i) {
|
||||
// non devo aggiungere i vertici, perchè coincidono con quelli iniziali
|
||||
// aggiungo triangolo in basso a sinistra
|
||||
nIdV[0] = nV - nStep + i - 1 ; nIdV[1] = nV - nStep + i ; nIdV[2] = i ;
|
||||
if ( AddTriangle( nIdV) == SVT_NULL)
|
||||
return false ;
|
||||
// aggiungo triangolo in alto a destra
|
||||
nIdV[0] = nV - nStep + i - 1 ; nIdV[1] = i ; nIdV[2] = i - 1 ;
|
||||
if ( AddTriangle( nIdV) == SVT_NULL)
|
||||
return false ;
|
||||
}
|
||||
// se rivoluzione completa, aggiungo i due triangoli di chiusura
|
||||
if ( bFullRev) {
|
||||
// aggiungo triangolo in basso a sinistra
|
||||
nIdV[0] = nV ; nIdV[1] = nV - nStep ; nIdV[2] = 0 ;
|
||||
if ( AddTriangle( nIdV) == SVT_NULL)
|
||||
return false ;
|
||||
// aggiungo triangolo in alto a destra
|
||||
nIdV[0] = nV ; nIdV[1] = 0 ; nIdV[2] = nStep ;
|
||||
if ( AddTriangle( nIdV) == SVT_NULL)
|
||||
return false ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// sistemo la topologia
|
||||
return AdjustTopology() ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
SurfTriMesh::VeryfyPolylineForRevolution( const PolyLine& PL, const Point3d& ptAx, const Vector3d& vtAx) const
|
||||
{
|
||||
// calcolo un riferimento con origine ptAx e asseZ vtAx
|
||||
Frame3d frAx ;
|
||||
if ( ! frAx.Set( ptAx, vtAx))
|
||||
return false ;
|
||||
|
||||
// numero di segmenti della polilinea
|
||||
int nTotSeg = PL.GetLineNbr() ;
|
||||
// flag di chiusa
|
||||
bool bClosed = PL.IsClosed() ;
|
||||
|
||||
// recupero il primo punto e lo porto nel riferimento Ax e quindi lo proietto su XY
|
||||
Point3d ptPp ;
|
||||
if ( ! PL.GetFirstPoint( ptPp))
|
||||
return false ;
|
||||
ptPp.ToLoc( frAx) ;
|
||||
ptPp.z = 0 ;
|
||||
|
||||
// calcolo la distanza tra i segmenti della polilinea portati nel piano XY del rif Ax e l'origine
|
||||
int nSeg = 0 ;
|
||||
Point3d ptPc ;
|
||||
while ( PL.GetNextPoint( ptPc)) {
|
||||
// punto corrente
|
||||
ptPc.ToLoc( frAx) ;
|
||||
ptPc.z = 0 ;
|
||||
++ nSeg ;
|
||||
// verifico distanza
|
||||
if ( DistPointLine( ORIG, ptPp, ptPc).IsSmall()) {
|
||||
if ( bClosed ||
|
||||
( ! ( nSeg == 1 && AreSamePointNear( ORIG, ptPp)) &&
|
||||
! ( nSeg == nTotSeg && AreSamePointNear( ORIG, ptPc))))
|
||||
return false ;
|
||||
}
|
||||
// salvo punto
|
||||
ptPp = ptPc ;
|
||||
}
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
SurfTriMesh::AddBiTriangle( const int nIdVert[4])
|
||||
{
|
||||
// 0 <- 3
|
||||
// | |
|
||||
// 1 -> 2
|
||||
int nIdV[3] ;
|
||||
// se la diagonale 0->2 è più corta della 1->3
|
||||
if ( SqDist( m_vVert[nIdVert[0]].ptP, m_vVert[nIdVert[2]].ptP) <=
|
||||
SqDist( m_vVert[nIdVert[1]].ptP, m_vVert[nIdVert[3]].ptP)) {
|
||||
// triangolo 0->1->2
|
||||
nIdV[0] = nIdVert[0] ;
|
||||
nIdV[1] = nIdVert[1] ;
|
||||
nIdV[2] = nIdVert[2] ;
|
||||
if ( AddTriangle( nIdV) == SVT_NULL)
|
||||
return false ;
|
||||
// triangolo 0->2->3
|
||||
nIdV[0] = nIdVert[0] ;
|
||||
nIdV[1] = nIdVert[2] ;
|
||||
nIdV[2] = nIdVert[3] ;
|
||||
if ( AddTriangle( nIdV) == SVT_NULL)
|
||||
return false ;
|
||||
}
|
||||
// altrimenti uso la 1->3
|
||||
else {
|
||||
// triangolo 0->1->3
|
||||
nIdV[0] = nIdVert[0] ;
|
||||
nIdV[1] = nIdVert[1] ;
|
||||
nIdV[2] = nIdVert[3] ;
|
||||
if ( AddTriangle( nIdV) == SVT_NULL)
|
||||
return false ;
|
||||
// triangolo 1->2->3
|
||||
nIdV[0] = nIdVert[1] ;
|
||||
nIdV[1] = nIdVert[2] ;
|
||||
nIdV[2] = nIdVert[3] ;
|
||||
if ( AddTriangle( nIdV) == SVT_NULL)
|
||||
return false ;
|
||||
}
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
SurfTriMesh::GetLocalBBox( BBox3d& b3Loc) const
|
||||
|
||||
Reference in New Issue
Block a user