//---------------------------------------------------------------------------- // EgalTech 2013-2014 //---------------------------------------------------------------------------- // File : SceneBasic.cpp Data : 03.02.14 Versione : 1.5b1 // Contenuto : Implementazione della classe gestione scena. // // // // Modifiche : 29.01.14 DS Creazione modulo. // 21.10.14 DS Aggiunta gestione Unselectable. // //---------------------------------------------------------------------------- //--------------------------- Include ---------------------------------------- #include "stdafx.h" #include "Scene.h" #include "GraphObjs.h" #include "DllMain.h" #include "/EgtDev/Include/EgtILogger.h" #include "/EgtDev/Include/EGnStringUtils.h" #include "/EgtDev/Include/EGkFrame3d.h" #include "/EgtDev/Include/EGkGdbConst.h" #include "/EgtDev/Include/EGkGeomDB.h" using namespace std ; //--------------------------- Constants -------------------------------------- static const double MIN_EXTENSION = 250 ; static const double MIN_W_H = 0.01 ; static const double MIN_ZCLIP_EXT = 5000 ; //---------------------------------------------------------------------------- IEGrScene* CreateEGrScene( void) { return static_cast ( new(nothrow) Scene) ; } //---------------------------------------------------------------------------- Scene::Scene( void) { // Context data m_hDC = nullptr ; m_hRC = nullptr ; memset( &m_wglewc, 0, sizeof( WGLEWContext)) ; memset( &m_glewc, 0, sizeof( GLEWContext)) ; m_bNewWay = false ; // Camera e viewport m_ptCenter = ORIG ; SetCamera( 0, 0, 0) ; m_nViewportW = 0 ; m_nViewportH = 0 ; // Sfondo m_colBackTop.Set( 176, 176, 176) ; m_colBackBottom.Set( 176, 176, 176) ; // Modalità di visualizzazione m_nShowMode = SM_WIREFRAME ; m_bShowCurveDirection = false ; m_bShowTriaAdvanced = true ; // Selezione m_bSelect = false ; m_nObjFilterForSelect = GEO_ZERODIM | GEO_CURVE | GEO_SURF | GEO_VOLUME | GEO_EXTRA ; m_Unsel.reserve( 50) ; m_nSelCurr = GDB_ID_NULL ; // Snap Punti m_nLastSnapId = GDB_ID_NULL ; m_bLastSnapDirOk = false ; // GeomData m_pGeomDB = nullptr ; m_colDef.Set( 0, 0, 0) ; m_colMark.Set( 255, 255, 0) ; m_colSelSurf.Set( 255, 255, 192) ; // Superfici semitrasparenti m_vAlphaSurf.reserve( 100) ; // Extension SetExtension( BBox3d( -MIN_EXTENSION, -MIN_EXTENSION, -MIN_EXTENSION, MIN_EXTENSION, MIN_EXTENSION, MIN_EXTENSION)) ; // Grid m_bShowGrid = false ; m_bShowFrame = false ; m_dSnapStep = 1 ; m_nMinLineSstep = 10 ; m_nMajLineSstep = 100 ; m_nExtSstep = 500 ; m_colMinLine.Set( 160, 160, 160) ; m_colMajLine.Set( 160, 160, 160) ; // Global Frame m_bShowGlobFrame = false ; // Direct m_colorGL.Set( 255, 0, 0) ; m_bGeoLine = false ; m_colorGT.Set( 255, 0, 0) ; m_bGeoTria = false ; m_bOutlineWR = true ; m_colorWR.Set( 0, 0, 0) ; m_bWinRect = false ; } //---------------------------------------------------------------------------- Scene::~Scene( void) { } //---------------------------------------------------------------------------- bool Scene::Init( IGeomDB* pGeomDB) { m_pGeomDB = pGeomDB ; return true ; } //---------------------------------------------------------------------------- bool Scene::CreateContext( HDC hDC, int nDriver, bool b2Buff, int nColorBits, int nDepthBits) { // verifico validità Device Context if ( hDC == nullptr) return false ; m_hDC = hDC ; // riporto nei limiti il tipo di driver if ( nDriver < OD_SOFT) nDriver = OD_SOFT ; else if ( nDriver > OD_NEW) nDriver = OD_NEW ; // assegno formato pixel PIXELFORMATDESCRIPTOR pfd ; memset( &pfd, 0, sizeof(PIXELFORMATDESCRIPTOR)) ; pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR) ; pfd.nVersion = 1 ; pfd.dwFlags = ( b2Buff ? PFD_DOUBLEBUFFER : 0) | PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW ; pfd.iPixelType = PFD_TYPE_RGBA ; pfd.cColorBits = nColorBits ; pfd.cDepthBits = nDepthBits ; pfd.iLayerType = PFD_MAIN_PLANE ; int nPixelFormat = ChoosePixelFormat( m_hDC, &pfd) ; if ( nPixelFormat == 0) return false ; if ( nDriver == OD_SOFT) { int nPixFormGen = ChooseGenPixelFormat( nPixelFormat, b2Buff, nColorBits, nDepthBits) ; if ( nPixFormGen != 0) nPixelFormat = nPixFormGen ; } if ( ! SetPixelFormat( m_hDC, nPixelFormat, &pfd)) return false ; HGLRC tempContext = wglCreateContext( m_hDC) ; wglMakeCurrent( m_hDC, tempContext) ; GLenum WglewInitResult ; WglewInitResult = wglewInit() ; if ( WglewInitResult != GLEW_OK) LOG_INFO( GetEGrLogger(), "WGLEW is not initialized !") int attribs[10] ; if ( nDriver == OD_SOFT) { attribs[0] = WGL_CONTEXT_MAJOR_VERSION_ARB ; attribs[1] = 1 ; attribs[2] = WGL_CONTEXT_MINOR_VERSION_ARB ; attribs[3] = 1 ; attribs[4] = 0 ; } else if ( nDriver == OD_OLD) { attribs[0] = WGL_CONTEXT_MAJOR_VERSION_ARB ; attribs[1] = 2 ; attribs[2] = WGL_CONTEXT_MINOR_VERSION_ARB ; attribs[3] = 0 ; attribs[4] = 0 ; } else { attribs[0] = WGL_CONTEXT_MAJOR_VERSION_ARB ; attribs[1] = 3 ; attribs[2] = WGL_CONTEXT_MINOR_VERSION_ARB ; attribs[3] = 0 ; attribs[4] = 0 ; } if ( wglewIsSupported( "WGL_ARB_create_context") == 1) { m_hRC = wglCreateContextAttribsARB( m_hDC, 0, attribs) ; wglMakeCurrent( m_hDC, NULL) ; wglDeleteContext( tempContext) ; wglMakeCurrent( m_hDC, m_hRC) ; } else { //It's not possible to make a GL 3.x context. Use the old style context (GL 2.1 and before) m_hRC = tempContext ; LOG_INFO( GetEGrLogger(), "WGL_ARB_create_context missing !") } // verifico validità Rendering Context if ( m_hRC == nullptr) return false ; GLenum GlewInitResult ; glewExperimental = GL_TRUE ; GlewInitResult = glewInit() ; if ( GlewInitResult != GLEW_OK) LOG_INFO( GetEGrLogger(), "GLEW is not initialized !") // verifico se posso lavorare in modalità nuova m_bNewWay = ( nDriver == OD_NEW && glewIsSupported( "GL_VERSION_3_0") == 1) ; if ( ! m_bNewWay) LOG_INFO( GetEGrLogger(), "OpenGL old way rendering !") // reset stato di errore di OpenGL glGetError() ; return true ; } //---------------------------------------------------------------------------- int Scene::ChooseGenPixelFormat( int nPfd, bool b2Buff, int nColorBits, int nDepthBits) { PIXELFORMATDESCRIPTOR pfdR ; // verifica del pixel format proposto int nTotPfd = DescribePixelFormat( m_hDC, nPfd, sizeof(PIXELFORMATDESCRIPTOR), &pfdR) ; if ( pfdR.dwFlags & PFD_GENERIC_FORMAT && ! ( pfdR.dwFlags & PFD_GENERIC_ACCELERATED)) return nPfd ; // eventuale ricerca di un pixel format soddisfacente int nIOpt = 0 ; int nErrOpt = 1000 ; for ( int nI = 1 ; nI <= nTotPfd ; nI ++) { DescribePixelFormat( m_hDC, nI, sizeof(PIXELFORMATDESCRIPTOR), &pfdR) ; if ( pfdR.dwFlags & PFD_GENERIC_FORMAT && ! (pfdR.dwFlags & PFD_GENERIC_ACCELERATED) && ( ! b2Buff || pfdR.dwFlags & PFD_DOUBLEBUFFER)) { int nErr = abs( nColorBits - pfdR.cColorBits) + abs( nDepthBits - pfdR.cDepthBits) ; if ( nErr < nErrOpt) { nErrOpt = nErr ; nIOpt = nI ; } } } return nIOpt ; } //---------------------------------------------------------------------------- bool Scene::MakeCurrent( void) { // se RC della scena non è definito, errore if ( m_hRC == nullptr) return false ; // se RC della scena non è quello corrente, lo imposto HGLRC hRC = wglGetCurrentContext() ; if ( m_hRC != hRC) return ( wglMakeCurrent( m_hDC, m_hRC) != 0) ; return true ; } //---------------------------------------------------------------------------- string Scene::GetOpenGLInfo( void) { string sInfo = "OpenGL " ; if ( MakeCurrent()) { const char* p ; if ( ( p = reinterpret_cast ( glGetString( GL_VERSION))) != nullptr) sInfo += p ; sInfo += ( m_bNewWay ? " (Nw)" : " (Ow)") ; sInfo += " " ; if ( ( p = reinterpret_cast ( glGetString( GL_VENDOR))) != nullptr) sInfo += p ; sInfo += " " ; if ( ( p = reinterpret_cast ( glGetString( GL_RENDERER))) != nullptr) sInfo += p ; } else sInfo += "ERROR" ; // reset stato di errore di OpenGL glGetError() ; return sInfo ; } //---------------------------------------------------------------------------- string Scene::GetGLSLInfo( void) { string sInfo = "GLSL " ; if ( MakeCurrent()) { const char* p ; if ( ( p = reinterpret_cast ( glGetString( GL_SHADING_LANGUAGE_VERSION))) != nullptr) sInfo += p ; else sInfo += "NONE" ; } else sInfo += "ERROR" ; // reset stato di errore di OpenGL glGetError() ; return sInfo ; } //---------------------------------------------------------------------------- string Scene::GetPixelFormatInfo( void) { string sInfo = "PixFmt " ; if ( MakeCurrent()) { int nPixFmt ; PIXELFORMATDESCRIPTOR Pfd ; if ( ( nPixFmt = GetPixelFormat( m_hDC)) > 0 && DescribePixelFormat( m_hDC, nPixFmt, sizeof(PIXELFORMATDESCRIPTOR), &Pfd) > 0) { // indice sInfo += ToString( nPixFmt) ; // tipo di driver if ( ! ( Pfd.dwFlags & PFD_GENERIC_FORMAT)) sInfo += " ICD" ; else if ( Pfd.dwFlags & PFD_GENERIC_ACCELERATED) sInfo += " MCD" ; else sInfo += " GEN" ; // singolo o doppio buffer sInfo += ( ( Pfd.dwFlags & PFD_DOUBLEBUFFER) ? " BUFF2" : " BUFF1") ; // RGBA o COLORINDEX sInfo += ( ( Pfd.iPixelType == PFD_TYPE_RGBA) ? " RGBA" : " CI") ; // color bits sInfo += ToString( Pfd.cColorBits) ; // depth bits sInfo += " Z" + ToString( Pfd.cDepthBits) ; } else sInfo = "NO DESCRIBE" ; } else sInfo += "ERROR" ; // reset stato di errore di OpenGL glGetError() ; return sInfo ; } //---------------------------------------------------------------------------- bool Scene::RedrawWindow( void) { HWND hWnd = ::WindowFromDC( m_hDC) ; if ( hWnd == nullptr) return false ; return ( ::RedrawWindow( hWnd, nullptr, nullptr, RDW_INVALIDATE | RDW_UPDATENOW) != 0) ; } //---------------------------------------------------------------------------- bool Scene::SetExtension( const BBox3d& b3Ext) { if ( b3Ext.IsEmpty()) m_b3ExtWorld.Set( -MIN_EXTENSION, -MIN_EXTENSION, -MIN_EXTENSION, MIN_EXTENSION, MIN_EXTENSION, MIN_EXTENSION) ; else m_b3ExtWorld = b3Ext ; m_bExtViewOk = false ; return true ; } //---------------------------------------------------------------------------- bool Scene::CalcExtView( void) { // verifico se il calcolo è necessario if ( m_bExtViewOk && m_bUpOk) return true ; // calcolo direzione camera Up if ( ! CalcDirUp()) return false ; // calcolo il riferimento di vista Frame3d frView ; if ( ! CalcCameraFrame( frView)) return false ; // calcolo l'estensione nel riferimento di vista m_b3ExtView = m_b3ExtWorld ; m_b3ExtView.ToLoc( frView) ; m_bExtViewOk = true ; return m_bExtViewOk ; } //---------------------------------------------------------------------------- bool Scene::CalcDimViewFromExtView( void) { // calcolo estensione nel riferimento di vista if ( ! CalcExtView()) return false ; // recupero gli ingombri Point3d ptMin ; Point3d ptMax ; if ( ! m_b3ExtView.GetMinMax( ptMin, ptMax)) return false ; // ricavo le dimensioni const double COEFF = 1.05 ; double dHalfWidth = COEFF * max( fabs( ptMin.x), fabs( ptMax.x)) ; double dHalfHeight = COEFF * max( fabs( ptMin.y), fabs( ptMax.y)) ; // adatto le dimensioni a quelle della vista return AdjustDimView( dHalfWidth, dHalfHeight) ; } //---------------------------------------------------------------------------- bool Scene::AdjustDimView( double dHalfWidth, double dHalfHeight) { // se non assegnate, recupero dimensioni vista if ( m_nViewportW == 0) { HWND hWnd = ::WindowFromDC( m_hDC) ; RECT rect ; if ( ! ::GetClientRect( hWnd, &rect)) return false ; m_nViewportW = rect.right ; m_nViewportH = rect.bottom ; // aggiorno la vista glViewport( 0, 0, m_nViewportW, m_nViewportH) ; // verifico presenza errori GLenum nErr = glGetError() ; if ( nErr != GL_NO_ERROR) { string sOut = "First glViewport OpenGL error " + ToString( (int)nErr) ; LOG_INFO( GetEGrLogger(), sOut.c_str()) } } // verifico minimo delle dimensioni dHalfWidth = max( dHalfWidth, MIN_W_H) ; dHalfHeight = max( dHalfHeight, MIN_W_H) ; // adatto il rapporto tra le dimensioni calcolate a quello delle dimensioni della vista double dAspect = m_nViewportH / ( double) m_nViewportW ; if ( dAspect * dHalfWidth > dHalfHeight) { m_dHalfWidth = dHalfWidth ; m_dHalfHeight = dAspect * dHalfWidth ; } else { m_dHalfWidth = dHalfHeight / dAspect ; m_dHalfHeight = dHalfHeight ; } return true ; } //---------------------------------------------------------------------------- bool Scene::CalcClippingPlanesFromExtView( void) { // calcolo estensione nel riferimento di vista if ( ! CalcExtView()) return false ; // recupero gli ingombri Point3d ptCenter ; Vector3d vtExtent ; if ( ! m_b3ExtView.GetCenterExtent( ptCenter, vtExtent)) return false ; // ricavo la posizione dei piani di clipping sull'asse Z di vista const double EXP_COEFF = 1.1 ; double dExtent = __max( ( EXP_COEFF * vtExtent.z), MIN_ZCLIP_EXT) ; m_dZNear = - ( ptCenter.z + dExtent) ; m_dZFar = - ( ptCenter.z - dExtent) ; return true ; } //---------------------------------------------------------------------------- bool Scene::Resize( int nW, int nH) { if ( ! MakeCurrent()) return false ; // assegno le dimensioni della vista m_nViewportW = nW ; m_nViewportH = nH ; // aggiorno la vista glViewport( 0, 0, m_nViewportW, m_nViewportH) ; // verifico presenza errori GLenum nErr = glGetError() ; if ( nErr != GL_NO_ERROR) { string sOut = "Reshape OpenGL error " + ToString( (int)nErr) ; LOG_INFO( GetEGrLogger(), sOut.c_str()) } // aggiorno AdjustDimView( m_dHalfWidth, m_dHalfHeight) ; // ridisegno return Draw() ; } //---------------------------------------------------------------------------- bool Scene::SetBackground( Color colBackTop, Color colBackBottom) { m_colBackTop = colBackTop ; m_colBackBottom = colBackBottom ; return true ; } //---------------------------------------------------------------------------- bool Scene::Background( void) { // imposto il rendering corrente if ( ! MakeCurrent()) return false ; // cancello lo Zbuffer glClearDepth( 1) ; glClear( GL_DEPTH_BUFFER_BIT) ; // se lo sfondo ha un colore uniforme if ( m_colBackTop == m_colBackBottom) { // imposto il colore dello sfondo e lo cancello glClearColor( m_colBackTop.GetRed(), m_colBackTop.GetGreen(), m_colBackTop.GetBlue(), 1) ; glClear( GL_COLOR_BUFFER_BIT) ; return true ; } // rendo neutre matrici di proiezione e di modello/vista glMatrixMode( GL_PROJECTION) ; glLoadIdentity() ; glMatrixMode( GL_MODELVIEW) ; glLoadIdentity() ; // disabilito lo Zdepth glDisable( GL_DEPTH_TEST) ; // disabilito illuminazione glDisable( GL_LIGHTING) ; // imposto riempimento poligoni glPolygonMode( GL_FRONT_AND_BACK, GL_FILL) ; // disegno lo sfondo con due colori if ( ! m_bNewWay) { glBegin( GL_TRIANGLE_STRIP) ; glColor3f( m_colBackBottom.GetRed(), m_colBackBottom.GetGreen(), m_colBackBottom.GetBlue()) ; glVertex3f( -1, -1, 0.5) ; glVertex3f( 1, -1, 0.5) ; glColor3f( m_colBackTop.GetRed(), m_colBackTop.GetGreen(), m_colBackTop.GetBlue()) ; glVertex3f( -1, 1, 0.5) ; glVertex3f( 1, 1, 0.5) ; glEnd() ; } else { unsigned int nVaoId ; unsigned int nVboId ; // definizione glGenVertexArrays( 1, &nVaoId) ; if ( nVaoId == 0) return false ; glBindVertexArray( nVaoId) ; glGenBuffers( 1, &nVboId) ; glBindBuffer( GL_ARRAY_BUFFER, nVboId) ; glBufferData( GL_ARRAY_BUFFER, 8 * SIZEV3F, NULL, GL_STATIC_DRAW) ; glVertexPointer( 3, GL_FLOAT, 2 * SIZEV3F, ((void*)(0))) ; glEnableClientState( GL_VERTEX_ARRAY) ; glColorPointer( 3, GL_FLOAT, 2 * SIZEV3F, ((void*)(1 * SIZEV3F))) ; glEnableClientState( GL_COLOR_ARRAY) ; Vert3f v3V ; Vert3f v3C ; // bottom left v3V.Set( -1, -1, 0.5) ; glBufferSubData( GL_ARRAY_BUFFER, 0 * SIZEV3F, SIZEV3F, &v3V) ; v3C.Set( m_colBackBottom.GetRed(), m_colBackBottom.GetGreen(), m_colBackBottom.GetBlue()) ; glBufferSubData( GL_ARRAY_BUFFER, 1 * SIZEV3F, SIZEV3F, &v3C) ; // bottom right v3V.Set( 1, -1, 0.5) ; glBufferSubData( GL_ARRAY_BUFFER, 2 * SIZEV3F, SIZEV3F, &v3V) ; // v3C constant glBufferSubData( GL_ARRAY_BUFFER, 3 * SIZEV3F, SIZEV3F, &v3C) ; // top left v3V.Set( -1, 1, 0.5) ; glBufferSubData( GL_ARRAY_BUFFER, 4 * SIZEV3F, SIZEV3F, &v3V) ; v3C.Set( m_colBackTop.GetRed(), m_colBackTop.GetGreen(), m_colBackTop.GetBlue()) ; glBufferSubData( GL_ARRAY_BUFFER, 5 * SIZEV3F, SIZEV3F, &v3C) ; // top right v3V.Set( 1, 1, 0.5) ; glBufferSubData( GL_ARRAY_BUFFER, 6 * SIZEV3F, SIZEV3F, &v3V) ; // v3C constant glBufferSubData( GL_ARRAY_BUFFER, 7 * SIZEV3F, SIZEV3F, &v3C) ; // disegno glDrawArrays( GL_TRIANGLE_STRIP, 0, 4) ; // cancellazione glBindBuffer( GL_ARRAY_BUFFER, 0) ; glDeleteBuffers( 1, &nVboId) ; glBindVertexArray( 0) ; glDeleteVertexArrays( 1, &nVaoId) ; } return true ; } //---------------------------------------------------------------------------- bool Scene::Prepare( void) { // imposto il rendering corrente if ( ! MakeCurrent()) return false ; // eventuale ricalcolo parametri di vista CalcDirUp() ; // 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 glMatrixMode( GL_MODELVIEW) ; glLoadIdentity() ; Point3d ptCamera = m_ptCenter + m_dDistCamera * m_vtDirCamera ; gluLookAt( ptCamera.x, ptCamera.y, ptCamera.z, m_ptCenter.x, m_ptCenter.y, m_ptCenter.z, m_vtUp.x, m_vtUp.y, m_vtUp.z) ; // verifico presenza errori GLenum nErr = glGetError() ; if ( nErr != GL_NO_ERROR) { string sOut = "Prepare OpenGL error " + ToString( (int)nErr) ; LOG_INFO( GetEGrLogger(), sOut.c_str()) } return true ; } //---------------------------------------------------------------------------- bool Scene::Draw( void) { // sistemo lo sfondo e lo Zbuffer if ( ! Background()) return false ; // imposto la camera if ( ! Prepare()) return false ; // imposto l'utilizzo dello Zbuffer glDepthFunc( GL_LEQUAL) ; glEnable( GL_DEPTH_TEST) ; // aggiorno il colore di default if ( m_pGeomDB != nullptr) m_pGeomDB->GetDefaultMaterial( m_colDef) ; // imposto la dimensione standard dei punti glPointSize( 3) ; // impostazioni dipendenti dalla modalità di visualizzazione switch ( m_nShowMode) { case SM_WIREFRAME : // disabilito illuminazione glDisable( GL_LIGHTING) ; // disegno griglia senza illuminazione (già impostato) DrawGrid() ; // imposto disegno wireframe anche per poligoni glPolygonMode( GL_FRONT_AND_BACK, GL_LINE) ; // disegno le geometrie del DB in una sola passata DrawGroup( GDB_ID_ROOT, 1, MdStMkCol( GDB_MD_STD, GDB_ST_ON, GDB_MK_OFF, m_colDef)) ; break ; case SM_HIDDENLINE : // disabilito illuminazione glDisable( GL_LIGHTING) ; // disegno griglia senza illuminazione (già impostato) DrawGrid() ; // disegno le geometrie del DB // prima passata per superfici solo per aggiornare Zbuffer (poligoni riempiti e offsettati) glPolygonMode( GL_FRONT_AND_BACK, GL_FILL) ; glEnable( GL_POLYGON_OFFSET_FILL) ; glPolygonOffset( 1.0, 1.0) ; glColorMask( GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE) ; DrawGroup( GDB_ID_ROOT, 1, MdStMkCol( GDB_MD_STD, GDB_ST_ON, GDB_MK_OFF, m_colDef)) ; glColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE) ; glDisable( GL_POLYGON_OFFSET_FILL) ; // seconda passata per tutto in forma 0dim e curve glPolygonMode( GL_FRONT_AND_BACK, GL_LINE) ; DrawGroup( GDB_ID_ROOT, 2, MdStMkCol( GDB_MD_STD, GDB_ST_ON, GDB_MK_OFF, m_colDef)) ; break ; case SM_SHADING : // disegno griglia senza illuminazione glDisable( GL_LIGHTING) ; DrawGrid() ; // imposto disegno shading per poligoni con davanti e dietro diversificati glPolygonMode( GL_FRONT_AND_BACK, GL_FILL) ; glLightModeli( GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE) ; // imposto tipo shading glShadeModel( GL_SMOOTH) ; // imposto illuminazione float LightAmbient[] = { 0.20f, 0.20f, 0.20f, 1.0f} ; float LightStd[] = { 0.35f, 0.35f, 0.35f, 1.0f} ; float Light0Pos[] = { 0.8f, 0.9f, 1.2f, 0.0f} ; float Light1Pos[] = { -0.9f, -0.7f, 0.6f, 0.0f} ; glLightfv( GL_LIGHT0, GL_AMBIENT, LightAmbient) ; glLightfv( GL_LIGHT0, GL_DIFFUSE, LightStd) ; glLightfv( GL_LIGHT0, GL_SPECULAR, LightStd) ; glLightfv( GL_LIGHT0, GL_POSITION, Light0Pos) ; glEnable( GL_LIGHT0) ; glLightfv( GL_LIGHT1, GL_AMBIENT, LightAmbient) ; glLightfv( GL_LIGHT1, GL_DIFFUSE, LightStd) ; glLightfv( GL_LIGHT1, GL_SPECULAR, LightStd) ; glLightfv( GL_LIGHT1, GL_POSITION, Light1Pos) ; glEnable( GL_LIGHT1) ; // disegno le geometrie del DB // annullo vettore superfici traslucide m_vAlphaSurf.clear() ; // prima passata per superfici completamente opache con illuminazione abilitata glEnable( GL_POLYGON_OFFSET_FILL) ; glPolygonOffset( 0.75, 0.75) ; glEnable( GL_LIGHTING) ; DrawGroup( GDB_ID_ROOT, 1, MdStMkCol( GDB_MD_STD, GDB_ST_ON, GDB_MK_OFF, m_colDef)) ; glDisable( GL_POLYGON_OFFSET_FILL) ; // seconda passata per 0dim e curve con illuminazione disabilitata glDisable( GL_LIGHTING) ; glPolygonMode( GL_FRONT_AND_BACK, GL_LINE) ; DrawGroup( GDB_ID_ROOT, 2, MdStMkCol( GDB_MD_STD, GDB_ST_ON, GDB_MK_OFF, m_colDef)) ; // terza passata su vettore di superfici trasparenti con : // illuminazione abilitata, blend abilitato e Zdepth solo in lettura if ( m_vAlphaSurf.size() > 0) { glPolygonMode( GL_FRONT_AND_BACK, GL_FILL) ; glEnable( GL_POLYGON_OFFSET_FILL) ; glPolygonOffset( 0.75, 0.75) ; glEnable( GL_LIGHTING) ; glEnable( GL_BLEND) ; glDepthMask( GL_FALSE) ; glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) ; DrawAlphaSurfVector() ; m_vAlphaSurf.clear() ; glDepthMask( GL_TRUE) ; glDisable( GL_BLEND) ; glDisable( GL_POLYGON_OFFSET_FILL) ; } break ; } // disabilito uso Zbuffer e illuminazione glDisable( GL_DEPTH_TEST) ; glDisable( GL_LIGHTING) ; // disegno riferimento globale DrawGlobFrame() ; // aggiungo disegni diretti (con poligoni riempiti) glPolygonMode( GL_FRONT_AND_BACK, GL_FILL) ; DrawDirect() ; // aggiorno glFlush() ; // verifico presenza errori GLenum nErr = glGetError() ; if ( nErr != GL_NO_ERROR) { string sOut = "Draw OpenGL error " + ToString( (int)nErr) ; LOG_INFO( GetEGrLogger(), sOut.c_str()) } // scambio i buffer back e front ( eseguita solo se previsti) if ( ! SwapBuffers( m_hDC)) LOG_INFO( GetEGrLogger(), "Draw SwapBuffers error") return true ; } /*------------------------------------------------------------------------------------------*/ bool Scene::Project( const Point3d& ptWorld, Point3d& ptView) { if ( ! MakeCurrent()) return false ; // recupero le matrici GLdouble ModelView[ 16] ; glGetDoublev( GL_MODELVIEW_MATRIX, ModelView) ; GLdouble Projection[ 16] ; glGetDoublev( GL_PROJECTION_MATRIX, Projection) ; GLint Viewport[ 4] ; glGetIntegerv( GL_VIEWPORT, Viewport) ; // 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) ; ptView.y = (double) Viewport[3] - ptView.y ; return ( nRes == GL_TRUE) ; } /*------------------------------------------------------------------------------------------*/ bool Scene::UnProject( const Point3d& ptView, Point3d& ptWorld) { if ( ! MakeCurrent()) return false ; // recupero le matrici GLdouble ModelView[ 16] ; glGetDoublev( GL_MODELVIEW_MATRIX, ModelView) ; GLdouble Projection[ 16] ; glGetDoublev( GL_PROJECTION_MATRIX, Projection) ; GLint Viewport[ 4] ; glGetIntegerv( GL_VIEWPORT, Viewport) ; // eseguo la contro 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 = gluUnProject( ptView.x, ((double) Viewport[3] - ptView.y), ptView.z, ModelView, Projection, Viewport, &ptWorld.x, &ptWorld.y, &ptWorld.z) ; return ( nRes == GL_TRUE) ; } //---------------------------------------------------------------------------- void Scene::Destroy( void) { // cancellazione eventuali ObjEgrGraphics attaccati a oggetti geometrici DeleteObjGraphicsGroup( GDB_ID_ROOT) ; // cancellazione rendering context wglMakeCurrent( nullptr, nullptr) ; if ( m_hRC != nullptr) { wglDeleteContext( m_hRC) ; m_hRC = nullptr ; } }