//---------------------------------------------------------------------------- // EgalTech 2013-2014 //---------------------------------------------------------------------------- // File : SceneGeom.cpp Data : 10.02.14 Versione : 1.5b1 // Contenuto : Implementazione della gestione geometria della classe scena. // // // // Modifiche : 10.02.14 DS Creazione modulo. // // //---------------------------------------------------------------------------- //--------------------------- Include ---------------------------------------- #include "stdafx.h" #include "Scene.h" #include "ObjOldGraphics.h" #include "ObjNewGraphics.h" #include "/EgtDev/Include/EgtILogger.h" #include "/EgtDev/Include/EGnStringUtils.h" #include "/EgtDev/Include/EGkFrame3d.h" #include "/EgtDev/Include/EgtPointerOwner.h" #include "/EgtDev/Include/EGkGdbIterator.h" #include "/EgtDev/Include/EGkGeoVector3d.h" #include "/EgtDev/Include/EGkGeoPoint3d.h" #include "/EgtDev/Include/EGkCurve.h" #include "/EgtDev/Include/EGkCurveComposite.h" #include "/EgtDev/Include/EGkSurfTriMesh.h" #include "/EgtDev/Include/EGkExtText.h" #include "/EgtDev/Include/EGkGdbFunct.h" using namespace std ; //------------------------------ Constants ----------------------------------- const int OGLMAT_DIM = 16 ; //------------------------------ Local functions ----------------------------- static bool FrameToOpenGlMatrix( const Frame3d& frFrame, double Matrix[OGLMAT_DIM]) ; static ObjEGrGraphics* CreateObjEGrGraphics( bool bNewWay) ; static bool CalcCurveTipArrow( const PolyLine& plCrv, PolyLine& plArr) ; //---------------------------------------------------------------------------- bool Scene::UpdateExtension( void) { BBox3d b3Ext ; if ( m_pGeomDB == nullptr || ! m_pGeomDB->GetLocalBBox( GDB_ID_ROOT, b3Ext, BBF_ONLY_VISIBLE)) return false ; return SetExtension( b3Ext) ; } //---------------------------------------------------------------------------- bool Scene::SetMark( Color colMark) { m_colMark = colMark ; return true ; } //---------------------------------------------------------------------------- bool Scene::DrawGroup( int nId, int nPass, MdStMk cParent) { // creo un iteratore PtrOwner pIter( CreateGdbIterator( m_pGeomDB)) ; if ( ! ::IsValid( pIter)) return false ; // recupero il gruppo if ( ! pIter->GoTo( nId)) return false ; // eseguo il disegno return DrawGroup( *pIter, nPass, cParent) ; } //---------------------------------------------------------------------------- bool Scene::DrawGroup( const IGdbIterator& iIter, int nPass, MdStMk cParent) { // recupero il riferimento del gruppo Frame3d frFrame ; if ( ! iIter.GetGroupFrame( frFrame)) return false ; // se non è identità, lo aggiungo sullo stack delle matrici MODELVIEW di OpenGL bool bMatrix = ( frFrame.GetType() != Frame3d::TOP || ! frFrame.Orig().IsSmall()) ; if ( bMatrix) { glPushMatrix() ; double Matrix[OGLMAT_DIM] ; if ( FrameToOpenGlMatrix( frFrame, Matrix)) glMultMatrixd( Matrix) ; } // creo un iteratore PtrOwner pIter( CreateGdbIterator( m_pGeomDB)) ; if ( ! ::IsValid( pIter)) return false ; // scandisco il gruppo for ( bool bNext = pIter->GoToFirstInGroup( iIter) ; bNext ; bNext = pIter->GoToNext()) { // leggo il tipo di oggetto int nGdbType = pIter->GetGdbType() ; // recupero e aggiorno il modo dell'oggetto int nMode = GDB_MD_STD ; pIter->GetMode( nMode) ; nMode = ::CalcMode( nMode, cParent.nMode) ; // recupero e aggiorno lo stato dell'oggetto int nStat = GDB_ST_ON ; pIter->GetStatus( nStat) ; nStat = ::CalcStatus( nStat, cParent.nStat) ; nStat = ::AdjustStatusWithMode( nStat, nMode) ; // recupero e aggiorno la marcatura dell'oggetto int nMark = GDB_MK_OFF ; pIter->GetMark( nMark) ; nMark = ::CalcMark( nMark, cParent.nMark) ; // se oggetto geometrico if ( nGdbType == GDB_TY_GEO) { // se non nascosto, lo disegno if ( nStat != GDB_ST_OFF) { if ( ! DrawGeoObj( *pIter, nPass, MdStMk( nMode, nStat, nMark))) return false ; } } // se gruppo else if ( nGdbType == GDB_TY_GROUP) { // se non nascosto, lo disegno if ( nStat != GDB_ST_OFF) { if ( ! DrawGroup( *pIter, nPass, MdStMk( nMode, nStat, nMark))) return false ; } } } // se necessario, ripristino lo stack delle matrici if ( bMatrix) glPopMatrix() ; return true ; } //---------------------------------------------------------------------------- bool Scene::DrawGeoObj( const IGdbIterator& iIter, int nPass, MdStMk siObj) { // recupero l'oggetto geometrico e il suo tipo IGeoObj* pGeoObj = (const_cast(&iIter))->GetGeoObj() ; if ( pGeoObj == nullptr) return false ; int nGeoType = pGeoObj->GetType() ; // se non esiste grafica associata, la creo if ( pGeoObj->GetObjGraphics() == nullptr) { ObjEGrGraphics* pGraphics = CreateObjEGrGraphics( m_bNewWay) ; if ( pGraphics == nullptr) return false ; pGraphics->SetScene( this) ; pGeoObj->SetObjGraphics( pGraphics) ; } // se la grafica associata non è valida la ricalcolo ObjEGrGraphics* pGraphics = GetObjEGrGraphics( pGeoObj) ; if ( ! pGraphics->IsValid()) { // recupero il colore Color cCol ; if ( ! iIter.GetCalcMaterial( cCol)) cCol = m_colDef ; // se vettore if ( nGeoType == GEO_VECT3D) { // recupero il vettore const IGeoVector3d* pVector = GetGeoVector3d( pGeoObj) ; if ( pVector == nullptr) return false ; // calcolo la grafica PolyLine PL ; pVector->GetDrawWithArrowHead( 0.1, 10, PL) ; pGraphics->Clear() ; pGraphics->AddColor( cCol) ; pGraphics->AddPolyLine( PL) ; } // se punto else if ( nGeoType == GEO_PNT3D) { // recupero il punto const IGeoPoint3d* pPoint = GetGeoPoint3d( pGeoObj) ; if ( pPoint == nullptr) return false ; // calcolo la grafica pGraphics->Clear() ; pGraphics->AddColor( cCol) ; pGraphics->AddPoint( pPoint->GetPoint()) ; } // se riferimento else if ( nGeoType == GEO_FRAME3D) { // recupero il riferimento const IGeoFrame3d* pFrame = GetGeoFrame3d( pGeoObj) ; if ( pFrame == nullptr) return false ; // aggiorno la grafica (colori speciali) PolyLine plX, plY, plZ ; pFrame->GetDrawWithArrowHeads( 10, 0.1, plX, plY, plZ) ; pGraphics->Clear() ; pGraphics->AddColor( RED) ; pGraphics->AddPolyLine( plX) ; pGraphics->AddColor( GREEN) ; pGraphics->AddPolyLine( plY) ; pGraphics->AddColor( BLUE) ; pGraphics->AddPolyLine( plZ) ; } // se curva else if ( ( nGeoType & GEO_CURVE) != 0) { // recupero la curva const ICurve* pCurve = GetCurve( pGeoObj) ; if ( pCurve == nullptr) return false ; // calcolo la grafica PolyLine PL ; pCurve->ApproxWithLines( 0.005, 5, PL) ; pGraphics->Clear() ; pGraphics->AddColor( cCol) ; pGraphics->AddPolyLine( PL) ; // eventuali segni ausiliari (frecce,...) Point3d ptStart ; if ( PL.GetFirstPoint( ptStart)) pGraphics->AddPoint( ptStart, true) ; PolyLine PLA ; if ( CalcCurveTipArrow( PL, PLA)) pGraphics->AddPolyLine( PLA, true) ; } // se superficie trimesh else if ( nGeoType == SRF_TRIMESH) { // recupero la superficie const ISurfTriMesh* pSTM = GetSurfTriMesh( pGeoObj) ; if ( pSTM == nullptr) return false ; // recupero il materiale Material mMat ; if ( ! iIter.GetCalcMaterial( mMat)) mMat.Set( m_colDef) ; // impostazioni iniziali pGraphics->Clear() ; pGraphics->AddColor( cCol) ; // per wireframe pGraphics->AddMaterial( mMat.GetAmbient(), mMat.GetDiffuse(), mMat.GetSpecular(), mMat.GetShininess()) ; pGraphics->AddBackMaterial( GetSurfBackColor( mMat.GetDiffuse())) ; pGraphics->StartTriangles( pSTM->GetTriangleNum()) ; // ciclo sui triangoli della superficie Triangle3d Tria ; TriNormals3d TNrms ; int nId = pSTM->GetFirstTriangle( Tria) ; while ( nId != SVT_NULL) { pSTM->GetTriangleSmoothNormals( nId, TNrms) ; pGraphics->AddTriangle( Tria, TNrms) ; nId = pSTM->GetNextTriangle( nId, Tria) ; } pGraphics->EndTriangles() ; } // se testo else if ( nGeoType == EXT_TEXT) { // recupero il testo const IExtText* pTXT = GetExtText( pGeoObj) ; if ( pTXT == nullptr) return false ; // calcolo la grafica POLYLINELIST lstPL ; pTXT->ApproxWithLines( 0.01, 5, lstPL) ; pGraphics->Clear() ; pGraphics->AddColor( cCol) ; POLYLINELIST::iterator Iter ; for ( Iter = lstPL.begin() ; Iter != lstPL.end() ; ++ Iter) pGraphics->AddPolyLine( *Iter) ; } } // se hiddenline if ( m_nShowMode == SM_HIDDENLINE) { // in prima passata disegno solo le superfici if ( nPass == 1 && ( nGeoType & GEO_SURF) == 0) return true ; } // se shading if ( m_nShowMode == SM_SHADING) { // in prima passata disegno solo le superfici if ( nPass == 1 && ( nGeoType & GEO_SURF) == 0) return true ; // in seconda passata disegno solo dimensioni 0 e curve if ( nPass == 2 && ( nGeoType & GEO_SURF) != 0) return true ; } // se richiesto, visualizzo la grafica associata bool bShowAux = false ; if ( ( nGeoType & GEO_CURVE) != 0 && m_bShowCurveDirection) bShowAux = true ; return pGraphics->Draw( siObj.nStat, siObj.nMark, bShowAux) ; } //---------------------------------------------------------------------------- bool Scene::DeleteObjGraphicsGroup( int nId) { // creo un iteratore PtrOwner pIter( CreateGdbIterator( m_pGeomDB)) ; if ( ! ::IsValid( pIter)) return false ; // scandisco il gruppo bool bNext = pIter->GoToFirstInGroup( nId) ; while ( bNext) { // leggo il tipo di nodo int nGdbType = pIter->GetGdbType() ; // se oggetto geometrico if ( nGdbType == GDB_TY_GEO) { // lo recupero IGeoObj* pGeoObj = pIter->GetGeoObj() ; if ( pGeoObj == nullptr) return false ; // ne cancello l'eventuale parte grafica ObjEGrGraphics* pGraph = GetObjEGrGraphics( pGeoObj) ; if ( pGraph != nullptr && pGraph->GetScene() == this) pGeoObj->SetObjGraphics( nullptr) ; } // se gruppo else if ( nGdbType == GDB_TY_GROUP) { // ripeto sugli oggetti dello stesso if ( ! DeleteObjGraphicsGroup( pIter->GetId())) return false ; } // passo al successivo bNext = pIter->GoToNext() ; } return true ; } //------------------------------ Local functions ----------------------------- //---------------------------------------------------------------------------- static bool FrameToOpenGlMatrix( const Frame3d& frFrame, double Matrix[OGLMAT_DIM]) { if ( frFrame.GetType() == Frame3d::ERR) return false ; Matrix[0] = frFrame.VersX().x ; Matrix[1] = frFrame.VersX().y ; Matrix[2] = frFrame.VersX().z ; Matrix[3] = 0 ; Matrix[4] = frFrame.VersY().x ; Matrix[5] = frFrame.VersY().y ; Matrix[6] = frFrame.VersY().z ; Matrix[7] = 0 ; Matrix[8] = frFrame.VersZ().x ; Matrix[9] = frFrame.VersZ().y ; Matrix[10] = frFrame.VersZ().z ; Matrix[11] = 0 ; Matrix[12] = frFrame.Orig().x ; Matrix[13] = frFrame.Orig().y ; Matrix[14] = frFrame.Orig().z ; Matrix[15] = 1 ; return true ; } //---------------------------------------------------------------------------- static ObjEGrGraphics* CreateObjEGrGraphics( bool bNewWay) { if ( bNewWay) return ( new ObjNewGraphics) ; else return ( new ObjOldGraphics) ; } //---------------------------------------------------------------------------- static bool CalcCurveTipArrow( const PolyLine& plCrv, PolyLine& plArr) { // pulisco la polilinea per la freccia plArr.Clear() ; // verifico effettiva esistenza della polilinea approssimante la curva if ( plCrv.GetLineNbr() < 1) return false ; // recupero dati ultimo tratto della curva double dU1, dU2 ; Point3d ptTip, ptPrev ; if ( ! plCrv.GetLastULine( &dU1, &ptPrev, &dU2, &ptTip)) return false ; Vector3d vtDir = ptTip - ptPrev ; double dLen = vtDir.Len() ; if ( dLen < EPS_SMALL) return false ; vtDir /= dLen ; double dLenRef = 0 ; if ( ( dU2 - dU1) > 100 * EPS_PARAM) dLenRef = dLen / ( dU2 - dU1) ; // lunghezza della freccia const double MAX_LEN_ARR = 3 ; const double MIN_LEN_ARR = 0.1 ; const double LEN_COEFF = 0.25 ; double dLenArr = LEN_COEFF * dLenRef ; if ( dLenArr > MAX_LEN_ARR) dLenArr = MAX_LEN_ARR ; else if ( dLenArr < MIN_LEN_ARR) dLenArr = MIN_LEN_ARR ; // disegno freccia const double A_WIDTH_COEFF = 0.3 ; Frame3d frF ; frF.Set( ptTip, vtDir) ; plArr.AddUPoint( 0, ptTip) ; Point3d ptP1 = ORIG + Vector3d( A_WIDTH_COEFF, 0, -1) * dLenArr ; ptP1.ToGlob( frF) ; plArr.AddUPoint( 1, ptP1) ; Point3d ptP2 = ORIG + Vector3d( -A_WIDTH_COEFF, 0, -1) * dLenArr ; ptP2.ToGlob( frF) ; plArr.AddUPoint( 2, ptP2) ; plArr.AddUPoint( 3, ptTip) ; return true ; }