This repository demonstrates a complete mesh-to-video rendering pipeline using Gmsh, meshio, PyVista, and FFmpeg, starting from a raw STL surface and ending with a rotating visualization video.
The goal of this project is to:
- Generate a surface mesh from an STL model
- Convert it into a VTK-compatible format
- Render it off-screen on an HPC environment
- Produce a smooth rotation video from rendered frames
Stanford_Bunny.stl
↓
Gmsh (surface meshing)
↓
bunny.msh
↓
meshio (format cleanup & conversion)
↓
bunny.vtu
↓
PyVista (off-screen rendering)
↓
PNG frame sequence
↓
FFmpeg
↓
bunny_mesh.mov / .mp4
Each step exists for a specific technical reason, explained below.
Convert the raw STL surface into a clean 2D triangular surface mesh.
- Surface-only mesh (2D): No volume tetrahedralization
- Controlled mesh resolution: Ensures reasonable runtime on HPC
gmsh.merge("Stanford_Bunny.stl")
angle = 40 * math.pi / 180.0
gmsh.model.mesh.classifySurfaces(angle, True, False, math.pi)
gmsh.option.setNumber("Mesh.CharacteristicLengthMin", 0.01)
gmsh.option.setNumber("Mesh.CharacteristicLengthMax", 0.05)
gmsh.model.mesh.generate(2)
gmsh.write("bunny.msh")- PyVista / VTK do not natively support
.mshwell - Gmsh
.mshfiles may contain:cell_setspoint_setsfield_data
These often cause PyVista to fail or misinterpret the mesh.
Use meshio as a clean intermediate layer.
m = meshio.read("bunny.msh")
# Remove metadata that can break PyVista
m.cell_sets = {}
m.point_sets = {}
m.field_data = {}
meshio.write("bunny.vtu", m)A clean, VTK-compatible .vtu file that PyVista can load reliably.
- Running on HPC / SSH
- No X server
- No interactive window
Use off-screen rendering with PyVista + VTK.
pv.OFF_SCREEN = True
pl = pv.Plotter(off_screen=True)Instead of rotating the camera (which is unstable in off-screen mode),
the mesh itself is rotated for each frame.
for i in range(n_frames):
mesh = mesh0.copy(deep=True)
mesh.rotate_z(step * i, point=mesh.center, inplace=True)
pl.remove_actor(actor)
actor = pl.add_mesh(mesh, ...)
pl.show(screenshot=fname, auto_close=False)VTK actors do not reliably support geometry mutation in off-screen mode.
Removing and re-adding ensures frame correctness.
frames/frame_0000.pngframes/frame_0001.png- …
frames/frame_0179.png
Each frame corresponds to a 2-degree rotation, totaling 360°.
module load ffmpegffmpeg -y -framerate 30 \
-i frames/frame_%04d.png \
-c:v prores_ks -profile:v 3 -pix_fmt yuv422p10le \
bunny_mesh.movThis avoids color artifacts and plays correctly in QuickTime.
- Surface mesh (
bunny.msh) - VTK mesh (
bunny.vtu) - Frame sequence (
frames/*.png) - Rotation video (
bunny_mesh.mov) - Fully reproducible pipeline
