//---------------------------------------------------------------------------- // EgalTech 2013-2014 //---------------------------------------------------------------------------- // File : TestEGrView.cpp Data : 05.02.14 Versione : 1.5b3 // Contenuto : Implementazione della classe gestione vista OpenGL. // // // // Modifiche : 29.01.14 DS Creazione modulo. // // //---------------------------------------------------------------------------- //--------------------------- Include ---------------------------------------- #include "stdafx.h" #include "TestEGrView.h" #include "TestEGrUtils.h" #include "SelectDlg.h" #include "resource.h" #include "/EgtDev/Include/EGkGdbConst.h" #include "/EgtDev/Include/EGkGeomDB.h" #include "/EgtDev/Include/EGkCurve.h" #include "/EgtDev/Include/EGkStringUtils3d.h" #include "/EgtDev/Include/EGrScene.h" #include "/EgtDev/Include/EgtPerfCounter.h" #include "/EgtDev/Include/EgtILogger.h" #include "/EgtDev/Include/EgtStringConverter.h" using namespace std ; //---------------------------------------------------------------------------- static const int DIM_SEL = 13 ; //---------------------------------------------------------------------------- #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif //---------------------------------------------------------------------------- BEGIN_MESSAGE_MAP( TestEGrView, CWnd) ON_WM_PAINT() ON_WM_LBUTTONDOWN() ON_WM_LBUTTONUP() ON_WM_RBUTTONUP() ON_WM_MBUTTONDOWN() ON_WM_MBUTTONUP() ON_WM_MOUSEMOVE() ON_WM_MOUSEWHEEL() ON_COMMAND_RANGE( IDM_ENDPOINT, IDM_NEARPOINT, OnSelSnapPoint) END_MESSAGE_MAP() //---------------------------------------------------------------------------- TestEGrView::TestEGrView( void) { m_pDC = nullptr ; m_pScene = nullptr ; m_nStatus = ST_NULL ; m_nOldStatus = ST_NULL ; m_PrevPoint.SetPoint( 0, 0) ; m_ptPrev.Set( 0, 0, 0) ; m_nSnapPoint = SP_END ; } //---------------------------------------------------------------------------- TestEGrView::~TestEGrView( void) { if ( m_pScene != nullptr) delete m_pScene ; m_pScene = nullptr ; if ( m_pDC != nullptr) delete m_pDC ; m_pDC = nullptr ; } //---------------------------------------------------------------------------- bool TestEGrView::Create( CWnd* pParent, int nID) { if ( pParent == nullptr || pParent->GetDlgItem( nID) == nullptr) return false ; CString className = AfxRegisterWndClass( CS_HREDRAW | CS_VREDRAW | CS_OWNDC, NULL, NULL, NULL) ; CRect rectWin ; pParent->GetDlgItem( nID)->GetWindowRect( rectWin) ; pParent->ScreenToClient( rectWin) ; if ( CreateEx( 0, className, L"TestEGrView", WS_VISIBLE | WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, rectWin, pParent, nID) != 0) { SetWindowPos( &wndTop, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE) ; SetCursor( AfxGetApp()->LoadCursor( IDC_SELECT)) ; m_pDC = new CClientDC( this) ; m_pScene = CreateEGrScene() ; // configuro le gesture //CGestureConfig cfg ; //GetGestureConfig( &cfg) ; //cfg.EnablePan( TRUE, GC_PAN) ; //cfg.EnableRotate( TRUE) ; //SetGestureConfig( &cfg) ; return ( m_pDC != nullptr && m_pScene != nullptr) ; } else return false ; } //---------------------------------------------------------------------------- bool TestEGrView::StartScene( int nDriver, bool b2Buff, int nColorBits, int nDepthBits) { if ( m_pScene == nullptr) return false ; // creazione della scena if ( ! m_pScene->CreateContext( GetSafeHdc(), nDriver, b2Buff, nColorBits, nDepthBits)) return false ; // impostazione dati di vista m_pScene->SetCamera( CT_ISO_SW) ; m_pScene->ZoomAll() ; return true ; } //---------------------------------------------------------------------------- bool TestEGrView::GetSceneInfo( string& sInfo) { if ( m_pScene == nullptr) return false ; sInfo = m_pScene->GetOpenGLInfo() + '\n' + m_pScene->GetGLSLInfo() + '\n' + m_pScene->GetPixelFormatInfo() ; return true ; } //---------------------------------------------------------------------------- void TestEGrView::Destroy( void) { if ( m_pScene != nullptr) m_pScene->Destroy() ; DestroyWindow() ; } //---------------------------------------------------------------------------- bool TestEGrView::Resize( int nX, int nY, int nW, int nH) { // se non è ancora stata creata, esco subito if ( m_pDC == nullptr || m_pScene == nullptr) return true ; MoveWindow( nX, nY, nW, nH, FALSE) ; m_pScene->Resize( nW, nH) ; return true ; } //---------------------------------------------------------------------------- void TestEGrView::OnPaint( void) { if ( m_pScene == nullptr) return ; PerformanceCounter Counter ; // ridisegno finestra OpenGL Counter.Start() ; m_pScene->Draw() ; ValidateRgn( NULL) ; Counter.Stop() ; // emetto info string sOut = "Redraw time = " + ToString( Counter.GetTime(), 2) + " ms" ; ::OutInfo( sOut, false) ; } //---------------------------------------------------------------------------- void TestEGrView::Redraw( void) { RedrawWindow() ; } //---------------------------------------------------------------------------- void TestEGrView::ShowMode( UINT nID) { if ( m_pScene == nullptr) return ; switch ( nID) { case IDC_WIREFRAME : m_pScene->SetShowMode( SM_WIREFRAME) ; break ; case IDC_HIDDENLINE : m_pScene->SetShowMode( SM_HIDDENLINE) ; break ; case IDC_SHADING : m_pScene->SetShowMode( SM_SHADING) ; break ; default : return ; break ; } RedrawWindow() ; } //---------------------------------------------------------------------------- void TestEGrView::ShowCurveDir( bool bShow) { if ( m_pScene == nullptr) return ; m_pScene->SetShowCurveDirection( bShow) ; RedrawWindow() ; } //---------------------------------------------------------------------------- void TestEGrView::Zoom( UINT nID) { if ( m_pScene == nullptr) return ; const double COEFF_IN = 0.9 ; const double COEFF_OUT = 1 / COEFF_IN ; switch ( nID) { case IDC_ZOOM_ALL : m_pScene->ZoomAll() ; break ; case IDC_ZOOM_IN : m_pScene->ZoomChange( COEFF_IN) ; break ; case IDC_ZOOM_OUT : m_pScene->ZoomChange( COEFF_OUT) ; break ; default : return ; break ; } RedrawWindow() ; } //---------------------------------------------------------------------------- void TestEGrView::View( UINT nID) { if ( m_pScene == nullptr) return ; switch ( nID) { case IDC_VIEW_TOP : m_pScene->SetCamera( CT_TOP) ; break ; case IDC_VIEW_FRONT : m_pScene->SetCamera( CT_FRONT) ; break ; case IDC_VIEW_BACK : m_pScene->SetCamera( CT_BACK) ; break ; case IDC_VIEW_LEFT : m_pScene->SetCamera( CT_LEFT) ; break ; case IDC_VIEW_RIGHT : m_pScene->SetCamera( CT_RIGHT) ; break ; case IDC_VIEW_ISO : m_pScene->SetCamera( CT_ISO_SW) ; break ; default : return ; break ; } RedrawWindow() ; } //---------------------------------------------------------------------------- void TestEGrView::SetAnalyze( void) { m_nStatus = ST_ANALYZE ; } //---------------------------------------------------------------------------- void TestEGrView::SetGetDistance( void) { m_pScene->ResetGeoLine() ; m_pScene->Draw() ; m_nStatus = ST_GETDIST ; } //---------------------------------------------------------------------------- void TestEGrView::OnLButtonDown( UINT nFlags, CPoint point) { if ( m_nStatus == ST_NULL) { int nSel ; m_pScene->Select( Point3d( point.x, point.y), DIM_SEL, DIM_SEL, nSel) ; if ( nSel == 1) { int nId = m_pScene->GetFirstSelectedObj() ; if ( m_pScene->GetGeomDB()->IsSelectedObj( nId)) m_pScene->GetGeomDB()->DeselectObj( nId) ; else m_pScene->GetGeomDB()->SelectObj( nId) ; m_pScene->Draw() ; } else if ( nSel > 1) { CSelectDlg dlgSelect( m_pScene) ; dlgSelect.DoModal() ; int nId = dlgSelect.GetCurrId() ; if ( nId != GDB_ID_NULL) { if ( m_pScene->GetGeomDB()->IsSelectedObj( nId)) m_pScene->GetGeomDB()->DeselectObj( nId) ; else m_pScene->GetGeomDB()->SelectObj( nId) ; m_pScene->Draw() ; } } } else if ( m_nStatus == ST_ANALYZE) { int nSel = 0 ; int nId = GDB_ID_NULL ; m_pScene->Select( Point3d( point.x, point.y), DIM_SEL, DIM_SEL, nSel) ; if ( nSel == 1) nId = m_pScene->GetFirstSelectedObj() ; else if ( nSel > 1) { CSelectDlg dlgSelect( m_pScene) ; dlgSelect.DoModal() ; nId = dlgSelect.GetCurrId() ; } if ( nId != GDB_ID_NULL) SelectIdInGeomDbTree( nId) ; SetCursor( AfxGetApp()->LoadCursor( IDC_SELECT)) ; m_nStatus = ST_NULL ; } else if ( m_nStatus == ST_GETDIST) { if ( m_pScene->GetGraphicSnapPoint( m_nSnapPoint, Point3d( point.x, point.y), DIM_SEL, DIM_SEL, m_ptPrev)) { // salvo il punto di riferimento Point3d ptWin ; m_pScene->Project( m_ptPrev, ptWin) ; m_PrevPoint.SetPoint( int( ptWin.x), int( ptWin.y)) ; m_nStatus = ST_GETDIST2 ; } else { SetCursor( AfxGetApp()->LoadCursor( IDC_SELECT)) ; m_nStatus = ST_NULL ; } } else if ( m_nStatus == ST_GETDIST2) { // recupero il punto selezionato Point3d ptSel ; if ( m_pScene->GetGraphicSnapPoint( m_nSnapPoint, Point3d( point.x, point.y), DIM_SEL, DIM_SEL, ptSel)) { // disegno la linea (coordinate geo globali) m_pScene->SetGeoLine( m_ptPrev, ptSel) ; RedrawWindow() ; // calcolo la distanza e il delta e li visualizzo double dDist = Dist( ptSel, m_ptPrev) ; Vector3d vtDiff = ptSel - m_ptPrev ; string sOut ; sOut = "Dist=" + ToString( dDist, 4) + " dX=" + ToString( vtDiff.x, 4) + " dY=" + ToString( vtDiff.y, 4) + " dZ=" + ToString( vtDiff.z, 4) ; AfxMessageBox( stringtoW( sOut), MB_ICONINFORMATION | MB_OK) ; } // annullo eventuale linea di misura e lo stato m_pScene->ResetGeoLine() ; RedrawWindow() ; m_nStatus = ST_NULL ; } } //---------------------------------------------------------------------------- void TestEGrView::OnLButtonUp( UINT nFlags, CPoint point) { ; } //---------------------------------------------------------------------------- void TestEGrView::OnRButtonUp( UINT nFlags, CPoint point) { // se utile menù punti notevoli proseguo if ( m_nStatus != ST_GETDIST && m_nStatus != ST_GETDIST2) return ; // inserisco menù per punti notevoli CMenu Menu ; Menu.CreatePopupMenu() ; Menu.AppendMenu( MF_STRING, IDM_ENDPOINT, L"EndPoint") ; Menu.CheckMenuItem( IDM_ENDPOINT, MF_BYCOMMAND | ( m_nSnapPoint == SP_END ? MF_CHECKED : MF_UNCHECKED)) ; Menu.AppendMenu( MF_STRING, IDM_MIDPOINT, L"MidPoint") ; Menu.CheckMenuItem( IDM_MIDPOINT, MF_BYCOMMAND | ( m_nSnapPoint == SP_MID ? MF_CHECKED : MF_UNCHECKED)) ; Menu.AppendMenu( MF_STRING, IDM_CENTERPOINT, L"CenterPoint") ; Menu.CheckMenuItem( IDM_CENTERPOINT, MF_BYCOMMAND | ( m_nSnapPoint == SP_CENTER ? MF_CHECKED : MF_UNCHECKED)) ; Menu.AppendMenu( MF_STRING, IDM_NEARPOINT, L"NearPoint") ; Menu.CheckMenuItem( IDM_NEARPOINT, MF_BYCOMMAND | ( m_nSnapPoint == SP_NEAR ? MF_CHECKED : MF_UNCHECKED)) ; ClientToScreen( &point) ; Menu.TrackPopupMenu( TPM_LEFTALIGN, point.x, point.y, this) ; } //---------------------------------------------------------------------------- void TestEGrView::OnSelSnapPoint( UINT nID) { switch ( nID) { case IDM_ENDPOINT : m_nSnapPoint = SP_END ; break ; case IDM_MIDPOINT : m_nSnapPoint = SP_MID ; break ; case IDM_CENTERPOINT : m_nSnapPoint = SP_CENTER ; break ; case IDM_NEARPOINT : m_nSnapPoint = SP_NEAR ; break ; } } //---------------------------------------------------------------------------- void TestEGrView::OnMButtonDown( UINT nFlags, CPoint point) { if ( nFlags & MK_SHIFT) { m_nOldStatus = ( m_nStatus == ST_GETDIST2) ? ST_GETDIST2 : ST_NULL ; m_nStatus = ST_ZOOMWIN ; SetCursor( AfxGetApp()->LoadCursor( IDC_ZOOMWIN)) ; } else if ( nFlags & MK_CONTROL) { m_nOldStatus = ( m_nStatus == ST_GETDIST2) ? ST_GETDIST2 : ST_NULL ; m_nStatus = ST_ROT ; SetCursor( AfxGetApp()->LoadCursor( IDC_ROTATE)) ; } else { m_nOldStatus = ( m_nStatus == ST_GETDIST2) ? ST_GETDIST2 : ST_NULL ; m_nStatus = ST_PAN ; SetCursor( AfxGetApp()->LoadCursor( IDC_PAN)) ; } // salvo il punto di riferimento m_PrevPoint = point ; } //---------------------------------------------------------------------------- void TestEGrView::OnMButtonUp( UINT nFlags, CPoint point) { // eseguo ZOOMWINDOWN if ( m_nStatus == ST_ZOOMWIN) { // annullo i dati del rettangolo di definizione della nuova vista if ( m_pScene != nullptr) m_pScene->ResetWinRect() ; // eseguo lo zoom if ( m_pScene != nullptr) m_pScene->ZoomWin( Point3d( m_PrevPoint.x, m_PrevPoint.y), Point3d( point.x, point.y)) ; // aggiorno il disegno RedrawWindow() ; } // eventuale ripristino vecchio stato if ( m_nOldStatus == ST_GETDIST2) { m_nStatus = ST_GETDIST2 ; SetCursor( AfxGetApp()->LoadCursor( IDC_GETDIST)) ; } // reset dello stato se non NULL else if ( m_nStatus != ST_NULL) { m_nStatus = ST_NULL ; SetCursor( AfxGetApp()->LoadCursor( IDC_SELECT)) ; } } //---------------------------------------------------------------------------- void TestEGrView::OnMouseMove( UINT nFlags, CPoint point) { // visualizzo le coordinate del puntatore ShowCursorCoordinates( Point3d( point.x, point.y)) ; // se in modalità ZOOMWINDOW if ( m_nStatus == ST_ZOOMWIN && nFlags & MK_MBUTTON) { SetCursor( AfxGetApp()->LoadCursor( IDC_ZOOMWIN)) ; // aggiorno i dati del rettangolo di definizione della nuova vista if ( m_pScene != nullptr) m_pScene->SetWinRect( Point3d( m_PrevPoint.x, m_PrevPoint.y), Point3d( point.x, point.y)) ; // aggiorno il disegno RedrawWindow() ; // il punto di riferimento deve rimanere quello originale } // se in modalità ROTATE else if ( m_nStatus == ST_ROT && nFlags & MK_MBUTTON) { SetCursor( AfxGetApp()->LoadCursor( IDC_ROTATE)) ; // eseguo la rotazione if ( m_pScene != nullptr) m_pScene->RotateCamera( Point3d( m_PrevPoint.x, m_PrevPoint.y), Point3d( point.x, point.y)) ; // aggiorno il disegno RedrawWindow() ; // aggiorno i bottoni UpdateButtons() ; // salvo il punto di riferimento m_PrevPoint = point ; } // se in modalità PAN else if ( m_nStatus == ST_PAN && nFlags & MK_MBUTTON) { SetCursor( AfxGetApp()->LoadCursor( IDC_PAN)) ; // eseguo il pan if ( m_pScene != nullptr) m_pScene->PanCamera( Point3d( m_PrevPoint.x, m_PrevPoint.y), Point3d( point.x, point.y)) ; // aggiorno il disegno RedrawWindow() ; // salvo il punto di riferimento m_PrevPoint = point ; } // se in modalità ANALYZE else if ( m_nStatus == ST_ANALYZE) { SetCursor( AfxGetApp()->LoadCursor( IDC_ANALYZE)) ; } // se in modalità GETDIST else if ( m_nStatus == ST_GETDIST) { SetCursor( AfxGetApp()->LoadCursor( IDC_GETDIST)) ; } // se in modalità GETDIST2 else if ( m_nStatus == ST_GETDIST2) { SetCursor( AfxGetApp()->LoadCursor( IDC_GETDIST)) ; Point3d ptP ; m_pScene->UnProject( Point3d( point.x, point.y, 0.5), ptP) ; m_pScene->SetGeoLine( m_ptPrev, ptP) ; // aggiorno il disegno RedrawWindow() ; } // altrimenti reset dello stato e cursore standard else { SetCursor( AfxGetApp()->LoadCursor( IDC_SELECT)) ; m_nStatus = ST_NULL ; } } //---------------------------------------------------------------------------- BOOL TestEGrView::OnMouseWheel( UINT nFlags, short zDelta, CPoint point) { // devo essere nello stato NULL o GETDIST if ( m_nStatus != ST_NULL && m_nStatus != ST_GETDIST && m_nStatus != ST_GETDIST2) return 0 ; // calcolo coefficiente double dCoeff = 1 - 0.1 * abs( zDelta) / WHEEL_DELTA ; if ( zDelta < 0) dCoeff = 1 / dCoeff ; // porto il punto in coordinate client ScreenToClient( &point) ; // eseguo lo zoom sul punto if ( m_pScene != nullptr) m_pScene->ZoomOnPoint( Point3d( point.x, point.y), dCoeff) ; // aggiorno il disegno RedrawWindow() ; return 0 ; } //---------------------------------------------------------------------------- BOOL TestEGrView::OnGesturePan( CPoint ptFRom, CPoint ptTO) { if ( m_pScene == nullptr) return false ; // eseguo il pan m_pScene->PanCamera( Point3d( ptFRom.x, ptFRom.y), Point3d( ptTO.x, ptTO.y)) ; // aggiorno il disegno RedrawWindow() ; return true ; } //---------------------------------------------------------------------------- BOOL TestEGrView::OnGestureRotate( CPoint ptCenter, double dblAngle) { if ( m_pScene == nullptr) return false ; // recupero gli angoli precedenti double dAngVertDeg, dAngOrizzDeg, dDist ; m_pScene->GetCamera( &dAngVertDeg, &dAngOrizzDeg, &dDist) ; // imposto i nuovi m_pScene->SetCamera( dAngVertDeg, dAngOrizzDeg - dblAngle, dDist) ; // aggiorno il disegno RedrawWindow() ; return true ; } //---------------------------------------------------------------------------- BOOL TestEGrView::OnGesturePressAndTap( CPoint ptPress, long lDelta) { if ( m_pScene == nullptr) return false ; // recupero gli angoli precedenti double dAngVertDeg, dAngOrizzDeg, dDist ; m_pScene->GetCamera( &dAngVertDeg, &dAngOrizzDeg, &dDist) ; // imposto il nuovo angolo verticale if ( lDelta > 10) dAngVertDeg = max( 0, dAngVertDeg - 15) ; else if ( lDelta < - 10) dAngVertDeg = min( 180, dAngVertDeg + 15) ; else return true ; m_pScene->SetCamera( dAngVertDeg, dAngOrizzDeg, dDist) ; // aggiorno il disegno RedrawWindow() ; return true ; } //---------------------------------------------------------------------------- void TestEGrView::ShowCursorCoordinates( const Point3d& ptWin) { if ( m_pScene == nullptr) return ; // trasformo il punto da coordinate view a coordinate mondo Point3d ptView( ptWin.x, ptWin.y, m_pScene->GetProjectedCenter().z) ; Point3d ptWorld ; if ( ! m_pScene->UnProject( ptView, ptWorld)) return ; // visualizzo le coordinate std::string sCoord ; switch ( m_pScene->GetCameraDir()) { case CT_TOP : case CT_BOTTOM : sCoord = "X=" + ToString( ptWorld.x, 4) + " Y=" + ToString( ptWorld.y, 4) ; break ; case CT_FRONT : case CT_BACK : sCoord = "X=" + ToString( ptWorld.x, 4) + " Z=" + ToString( ptWorld.z, 4) ; break ; case CT_LEFT : case CT_RIGHT : sCoord = "Y=" + ToString( ptWorld.y, 4) + " Z=" + ToString( ptWorld.z, 4) ; break ; default : sCoord = " " ; break ; } GetParent()->GetDlgItem( IDC_COORD)->SetWindowText( stringtoW( sCoord)) ; }