≡ Menu

Creare una GIF animata di un toro 3D utilizzando PyOpenGL e Pygame

In questo tutorial, ti guiderò attraverso la creazione di un programma Python per visualizzare un toro 3D rappresentato con linee e farlo ruotare intorno al suo asse utilizzando PyOpenGL e Pygame. Infine, mostrerò come generare e salvare una GIF animata del toro ruotante.

Prerequisiti:
Prima di iniziare, assicurati di aver installato le seguenti dipendenze:

pip install PyOpenGL PyOpenGL_accelerate numpy pygame imageio imageio[ffmpeg]

Passo 1: Importare le librerie necessarie
Innanzitutto, importiamo le librerie che useremo nel nostro codice:

import pygame
from pygame.locals import *
from OpenGL.GL import *
from OpenGL.GLUT import *
from OpenGL.GLU import *
import numpy as np
import imageio

Passo 2: Creare la funzione per generare il toro

Creiamo una funzione chiamata torus che genera i vertici e gli indici del toro. La funzione accetta quattro argomenti: il raggio del cerchio interno, il raggio del tubo, il numero di segmenti e il numero di segmenti del tubo.

def torus(radius, tube_radius, num_segments, num_tube_segments):
    vertices = []
    indices = []

    # Calcolare i vertici del toro
    for i in range(num_segments):
        theta = i * 2 * np.pi / num_segments
        for j in range(num_tube_segments):
            phi = j * 2 * np.pi / num_tube_segments

            x = (radius + tube_radius * np.cos(phi)) * np.cos(theta)
            y = (radius + tube_radius * np.cos(phi)) * np.sin(theta)
            z = tube_radius * np.sin(phi)

            vertices.append([x, y, z])

    # Creare gli indici per collegare i vertici
    for i in range(num_segments):
        for j in range(num_tube_segments):
            index1 = (i * num_tube_segments + j) % (num_segments * num_tube_segments)
            index2 = ((i + 1) * num_tube_segments + j) % (num_segments * num_tube_segments)
            index3 = ((i + 1) * num_tube_segments + (j + 1)) % (num_segments * num_tube_segments)
            index4 = (i * num_tube_segments + (j + 1)) % (num_segments * num_tube_segments)

            indices.extend([index1, index2, index3, index4])

    return vertices, indices

Passo 3: Creare la funzione per disegnare il toro

La funzione draw_torus accetta i vertici e gli indici generati dalla funzione torus e utilizza le funzioni OpenGL per disegnare il toro come una serie di linee.

def draw_torus(vertices, indices):
    for i in range(0, len(indices), 4):
        glBegin(GL_LINES)
        glVertex3fv(vertices[indices[i]])
        glVertex3fv(vertices[indices[i + 1]])
        glEnd()

        glBegin(GL_LINES)
        glVertex3fv(vertices[indices[i + 1]])
            glVertex3fv(vertices[indices[i + 2]])
    glEnd()

    glBegin(GL_LINES)
    glVertex3fv(vertices[indices[i + 2]])
    glVertex3fv(vertices[indices[i + 3]])
    glEnd()

    glBegin(GL_LINES)
    glVertex3fv(vertices[indices[i + 3]])
    glVertex3fv(vertices[indices[i]])
    glEnd()

Passo 4: Creare la funzione per catturare i frame OpenGL
Creiamo una funzione chiamata capture_frame che utilizza glReadPixels per catturare i frame direttamente dall’OpenGL e restituisce un array NumPy.

def capture_frame(width, height):
    buffer = (GLubyte * (3 * width * height))()
    glReadPixels(0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, buffer)
    return np.frombuffer(buffer, dtype=np.uint8).reshape(height, width, 3)[::-1, :, :]

Passo 5: Creare la funzione principale

Ora creiamo la funzione principale main che inizializza Pygame, configura la finestra e la visualizzazione OpenGL, e crea un ciclo principale che gestisce gli eventi, aggiorna la rotazione del toro, disegna il toro sullo schermo e cattura i frame per generare la GIF animata.

def main():
    pygame.init()
    display = (800, 600)
    pygame.display.set_mode(display, DOUBLEBUF | OPENGL)

    gluPerspective(45, (display[0] / display[1]), 0.1, 50.0)
    glTranslatef(0.0, 0.0, -5)

    glEnable(GL_DEPTH_TEST)

    torus_vertices, torus_indices = torus(0.5, 0.5, 32, 32)

    frames = []
    num_frames = 360
    frame_interval = 10

    # Ruota il toro di 90 gradi
    glRotatef(90, 0, 1, 0)

    for _ in range(num_frames):
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                quit()

        glRotatef(1, 0, 1, 0)
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)

        glColor3f(1, 1, 1)
        draw_torus(torus_vertices, torus_indices)

        pygame.display.flip()

        # Cattura il frame corrente e aggiungilo all'array di frame
        frame_data = capture_frame(*display)
        frames.append(frame_data)

        pygame.time.wait(frame_interval)

    # Salva l'array di frame come una GIF animata
    imageio.mimsave('torus_animation.gif', frames, fps=30)

    pygame.quit()

if __name__ == "__main__":
    main()

{ 0 comments… add one }

Rispondi