[python] Disegnare un fiocco di neve con OpenGL, Python e pygame

Visto che siamo in tema natalizio vediamo come disegnare un fiocco di neve con Python, OpenGL e pygame.

Questo esercizio riprende in parte quanto già visto per disegnare un poligono sempre con Python e OpenGL.

Anzitutto assicuriamoci di avere installate le librerie PyOpenGL e pygame, qualora non le avessimo sarà sufficiente installarle mediante pip con i seguenti due comandi:

Fatto questo possiamo cominciare a predisporre il nostro programma.

Anzitutto voglio fare un breve approfondimento su alcune funzioni che andremo ad utilizzare.

Cominciamo da gluPerspective. Questa funzione accetta 4 argomenti:

  • fovy: sostanzialmente l’angolo di visione in gradi, come illustrato nell’immagine di seguito
  • aspect ratio: il rapporto tra altezza e larghezza, sostanzialmente ci andiamo ad inserire il rapporto tra le dimensioni del nostro schermo (poi ne discutiamo meglio)
  • zNear: il piano più vicino dopo il quale comincia la visione
  • zFar: il piano più lontano al quale termina la visione
Risultato immagini per gluPerspective"
Immagine presa da GLUT and OpenGL by Robby T. Tan

Ricordiamoci che andremo a disegnare un oggetto in 3D, che dovrà essere posizionato all’interno del tronco di piramide definito dai due piani e dall’angolo di apertura. Se l’oggetto dovesse uscire da questo spazio semplicemente non risulterebbe visibile sullo schermo (o risulterebbe parzialmente tagliato). Da questo si capisce come l’angolo di apertura determinerà la prospettiva e lo spazio di interazione dell’oggetto. La situazione sostanzialmente è la seguente:

Per maggiori approfondimenti consiglio anche una lettura veloce a Perspective distortion (photography)

Dal momento che andrò a posizionare i nostri oggetti a partire da (0,0,0) voglio anche spostare il punto di visione (viewpoint) indietro, in modo da farceli entrare, altrimenti non sarebbero visibili. Per farlo utilizzo la funzione glTranslatef che prendere come argomenti i valori x, y e z sui quali effettuare la traslazione.

Infine voglio disegnare delle linee usando i rispettivi vertici. Per farlo dovrò aggiungere coppie di vertici alla “matrice del mondo” con il metodo glVertex3fv. Nel caso specifico posso disegnare una linea orizzontale che vada da (0,0,0) a (1,0,0) scrivendo le seguenti quattro righe di codice:

Se volessi disegnare un quadrato dovrei disegnare tutte le linee a coppie di vertici, nel modo seguente:

Sostanzialmente quello che facciamo in questo caso potrebbe essere riassunto col seguente schema:

Disegniamo le varie linee del quadrato seguendo le direzioni delle frecce rosse.

Adesso se volessimo limitarci a disegnare un quadrato e farlo ruotare davanti alla telecamera potremmo scrivere il seguente programma:

Grazie a glClearColor(0, 0, 0.1, 1) coloriamo lo sfondo di un blu scuro. Eseguendo il programma vedremo qualcosa di simile:

Il quadrato sarà in movimento ovviamente, grazie alla funzione glRotatef che ruota la matrice del mondo.

Arrivati a questo punto ci manca solo di disegnare il fiocco di neve, ovvero preparare le coppie di vertici di tutte le linee del fiocco di neve stesso.

Per farlo voglio seguire il seguente schema:

Partiamo dal basso e disegniamo un ramo di lunghezza L. Prendiamo come riferimento un angolo α di 45° (ovvero π/4). Alla fine del ramo teniamo conto dell’angolo di arrivo e disegniamo altri due rami, ciascuno spostato di 45°. Procediamo in avanti ripetendo questo schema per n iterazioni.

Creiamo quindi due classi, una per il Fiocco e una per ciascun Ramo, nel modo seguente (nei commenti in Python ulteriori dettagli):

Fatto tutte questo reintegriamo il tutto nella nostra classe iniziale FioccoDiNeve.

Se abbiamo fatto tutto correttamente otterremo il nostro fiocco di neve frattale ruotante in questo modo:

Rispondi

Questo sito usa Akismet per ridurre lo spam. Scopri come i tuoi dati vengono elaborati.