Scaricare la presentazione
La presentazione è in caricamento. Aspetta per favore
1
Claudio Rocchini, Visual Computing Group
OpenGL + MFC Claudio Rocchini 12/11/2018 Claudio Rocchini, Visual Computing Group
2
Claudio Rocchini, Visual Computing Group
Introduzione Vedremo come si realizza una applicazione OpenGL in ambiente Windows, utilizzando le Microsoft Foundation Class. 12/11/2018 Claudio Rocchini, Visual Computing Group
3
Claudio Rocchini, Visual Computing Group
MFC Le Microsoft Foundation Class formano la nota libreria di sviluppo di applicazioni per ambiente Windows. Vedremo come siano state realizzate delle opportune chiamate di libreria per l’interfacciamento di OpenGL. 12/11/2018 Claudio Rocchini, Visual Computing Group
4
Claudio Rocchini, Visual Computing Group
OpenGL OpenGL è il famoso standard per la visualizzazione grafica bi e tridimensionale. E’ supportato da tutte le piattaforme. Le schede grafiche di ultima generazione lo implementano in hardware. 12/11/2018 Claudio Rocchini, Visual Computing Group
5
Claudio Rocchini, Visual Computing Group
Cenni su OpenGL (1) Una introduzione ad OpenGL e’ fuori dagli scopi di questa presentazione. Ne evidenzieremo le caratteristiche necessarie all’interfacciamento con il sistema a finestre. 12/11/2018 Claudio Rocchini, Visual Computing Group
6
Claudio Rocchini, Visual Computing Group
Cenni su OpenGL (2) I comandi di OpenGL sottintendono un contesto grafico di default, la seguente serie di comandi visualizza un triangolo: glBegin(GL_TRIANGLES); glVertex3f(0,0,-10); glVertex3f(10,0,-10); glVertex3f(0,10,-10); glEnd(); 12/11/2018 Claudio Rocchini, Visual Computing Group
7
Claudio Rocchini, Visual Computing Group
Cenni su OpenGL (3) In ogni applicazione Windows si puo’ definire un contesto OpenGL corrente che riceve i comandi grafici. Un applicazione multifinestra puo’ alternare vari contesti grafici OpenGL. 12/11/2018 Claudio Rocchini, Visual Computing Group
8
Claudio Rocchini, Visual Computing Group
MFC+OpenGL Una volta costruita una applicazione standard MFC sono necessarie alcune aggiunte per l’utilizzo di OpenGL all’interno di una finestra. 12/11/2018 Claudio Rocchini, Visual Computing Group
9
Claudio Rocchini, Visual Computing Group
Punti principali Scelta del formato pixel. Creazione di un contesto OpenGL (GLRC). Creazione di un Device contest (DC) associato ad una finestra. Collegamento fra GLRC e DC. 12/11/2018 Claudio Rocchini, Visual Computing Group
10
Inclusione file header
Aggiungere nel file header della view: #include <GL\\gl.h> #include <GL\\glu.h> 12/11/2018 Claudio Rocchini, Visual Computing Group
11
Claudio Rocchini, Visual Computing Group
Inclusione librerie File di Libreria aggiuntivi 12/11/2018 Claudio Rocchini, Visual Computing Group
12
Dati aggiuntivi della View
I seguenti dati sono aggiunti alla classe view: CPalette m_cPalette; // Palette Personale CPalette *m_pOldPalette; // Vecchia Palette CClientDC *m_pDC; // DC della finestra HGLRC m_hrc; // Contesto OpenGL 12/11/2018 Claudio Rocchini, Visual Computing Group
13
Dati per multifinestra
In caso di gestione multifinestra e’ necessario aggiunge alla view il seguente: // IL proprietario del contesto GL static CGlwrapperView * m_glOwner; Nel file …view.cpp si dichiara: CGlwrapperView * CGlwrapperView::m_glOwner = 0; 12/11/2018 Claudio Rocchini, Visual Computing Group
14
Inizializzazione variabili
// E’ importante ricordarsi di inizializzare le variabili nel costruttore della classe. CGlwrapperView::CGlwrapperView() { m_pOldPalette = 0; m_pDC = 0; m_hrc = 0; } 12/11/2018 Claudio Rocchini, Visual Computing Group
15
Claudio Rocchini, Visual Computing Group
Funzione di switch inline BOOL SetGL() { if(m_glOwner!=this) { if(!wglMakeCurrent(m_pDC->GetSafeHdc(),m_hrc)) { AfxMessageBox("GlMakeCurrent Error"); return FALSE; } m_glOwner = this; return TRUE; 12/11/2018 Claudio Rocchini, Visual Computing Group
16
Claudio Rocchini, Visual Computing Group
Messaggi e Virtual Attraverso il Class Wizard e’ necessario inserire alcuni gestori di messaggi 12/11/2018 Claudio Rocchini, Visual Computing Group
17
Claudio Rocchini, Visual Computing Group
Gestori necessari I gestori necessari sono: Create PrecreateWindow(*) OnDraw(*) OnSize OnEraseBkgnd OnDestroy (*) Gia’ dichiarati dall’Application Wizard 12/11/2018 Claudio Rocchini, Visual Computing Group
18
Claudio Rocchini, Visual Computing Group
Create (1/5) //Creazione finestra if( !CWnd::Create(lpszClassName, lpszWindowName, dwStyle, rect, pParentWnd, nID, pContext) ) return FALSE; 12/11/2018 Claudio Rocchini, Visual Computing Group
19
Claudio Rocchini, Visual Computing Group
Create (2/5) // Creazione DC (Contesto grafico standard) m_pDC = new CClientDC(this); ASSERT(m_pDC != NULL); // Setta il pixel format e crea la palette if (!SetupPixelFormat(m_pDC)) return FALSE; 12/11/2018 Claudio Rocchini, Visual Computing Group
20
Claudio Rocchini, Visual Computing Group
Create (3/5) // Creazione palette (se necessaria) if( CreateRGBPalette(m_pDC,m_cPalette) ) { m_pOldPalette = m_pD->SelectPalette( &m_cPalette, FALSE); m_pDC->RealizePalette(); } 12/11/2018 Claudio Rocchini, Visual Computing Group
21
Claudio Rocchini, Visual Computing Group
Create (4/5) // Crea e setta il contesto OPENGL m_hrc = wglCreateContext( m_pDC->GetSafeHdc()); if(m_hrc==NULL) { AfxMessageBox("OpenGL contest fail"); return FALSE; } 12/11/2018 Claudio Rocchini, Visual Computing Group
22
Claudio Rocchini, Visual Computing Group
Create (5/5) // Inizializzazioni GL SetGL(); InitGL(); 12/11/2018 Claudio Rocchini, Visual Computing Group
23
Claudio Rocchini, Visual Computing Group
Gestione palette La palette serve solo in caso di schermo a 256 colori(obsoleto). Si realizza tramite le specifiche della Microsoft. Si puo’ scaricare l’implementazione di default dal sito: vcg.iei.pi.cnr.it/˜rocchini/corso.html 12/11/2018 Claudio Rocchini, Visual Computing Group
24
Claudio Rocchini, Visual Computing Group
Pixel Format (1/2) Prima di inizializzare OpenGL e’ necessario settare il tipo di supporto pixel, che comprende: Numero di pixel colore Profondita’ z-buffer Tipo di buffer (singolo/doppio) … I settaggi vengono inseriti nella struttura PIXELFORMATDESCRIPTOR. 12/11/2018 Claudio Rocchini, Visual Computing Group
25
Claudio Rocchini, Visual Computing Group
Pixel Format(2/2) // Esempio di codice di richiesta di formato if ( (pixelformat = ChoosePixelFormat(pDC->GetSafeHdc(), &pfd)) == 0 ) { AfxMessageBox("ChoosePixelFormat failed"); return FALSE; } if (SetPixelFormat(pDC->GetSafeHdc(), pixelformat, &pfd) == FALSE) AfxMessageBox("SetPixelFormat failed"); 12/11/2018 Claudio Rocchini, Visual Computing Group
26
Inizializzazioni OpenGL
Le inizializzazioni di OpenGL non fanno parte del sistema di finestre, ma sono state citate perche’ indispensabili per la visualizzazione della finestra OpenGl (per evitare l’effetto “finestra nera”). 12/11/2018 Claudio Rocchini, Visual Computing Group
27
Esempi di settaggi OpenGL
glClearDepth(1.0f); glShadeModel( GL_SMOOTH ); glEnable(GL_DEPTH_TEST); glEnable(GL_COLOR_MATERIAL); glDisable(GL_CULL_FACE); glEnable(GL_LIGHT0); fv4[0]=0.1f; fv4[1]=0.1f; fv4[2]=0.1f; fv4[3]=1.0f; glLightModelfv(GL_LIGHT_MODEL_AMBIENT, fv4); glLightfv(GL_LIGHT0, GL_POSITION, fv4); glLightfv(GL_LIGHT0, GL_DIFFUSE, fv4); glEnable(GL_LIGHTING); 12/11/2018 Claudio Rocchini, Visual Computing Group
28
Claudio Rocchini, Visual Computing Group
OnDestroy (1/2) Alla fine dell’utilizzo delle strutture OpenGl e’ importante chiamare le funzioni di rilascio delle risorse. Queste funzioni devono essere chiamate subito prima la distruzione della finestra View. 12/11/2018 Claudio Rocchini, Visual Computing Group
29
Claudio Rocchini, Visual Computing Group
OnDestroy (2/2) void CGlwrapperView::OnDestroy() { SetGL(); glFinish(); wglMakeCurrent(NULL, NULL); if (m_hrc) ::wglDeleteContext(m_hrc); if (m_pOldPalette) m_pDC->SelectPalette(m_pOldPalette, FALSE); if (m_pDC) delete m_pDC; m_glOwner = NULL; CView::OnDestroy(); } 12/11/2018 Claudio Rocchini, Visual Computing Group
30
Claudio Rocchini, Visual Computing Group
PreCreateWindow // Lo stile della finestra deve contenere le seguenti specifiche: BOOL CGlwrapperView::PreCreateWindow( CREATESTRUCT& cs) { cs.style |= WS_CLIPSIBLINGS | WS_CLIPCHILDREN | CS_OWNDC; return CView::PreCreateWindow(cs); } 12/11/2018 Claudio Rocchini, Visual Computing Group
31
Claudio Rocchini, Visual Computing Group
Erase Background // Questa callback impedisce al sistema di disegnare lo sfondo bianco di defalt: BOOL CGlwrapperView::OnEraseBkgnd(CDC* pDC) { return TRUE; } 12/11/2018 Claudio Rocchini, Visual Computing Group
32
Claudio Rocchini, Visual Computing Group
OnSize (1/3) OnSize e’ chiamata alla creazione della Finestra e ad ogni cambiamento di dimensione. Si deve occupare di comunicare ad OpenGL l’effettiva dimensione della finestra (viewport) Deve settare il tipo di proiezione di visualizzazione (ortogonale/prospettica) 12/11/2018 Claudio Rocchini, Visual Computing Group
33
Claudio Rocchini, Visual Computing Group
OnSize (2/3) void CGlwrapperView::OnSize(UINT nType, int cx, int cy) { CView::OnSize(nType, cx, cy); if(cx!=0 && cy!=0) … gestione dimensione… } 12/11/2018 Claudio Rocchini, Visual Computing Group
34
Claudio Rocchini, Visual Computing Group
OnSize (3/3) const float fNearP = 0.1f; const float fFarP = 20.0f; const float fPAngle = 45.0f; SetGL(); glViewport(0, 0, cx, cy); GLfloat fAspect; if (cy) fAspect = GLfloat(cx)/cy; else fAspect = 1.0f; glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(fPAngle, fAspect, fNearP, fFarP); glMatrixMode(GL_MODELVIEW); 12/11/2018 Claudio Rocchini, Visual Computing Group
35
Claudio Rocchini, Visual Computing Group
OnDraw, introduzione OnDraw, finalmente, visualizza effettivamente il contesto OpenGl. Deve contenere il codice utente per la visualizzazione 12/11/2018 Claudio Rocchini, Visual Computing Group
36
OnDraw, sezione critica (1/2)
OpenGL e intrinsecamente asincrono, vale a dire che la visualizzazione continua in parallelo con il programma. E’ possibile che il sistema chiami più volte OnDraw, prima che la visualizzazione sia terminata. 12/11/2018 Claudio Rocchini, Visual Computing Group
37
OnDraw, sezione critica (2/2)
void CGlwrapperView::OnDraw(CDC* pDC) { if(pDC==NULL) return; static BOOL bBusy = FALSE; if(bBusy) return; bBusy = TRUE; … SEZIONE PRINCIPALE… bBusy = FALSE; } 12/11/2018 Claudio Rocchini, Visual Computing Group
38
OnDraw, sezione principale
SetGL(); // Setta il contesto corrente // Cancellazione buffer glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); glLoadIdentity(); … COMANDI UTENTE… glFinish(); SwapBuffers(wglGetCurrentDC()); 12/11/2018 Claudio Rocchini, Visual Computing Group
39
Claudio Rocchini, Visual Computing Group
OnDraw Ottimizzata SetGL(); // Setta il contesto corrente glLoadIdentity(); … COMANDI UTENTE… glFinish(); SwapBuffers(wglGetCurrentDC()); glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); 12/11/2018 Claudio Rocchini, Visual Computing Group
40
Claudio Rocchini, Visual Computing Group
OnDraw, comandi utente Esempio di comandi utente (visualizzazione triangolo): glBegin(GL_TRIANGLES); glVertex3f(0,0,-10); glVertex3f(10,0,-10); glVertex3f(0,10,-10); glEnd(); 12/11/2018 Claudio Rocchini, Visual Computing Group
41
Claudio Rocchini, Visual Computing Group
Applicazione L’applicazione e’ finalmente pronta per essere compilata ed eseguita. 12/11/2018 Claudio Rocchini, Visual Computing Group
42
Un comodo tool: Trackball
Nel sito web del corso e’ possibile scaricare il sorgente del programma, che comprende la classe Trackball per La manipolazione della vista. 12/11/2018 Claudio Rocchini, Visual Computing Group
43
Visualizzazioni animate, intro
La visualizzazione della finestra OpenGl avviene su richiesta del sistema, quando e’ necessario ridisegnarne il contenuto. In alcune applicazioni e’ necessario invece ridisegnare la finestra OpenGL su richiesta dell’applicazione. 12/11/2018 Claudio Rocchini, Visual Computing Group
44
Claudio Rocchini, Visual Computing Group
Animazioni, il Timer Una prima possibilità è quella di usare un timer (classe Ctimer), che periodicamente genera il messaggio WM_TIMER. Il messaggio può essere gestito dall’applicazione per generare animazioni. Questa soluzione non è però efficace; infatti il timer non è affidabile per intervalli inferiori al secondo. 12/11/2018 Claudio Rocchini, Visual Computing Group
45
Claudio Rocchini, Visual Computing Group
Animazioni, OnIdle Una soluzione migliore è l’utilizzo della funzione OnIdle, della classe Applicazione. Tale funzione viene chiamata tutte le volte che il sistema ha finito le sue operazioni. 12/11/2018 Claudio Rocchini, Visual Computing Group
46
Claudio Rocchini, Visual Computing Group
Esercizi Scaricare lo scheletro di applicazione glwrapper, oppure rigenerarlo da zero e: Visualizzare grafici di funzioni da R2 a R. Visualizzare oggetti animati nel tempo, utilizzando Onidle Realizzare una versione di graphedit visualizzata in OpenGL. 12/11/2018 Claudio Rocchini, Visual Computing Group
47
Claudio Rocchini, Visual Computing Group
Contatti Claudio Rocchini Visual Computing Group Istituto Elaborazione Informazione Area della Ricerca di Pisa Tel: 12/11/2018 Claudio Rocchini, Visual Computing Group
Presentazioni simili
© 2024 SlidePlayer.it Inc.
All rights reserved.