2012-02-04 14 views
6

Dal codice che ho di un programma che disegna e sposta un quadrato attorno a una finestra dell'applicazione, ho problemi durante il ridimensionamento della finestra dell'applicazione. Quando gestisco un ridimensionamento e altero gli stati di conseguenza, tutto sullo schermo che deve essere disegnato ed era prima che il ridimensionamento svanisca. Non ho idea del perché, poiché nessuna delle coordinate interne degli oggetti viene modificata durante il ridimensionamento della finestra.Gestione del ridimensionamento della finestra utilizzando OpenGL e SDL

La mia domanda è qualcuno mi può puntare nella giusta direzione per risolvere il mio problema (Il codice compila bene)

void ResizeWindow() 
{ 
    screen_width = event.resize.w; 
    screen_height = event.resize.h; 

    SDL_SetVideoMode(screen_width, screen_height, bpp, SDL_OPENGL | SDL_RESIZABLE | SDL_DOUBLEBUF); 

    glViewport(0, 0, screen_width, screen_height); 
    glMatrixMode(GL_PROJECTION); 
    glOrtho(0, screen_width, 0, screen_height, -1, 1); 
    glLoadIdentity(); 
    glMatrixMode(GL_MODELVIEW); 
    glLoadIdentity(); 
    glClear(GL_COLOR_BUFFER_BIT); 
    glLoadIdentity(); 
} 

ciclo principale:.

while (running == true) 

{ 

    while(SDL_PollEvent(&event)) 

    { 

     switch(event.type) 

     { 

      case SDL_VIDEORESIZE: ResizeWindow(); break; // resizing called here 
      case SDL_QUIT: running = false; break; 
      case SDL_KEYDOWN: square.Handle_Input(down); break; 
      case SDL_KEYUP: square.Handle_Input(up); break; 

     } 

    } 

    square.Move(); 
    square.Check_Collision(); 

    glClear(GL_COLOR_BUFFER_BIT); 

    square.Draw(); 

    SDL_GL_SwapBuffers(); 

} 

dovrebbe funzionare tutto perfettamente finché la finestra è ridimensionato.

+0

Ho visto la tua domanda precedente, ma non sono riuscito a mettere in evidenza tutti i problemi in quel momento. Confido che tu non abbia risolto i tuoi problemi precedenti. Probabilmente dovresti pubblicare le modifiche che hai apportato per farlo funzionare come la tua risposta e chiudere la domanda. – batbrat

+0

I miei suggerimenti hanno risolto il problema? – batbrat

+0

Ho dormito da quando ho postato questa domanda, la tua risposta ha senso, specialmente il bit su SDL_SetVideoMode, a guardarlo, mi sembra un errore stupido da parte mia. La prima domanda che ho postato ha avuto un problema che è stato un altro grande errore da parte mia; Stavo lavorando dalla memoria e non ho cercato i parametri glOrtho. Ho avuto come andare da sinistra a destra come 0-0. Proverò ora i tuoi suggerimenti –

risposta

13

Ho copiato il codice e spiegherò cosa sta succedendo per riga. Dovrebbe aiutarti a vedere non solo il motivo per cui lo schermo diventa bianco dopo un ridimensionamento, ma anche aiutarti a rimuovere elementi che non ti servono realmente.

void ResizeWindow() 
{ 

Queste righe successive sono buone! Hai ottenuto la nuova larghezza e altezza dello schermo dall'evento di ridimensionamento. Suppongo che l'evento sia accessibile a questo punto nel tuo codice.

screen_width = event.resize.w; 
    screen_height = event.resize.h; 

Dubito che sia necessaria questa chiamata allo SDL_SetViedoMode. Mi aspetto che venga utilizzato solo durante l'impostazione della finestra OpenGL. Al momento non ho esperienza con l'utilizzo di SDL, quindi non posso esserne certo. Ho fatto una rapida occhiata alla documentazione e sembra supportare l'utilizzo come mi aspettavo.

SDL_SetVideoMode(screen_width, screen_height, bpp, SDL_OPENGL | SDL_RESIZABLE | SDL_DOUBLEBUF); 

Ora arriviamo alla roba interessante di GL. Hai ridimensionato il viewport, che è necessario.

glViewport(0, 0, screen_width, screen_height); 

Ora, stai creando una nuova matrice di proiezione per mantenere le proporzioni (a meno che non mi sbagli). Hai cambiato la modalità matrice e hai impostato una matrice di proiezione ortografica, il che è sensato.

glMatrixMode(GL_PROJECTION); 
    glOrtho(0, screen_width, 0, screen_height, -1, 1); 

Ora, è possibile impostare la matrice di proiezione all'identità, sovrascrivendo il vecchio matrice di proiezione OpenGL e disfare tutto il buon lavoro che hai fatto. Questo è il motivo per cui lo schermo si è oscurato.

glLoadIdentity(); 

Ora, si passa alla matrice model-view e impostarlo su identità, che non è davvero necessario, fino a quando si imposta correttamente altrove.

glMatrixMode(GL_MODELVIEW); 
    glLoadIdentity(); 

Dubito che abbiate davvero bisogno di questa linea successiva. Perché dovresti cancellare lo schermo dopo un ridimensionamento, comunque? Lo vuoi ridisegnare, ma sono sicuro che la tua funzione di disegno cancellerà lo schermo e disegnerà l'oggetto che verrà chiamato automaticamente dopo che l'aggiornamento è terminato.

glClear(GL_COLOR_BUFFER_BIT); 

E sicuramente non è necessario reimpostare l'identità della matrice vista modello per l'identità per la seconda volta. OpenGL è ancora in modalità vista modello e quella matrice era già impostata su identità! Ricorda che OpenGL è una macchina a stati!

glLoadIdentity(); 
} 
1

Un problema che probabilmente hai è, che il ridimensionamento di una finestra con SDL viene creato un nuovo contesto OpenGL, il che significa che tutte le cose che hai caricato prima (texture, oggetti vertex buffer) e lo stato si imposta (come vertice puntatori di array) vengono persi. È necessario reinizializzarli se si utilizza SDL. Se si desidera mantenerli, non utilizzare SDL per la gestione delle finestre. Raccomando GLFW.

Questo

void ResizeWindow() 

{ 

screen_width = event.resize.w; 
screen_height = event.resize.h; 

SDL_SetVideoMode(screen_width, screen_height, bpp, SDL_OPENGL | SDL_RESIZABLE | SDL_DOUBLEBUF); 

glViewport(0, 0, screen_width, screen_height); 
glMatrixMode(GL_PROJECTION); 
glOrtho(0, screen_width, 0, screen_height, -1, 1); 
glLoadIdentity(); 
glMatrixMode(GL_MODELVIEW); 
glLoadIdentity(); 
glClear(GL_COLOR_BUFFER_BIT); 
glLoadIdentity(); 

} 

è il modello più comune di anti trovato nel codice principianti OpenGL. I comandi di disegno e la gestione dello stato che influenza il disegno appartengono alla funzione di disegno. Questo è il seguente:

glViewport(0, 0, screen_width, screen_height); 
glMatrixMode(GL_PROJECTION); 
glOrtho(0, screen_width, 0, screen_height, -1, 1); 
glLoadIdentity(); 
glMatrixMode(GL_MODELVIEW); 
glLoadIdentity(); 
glClear(GL_COLOR_BUFFER_BIT); 
glLoadIdentity(); 

Se si desidera un programma OpenGL robusto mai metterli (solo) nel gestore di ridimensionamento. Appartengono agli altri comandi di disegno.

+0

Penso di vedere quello che stai dicendo. Non c'è davvero un minimo sforzo per mantenere il programma in esecuzione normale durante il ridimensionamento in SDL? –

+0

Quindi ha bisogno della chiamata a SDL_SetVideoMode? In una nota a parte, non è sensato ridimensionare il viewport e impostare la proiezione sia all'inizio che durante il ridimensionamento? In effetti, se voglio preservare le proporzioni, penso che sia essenziale. Per quanto riguarda la matrice modelview, l'avrei impostata durante il disegno, se necessario. Naturalmente, questo non tiene conto delle pratiche OpenGL moderne e considera solo la modalità immediata. – batbrat

+0

Sono d'accordo che i comandi di gestione dello stato e di disegno dovrebbero andare nella funzione di disegno. Tuttavia, ho trovato conveniente avere la matrice di proiezione e il viewport impostati nella funzione di ridimensionamento (e la funzione di inizializzazione) quando si fanno cose semplici. – batbrat

Problemi correlati