From 3c0d573c46269728152c87b0ea8a351262d514a8 Mon Sep 17 00:00:00 2001 From: Dario Sassi Date: Fri, 10 Oct 2014 06:36:30 +0000 Subject: [PATCH] EgtGraphics 1.5j1 : - aggiunta gestione selezione con mouse - aggiunta gestione selezione punti notevoli (snap points). --- EgtGraphics.rc | Bin 11390 -> 11398 bytes EgtGraphics.vcxproj | 3 +- EgtGraphics.vcxproj.filters | 5 +- Scene.h | 51 ++++++++++-- SceneBasic.cpp | 136 ++++++++++++++++++++++++++++++-- SceneAux.cpp => SceneDirect.cpp | 69 ++++++++++++++-- SceneGeom.cpp | 29 ++++--- SceneSnap.cpp | 125 +++++++++++++++++++++++++++++ 8 files changed, 386 insertions(+), 32 deletions(-) rename SceneAux.cpp => SceneDirect.cpp (77%) create mode 100644 SceneSnap.cpp diff --git a/EgtGraphics.rc b/EgtGraphics.rc index d78fa677e02491d6d0b8c25f1dbdf25e74e8d59c..12430356b915b024e3e9937f82122e82aa510550 100644 GIT binary patch delta 113 zcmewt(H6Pk6C1lBg8_pMgW=};vi!`s|6C0}~gARk~=5D_IOp|wT1~6wbm` - + + Create Create diff --git a/EgtGraphics.vcxproj.filters b/EgtGraphics.vcxproj.filters index 4de69f3..99e683f 100644 --- a/EgtGraphics.vcxproj.filters +++ b/EgtGraphics.vcxproj.filters @@ -98,7 +98,10 @@ File di origine - + + File di origine + + File di origine diff --git a/Scene.h b/Scene.h index f3087bf..2a4ef25 100644 --- a/Scene.h +++ b/Scene.h @@ -31,6 +31,15 @@ class MdStMk int nMark ; } ; +//---------------------------------------------------------------------------- +struct SelRec { // record di selezione per OpenGL (buffer di GLuint) + GLuint nLen ; // numero di Id sullo stack dei nomi al momento del disegno (sempre 1) + GLuint nZmin ; // Zdepth minima + GLuint nZmax ; // Zdepth massima + GLuint nId ; // nome dell'oggetto +} ; + + //---------------------------------------------------------------------------- class Scene : public IEGrScene { @@ -44,11 +53,17 @@ class Scene : public IEGrScene virtual std::string GetOpenGLInfo( void) ; virtual std::string GetGLSLInfo( void) ; virtual std::string GetPixelFormatInfo( void) ; + virtual IGeomDB* GetGeomDB( void) + { return m_pGeomDB ; } virtual bool RedrawWindow( void) ; virtual bool Resize( int nW, int nH) ; virtual bool SetBackground( Color colBackTop, Color colBackBottom) ; - virtual bool Prepare( void) ; virtual bool Draw( void) ; + virtual bool Select( const Point3d& ptView, int nW, int nH, int& nSel) ; + virtual bool GetSelectedObjs( INTVECTOR& nIds) ; + virtual int GetFirstSelectedObj( void) ; + virtual int GetNextSelectedObj( void) ; + virtual double GetSelectedObjWinZ( int nSel = - 1) ; virtual bool Project( const Point3d& ptWorld, Point3d& ptView) ; virtual bool UnProject( const Point3d& ptView, Point3d& ptWorld) ; virtual void Destroy( void) ; @@ -85,10 +100,15 @@ class Scene : public IEGrScene virtual bool SetExtension( const BBox3d& b3Ext) ; virtual bool UpdateExtension( void) ; virtual bool SetMark( Color colMark) ; - // Aux + // Direct + virtual bool SetGeoLineAttribs( Color GLcol) ; + virtual bool SetGeoLine( const Point3d& ptP1, const Point3d& ptP2) ; + virtual bool ResetGeoLine( void) ; virtual bool SetWinRectAttribs( bool bOutline, Color WRcol) ; virtual bool SetWinRect( const Point3d& ptWinRectP1, const Point3d& ptWinRectP2) ; virtual bool ResetWinRect( void) ; + // Snap + virtual bool GetSelectedSnapPoint( int nSnap, const Point3d& ptWin, int nW, int nH, Point3d& ptSel) ; public : // Basic @@ -110,6 +130,7 @@ class Scene : public IEGrScene bool AdjustDimView( double dHalfWidth, double dHalfHeight) ; bool CalcClippingPlanesFromExtView( void) ; bool Background( void) ; + bool Prepare( void) ; // Camera bool VerifyCamera( void) ; bool CalcDirUp( void) ; @@ -119,8 +140,13 @@ class Scene : public IEGrScene bool DrawGroup( const IGdbIterator& iIter, int nPass, MdStMk siParent) ; bool DrawGeoObj( const IGdbIterator& iIter, int nPass, MdStMk siObj) ; bool DeleteObjGraphicsGroup( int nId) ; - // Aux + // Direct + bool DrawDirect( void) ; + bool DrawGeoLine( void) ; bool DrawWinRect( void) ; + // Snap + bool VerifySnapPoint( const Point3d& ptP, const Point3d& ptWin, double& dMinSqDist) ; + private : HDC m_hDC ; // Device Context @@ -143,6 +169,15 @@ class Scene : public IEGrScene int m_nShowMode ; // modo di visualizzazione (wireframe, hiddenline, shading) bool m_bShowCurveDirection ; // flag di visualizzazione direzione curve + bool m_bSelect ; // flag di selezione attiva + Point3d m_ptSelCent ; // centro di selezione + int m_nSelW ; // larghezza finestra di selezione + int m_nSelH ; // altezza finestra di selezione + int m_nSelNbr ; // numero di selezioni registrate + int m_nSelCurr ; // indice oggetto selezionato corrente + static const int DIM_SEL_BUF = 4096 ; + SelRec m_nSelBuff[DIM_SEL_BUF] ; // buffer per selezione con OpenGL + IGeomDB* m_pGeomDB ; // puntatore al DB geometrico Color m_colDef ; // colore di default Color m_colMark ; // colore per marcatura @@ -155,9 +190,13 @@ class Scene : public IEGrScene double m_dZNear ; // distanza del piano di clipping vicino double m_dZFar ; // distanza del piano di clipping lontano + Color m_colorGL ; // colore per GeoLine + bool m_bGeoLine ; // flag esistenza linea diretta in finestra + Point3d m_ptGeoLineP1 ; // primo estremo della linea diretta + Point3d m_ptGeoLineP2 ; // secondo estremo della linea diretta bool m_bOutlineWR ; // flag per disegno WinRect con solo contorno o pieno Color m_colorWR ; // colore per WinRect - bool m_bWinRect ; // flag esistenza rettangolo temporaneo in finestra - Point3d m_ptWinRectP1 ; // primo estremo del rettangolo temporaneo - Point3d m_ptWinRectP2 ; // secondo estremo del rettangolo temporaneo + bool m_bWinRect ; // flag esistenza rettangolo diretto in finestra + Point3d m_ptWinRectP1 ; // primo estremo del rettangolo diretto + Point3d m_ptWinRectP2 ; // secondo estremo del rettangolo diretto } ; diff --git a/SceneBasic.cpp b/SceneBasic.cpp index 0384d70..59b41f1 100644 --- a/SceneBasic.cpp +++ b/SceneBasic.cpp @@ -56,6 +56,9 @@ Scene::Scene( void) m_colBackBottom.Set( 128, 128, 128) ; // Modalità di visualizzazione m_nShowMode = SM_WIREFRAME ; + // Selezione + m_bSelect = false ; + m_nSelCurr = - 1 ; // GeomData m_pGeomDB = nullptr ; m_colDef.Set( 0, 0, 0) ; @@ -63,7 +66,9 @@ Scene::Scene( void) // Extension SetExtension( BBox3d( -MIN_EXTENSION, -MIN_EXTENSION, -MIN_EXTENSION, MIN_EXTENSION, MIN_EXTENSION, MIN_EXTENSION)) ; - // WinRect + // Direct + m_colorGL.Set( 0, 0, 0) ; + m_bGeoLine = false ; m_bOutlineWR = true ; m_colorWR.Set( 0, 0, 0) ; m_bWinRect = false ; @@ -600,6 +605,13 @@ Scene::Prepare( void) // imposto matrice di proiezione glMatrixMode( GL_PROJECTION) ; glLoadIdentity() ; + if ( m_bSelect) { + // recupero viewport + GLint Viewport[4] ; + glGetIntegerv( GL_VIEWPORT, Viewport) ; + // imposto area di pick + gluPickMatrix( m_ptSelCent.x, ( Viewport[3] - m_ptSelCent.y), m_nSelW, m_nSelH, Viewport) ; + } glOrtho( - m_dHalfWidth, m_dHalfWidth, - m_dHalfHeight, m_dHalfHeight, m_dZNear, m_dZFar) ; // imposto matrice modello/vista @@ -704,7 +716,7 @@ Scene::Draw( void) glDisable( GL_DEPTH_TEST) ; glDisable( GL_LIGHTING) ; glPolygonMode( GL_FRONT_AND_BACK, GL_FILL) ; - DrawWinRect() ; + DrawDirect() ; // aggiorno glFlush() ; @@ -723,6 +735,120 @@ Scene::Draw( void) return true ; } +//---------------------------------------------------------------------------- +int +CompareSelRec( const void* pSr1, const void* pSr2) +{ + if ( ((SelRec*)pSr1)->nZmin > ((SelRec*)pSr2)->nZmin) + return 1 ; + else if ( ((SelRec*)pSr1)->nZmin < ((SelRec*)pSr2)->nZmin) + return - 1 ; + else { + if ( ((SelRec*)pSr1)->nId > ((SelRec*)pSr2)->nId) + return 1 ; + else if ( ((SelRec*)pSr1)->nId < ((SelRec*)pSr2)->nId) + return - 1 ; + else + return 0 ; + } +} + +//---------------------------------------------------------------------------- +bool +Scene::Select( const Point3d& ptSelCenter, int nW, int nH, int& nSel) +{ + // inizializzo selezione + m_bSelect = true ; + m_ptSelCent = ptSelCenter ; + m_nSelW = nW ; + m_nSelH = nH ; + m_nSelNbr = 0 ; + + // sfondo e Zbuffer non interessano + + // imposto la camera, riducendo la viewport all'area di selezione + if ( ! Prepare()) { + m_bSelect = false ; + nSel = m_nSelNbr ; + return false ; + } + + // imposto modalità di selezione + glSelectBuffer( DIM_SEL_BUF, (GLuint*)m_nSelBuff) ; + glRenderMode( GL_SELECT) ; + + // inizializzo stack dei nomi + glInitNames() ; + glPushName( 0) ; + + // eseguo disegno + // disabilito illuminazione + glDisable( GL_LIGHTING) ; + // non imposto glPolygonMode secondo il tipo di rendering perchè ignorato in selezione + // disegno le geometrie del DB in una sola passata + DrawGroup( GDB_ID_ROOT, 1, MdStMk( GDB_MD_STD, GDB_ST_ON, GDB_MK_OFF)) ; + + // pulisco stack nomi + glPopName() ; + + // chiudo modalità selezione, recupero buffer ripristino le matrici di OpenGL + m_nSelNbr = glRenderMode( GL_RENDER) ; + if ( m_nSelNbr < 0) + m_nSelNbr = DIM_SEL_BUF ; + m_bSelect = false ; + Prepare() ; + + // riordino il buffer di selezione secondo la Zdepth minima crescente + qsort( m_nSelBuff, m_nSelNbr, sizeof( SelRec), CompareSelRec) ; + + nSel = m_nSelNbr ; + return true ; +} + +//---------------------------------------------------------------------------- +bool +Scene::GetSelectedObjs( INTVECTOR& nIds) +{ + // inizializzo vettore Id + nIds.clear() ; + try { nIds.reserve( m_nSelNbr) ; } + catch(...) { return false ; } + // inserisco l'Id degli oggetti selezionati + for ( int i = 0 ; i < m_nSelNbr ; ++ i) + nIds.push_back( m_nSelBuff[i].nId) ; + return true ; +} + +//---------------------------------------------------------------------------- +int +Scene::GetFirstSelectedObj( void) +{ + m_nSelCurr = - 1 ; + return GetNextSelectedObj() ; +} + +//---------------------------------------------------------------------------- +int +Scene::GetNextSelectedObj( void) +{ + // fuori dal range + m_nSelCurr ++ ; + if ( m_nSelCurr < 0 || m_nSelCurr >= m_nSelNbr) + return GDB_ID_NULL ; + return m_nSelBuff[m_nSelCurr].nId ; +} + +//---------------------------------------------------------------------------- +double +Scene::GetSelectedObjWinZ( int nSel) +{ + if ( nSel < 0) + nSel = m_nSelCurr ; + if ( nSel < 0 || nSel >= m_nSelNbr) + return 0.5 ; + return 0.5 * ( double( m_nSelBuff[nSel].nZmin) + double( m_nSelBuff[nSel].nZmax)) / UINT_MAX ; +} + /*------------------------------------------------------------------------------------------*/ bool Scene::Project( const Point3d& ptWorld, Point3d& ptView) @@ -741,9 +867,9 @@ Scene::Project( const Point3d& ptWorld, Point3d& ptView) // eseguo la proiezione // l'asse y della vista OpenGL va in alto con l'origine in basso, // quello di Windows va in basso con l'origine in alto - int nRes =gluProject( ptWorld.x, ptWorld.y, ptWorld.z, - ModelView, Projection, Viewport, - &ptView.x, &ptView.y, &ptView.z) ; + int nRes = gluProject( ptWorld.x, ptWorld.y, ptWorld.z, + ModelView, Projection, Viewport, + &ptView.x, &ptView.y, &ptView.z) ; ptView.y = (double) Viewport[3] - ptView.y ; return ( nRes == GL_TRUE) ; diff --git a/SceneAux.cpp b/SceneDirect.cpp similarity index 77% rename from SceneAux.cpp rename to SceneDirect.cpp index d94b15b..fdf4702 100644 --- a/SceneAux.cpp +++ b/SceneDirect.cpp @@ -1,8 +1,8 @@ //---------------------------------------------------------------------------- // EgalTech 2014-2014 //---------------------------------------------------------------------------- -// File : SceneAux.cpp Data : 25.02.14 Versione : 1.5b4 -// Contenuto : Implementazione della gestione ausiliari della classe scena. +// File : SceneDirect.cpp Data : 09.10.14 Versione : 1.5j1 +// Contenuto : Implementazione disegno diretto nella scena. // // // @@ -26,7 +26,34 @@ using namespace std ; -//------------------------------ Constants ----------------------------------- +//---------------------------------------------------------------------------- +bool +Scene::SetGeoLineAttribs( Color GLcol) +{ + m_colorGL = GLcol ; + return true ; +} + +//---------------------------------------------------------------------------- +bool +Scene::SetGeoLine( const Point3d& ptP1, const Point3d& ptP2) +{ + m_bGeoLine = true ; + m_ptGeoLineP1 = ptP1 ; + m_ptGeoLineP2 = ptP2 ; + + return ( ! AreSamePointApprox( m_ptGeoLineP1, m_ptGeoLineP2)) ; +} + +//---------------------------------------------------------------------------- +bool +Scene::ResetGeoLine( void) +{ + bool bOld = m_bGeoLine ; + m_bGeoLine = false ; + + return bOld ; +} //---------------------------------------------------------------------------- bool @@ -58,14 +85,42 @@ Scene::ResetWinRect( void) return bOld ; } +//---------------------------------------------------------------------------- +bool +Scene::DrawDirect( void) +{ + // eseguo disegni diretti + bool bOk = true ; + if ( m_bGeoLine) { + if ( ! DrawGeoLine()) + bOk = false ; + } + if ( m_bWinRect) { + if ( ! DrawWinRect()) + bOk = false ; + } + + return bOk ; +} + +//---------------------------------------------------------------------------- +bool +Scene::DrawGeoLine( void) +{ + // disegno linea in geometria globale + glBegin( GL_LINES) ; + glColor3f( m_colorGL.GetRed(), m_colorGL.GetGreen(), m_colorGL.GetBlue()) ; + glVertex3f( float( m_ptGeoLineP1.x), float( m_ptGeoLineP1.y), float( m_ptGeoLineP1.z)) ; + glVertex3f( float( m_ptGeoLineP2.x), float( m_ptGeoLineP2.y), float( m_ptGeoLineP2.z)) ; + glEnd() ; + + return true ; +} + //---------------------------------------------------------------------------- bool Scene::DrawWinRect( void) { - // verifico sia da disegnare - if ( ! m_bWinRect) - return true ; - // rendo neutre matrici di proiezione e di modello/vista glMatrixMode( GL_PROJECTION) ; glPushMatrix() ; diff --git a/SceneGeom.cpp b/SceneGeom.cpp index 2ce703a..d6302d3 100644 --- a/SceneGeom.cpp +++ b/SceneGeom.cpp @@ -80,6 +80,10 @@ Scene::DrawGroup( int nId, int nPass, MdStMk cParent) bool Scene::DrawGroup( const IGdbIterator& iIter, int nPass, MdStMk cParent) { + // creo un iteratore + PtrOwner pIter( CreateGdbIterator( m_pGeomDB)) ; + if ( IsNull( pIter)) + return false ; // recupero il riferimento del gruppo Frame3d frFrame ; if ( ! iIter.GetGroupFrame( frFrame)) @@ -92,13 +96,10 @@ Scene::DrawGroup( const IGdbIterator& iIter, int nPass, MdStMk cParent) if ( FrameToOpenGlMatrix( frFrame, Matrix)) glMultMatrixd( Matrix) ; } - // creo un iteratore - PtrOwner pIter( CreateGdbIterator( m_pGeomDB)) ; - if ( IsNull( pIter)) - return false ; // scandisco il gruppo + bool bOk = true ; for ( bool bNext = pIter->GoToFirstInGroup( iIter) ; - bNext ; + bNext && bOk ; bNext = pIter->GoToNext()) { // leggo il tipo di oggetto int nGdbType = pIter->GetGdbType() ; @@ -120,7 +121,7 @@ Scene::DrawGroup( const IGdbIterator& iIter, int nPass, MdStMk cParent) // se non nascosto, lo disegno if ( nStat != GDB_ST_OFF) { if ( ! DrawGeoObj( *pIter, nPass, MdStMk( nMode, nStat, nMark))) - return false ; + bOk = false ; } } // se gruppo @@ -128,7 +129,7 @@ Scene::DrawGroup( const IGdbIterator& iIter, int nPass, MdStMk cParent) // se non nascosto, lo disegno if ( nStat != GDB_ST_OFF) { if ( ! DrawGroup( *pIter, nPass, MdStMk( nMode, nStat, nMark))) - return false ; + bOk = false ; } } } @@ -136,7 +137,7 @@ Scene::DrawGroup( const IGdbIterator& iIter, int nPass, MdStMk cParent) if ( bMatrix) glPopMatrix() ; - return true ; + return bOk ; } //---------------------------------------------------------------------------- @@ -293,15 +294,15 @@ Scene::DrawGeoObj( const IGdbIterator& iIter, int nPass, MdStMk siObj) } } - // se hiddenline - if ( m_nShowMode == SM_HIDDENLINE) { + // se hiddenline e non selezione + if ( m_nShowMode == SM_HIDDENLINE && ! m_bSelect) { // in prima passata disegno solo le superfici if ( nPass == 1 && ( nGeoType & GEO_SURF) == 0) return true ; } - // se shading - if ( m_nShowMode == SM_SHADING) { + // se shading e non selezione + if ( m_nShowMode == SM_SHADING && ! m_bSelect) { // in prima passata disegno solo le superfici if ( nPass == 1 && ( nGeoType & GEO_SURF) == 0) return true ; @@ -310,6 +311,10 @@ Scene::DrawGeoObj( const IGdbIterator& iIter, int nPass, MdStMk siObj) return true ; } + // se in selezione, carico il nome + if ( m_bSelect) + glLoadName( iIter.GetId()) ; + // se richiesto, visualizzo la grafica associata bool bShowAux = false ; if ( ( nGeoType & GEO_CURVE) != 0 && m_bShowCurveDirection) diff --git a/SceneSnap.cpp b/SceneSnap.cpp new file mode 100644 index 0000000..de25e69 --- /dev/null +++ b/SceneSnap.cpp @@ -0,0 +1,125 @@ +//---------------------------------------------------------------------------- +// EgalTech 2014-2014 +//---------------------------------------------------------------------------- +// File : SceneSnap.cpp Data : 09.10.14 Versione : 1.5j1 +// Contenuto : Implementazione snap di punti trmite selezione. +// +// +// +// Modifiche : 09.10.14 DS Creazione modulo. +// +// +//---------------------------------------------------------------------------- + +//--------------------------- Include ---------------------------------------- +#include "stdafx.h" +#include "Scene.h" +#include "/EgtDev/Include/EGkGeomDB.h" +#include "/EgtDev/Include/EGkFrame3d.h" +#include "/EgtDev/Include/EGkCurve.h" +#include "/EgtDev/Include/EGkDistPointCurve.h" + + +using namespace std ; + +//---------------------------------------------------------------------------- +bool +Scene::GetSelectedSnapPoint( int nSnap, const Point3d& ptWin, int nW, int nH, Point3d& ptSel) +{ + // verifico siano state selezionate delle entità + int nSel ; + Select( ptWin, nW, nH, nSel) ; + if ( nSel <= 0) + return false ; + // recupero le entità selezionate + INTVECTOR nIds ; + GetSelectedObjs( nIds) ; + // cerco il punto estremo più vicino alla selezione + bool bFound = false ; + double dMinSqDist = INFINITO * INFINITO ; + for ( size_t i = 0 ; i < nIds.size() ; ++ i) { + // recupero geometria e frame dell'entità + const ICurve* pCrv = GetCurve( m_pGeomDB->GetGeoObj( nIds[i])) ; + if ( pCrv == nullptr) + continue ; + Frame3d frEnt ; + if ( ! m_pGeomDB->GetGlobFrame( nIds[i], frEnt)) + continue ; + // recupero il punto + Point3d ptP ; + switch ( nSnap) { + case SP_END : + // punto iniziale + if ( pCrv->GetStartPoint( ptP)) { + ptP.ToGlob( frEnt) ; + if ( VerifySnapPoint( ptP, ptWin, dMinSqDist)) { + bFound = true ; + ptSel = ptP ; + } + } + // punto finale + if ( pCrv->GetEndPoint( ptP)) { + ptP.ToGlob( frEnt) ; + if ( VerifySnapPoint( ptP, ptWin, dMinSqDist)) { + bFound = true ; + ptSel = ptP ; + } + } + break ; + case SP_MID : + if ( pCrv->GetMidPoint( ptP)) { + ptP.ToGlob( frEnt) ; + if ( VerifySnapPoint( ptP, ptWin, dMinSqDist)) { + bFound = true ; + ptSel = ptP ; + } + } + break ; + case SP_CENTER : + if ( pCrv->GetCenterPoint( ptP)) { + ptP.ToGlob( frEnt) ; + if ( VerifySnapPoint( ptP, ptWin, dMinSqDist)) { + bFound = true ; + ptSel = ptP ; + } + } + break ; + case SP_NEAR : + { // il punto di riferimento deriva da XY su viewport e Z da selezione + Point3d ptRefWin( ptWin.x, ptWin.y, GetSelectedObjWinZ( int( i))) ; + Point3d ptRef ; + // lo porto da spazio grafico a spazio geometrico globale + UnProject( ptRefWin, ptRef) ; + // lo porto nel frame della curva + ptRef.ToLoc( frEnt) ; + // determino il punto più vicino della curva a questo + int nFlag ; + DistPointCurve dstPtCurve( ptRef, *pCrv) ; + if ( dstPtCurve.GetMinDistPoint( 0, ptP, nFlag)) { + ptP.ToGlob( frEnt) ; + if ( VerifySnapPoint( ptP, ptWin, dMinSqDist)) { + bFound = true ; + ptSel = ptP ; + } + } + } break ; + } + } + return bFound ; +} + +//---------------------------------------------------------------------------- +bool +Scene::VerifySnapPoint( const Point3d& ptP, const Point3d& ptWin, double& dMinSqDist) +{ + // proietto il punto sulla viewport + Point3d ptWinP ; + Project( ptP, ptWinP) ; + // confronto le distanze + double dSqDist = SqDistXY( ptWin, ptWinP) ; + if ( dSqDist < dMinSqDist) { + dMinSqDist = dSqDist ; + return true ; + } + return false ; +} \ No newline at end of file