/ tools / mesh-converter
Sign in
tools / mesh-converter
mesh-converter
Go to fileHistoryFork
.githubMesh converter: upload, view, and export meshes across formats
examplesConvert real mesh formats with meshio via Pyodide
publicMesh converter: upload, view, and export meshes across formats
srcShare meshes as self-contained URLs
.gitignoreMesh converter: upload, view, and export meshes across formats
.oxlintrc.jsonMesh converter: upload, view, and export meshes across formats
index.htmlConvert real mesh formats with meshio via Pyodide
package-lock.jsonMesh converter: upload, view, and export meshes across formats
package.jsonMesh converter: upload, view, and export meshes across formats
README.mdShare meshes as self-contained URLs
tsconfig.app.jsonMesh converter: upload, view, and export meshes across formats
tsconfig.jsonMesh converter: upload, view, and export meshes across formats
tsconfig.node.jsonMesh converter: upload, view, and export meshes across formats
vite.config.tsMesh converter: upload, view, and export meshes across formats

mesh-converter#

A static web app for converting meshes between formats: upload a mesh file, inspect it in an interactive 3D view (shaded, wireframe, shaded + wireframe, or points), and download it in a format of your choice. Formats differ in what they can store, and the UI shows exactly which attributes (normals, colors) would be dropped by a lossy conversion.

Conversion is powered by meshio running in the browser via Pyodide — no server, all mesh I/O happens client-side. The first visit downloads the Python runtime (~15 MB from the jsDelivr CDN, cached afterwards).

Format Extension positions/faces normals colors notes
PLY (Polygon File Format) .ply ✓ ✓ ✓
Wavefront OBJ .obj ✓ ✓ —
STL .stl ✓ — — binary
OFF (Object File Format) .off ✓ — —
VTK legacy .vtk ✓ ✓ ✓
VTU (VTK XML) .vtu ✓ ✓ ✓
Gmsh MSH .msh ✓ — —
XDMF .xdmf ✓ ✓ ✓ h5py†
MED (Salome) .med ✓ ✓ ✓ h5py†
H5M (MOAB) .h5m ✓ ✓ ✓ h5py†
AVS-UCD .avs ✓ ✓ ✓
Abaqus .inp ✓ — —
Nastran .bdf ✓ — —
Medit .mesh ✓ — —
Netgen .vol ✓ — —
MDPA (Kratos) .mdpa ✓ — —
Tecplot .dat ✓ — —
DOLFIN XML .xml ✓ — —
PERMAS .post ✓ — —

† HDF5-based formats need the h5py Pyodide package (~4 MB); it is loaded lazily the first time such a format is used, so the default footprint stays small.

✓ marks what this app preserves when writing the format: vertex normals map to each format's native representation (nx/ny/nz properties in PLY, vn lines in OBJ, a Normals point-data array elsewhere) and vertex colors likewise (red/green/blue in PLY, an RGB point-data array elsewhere). On import, quads and polygons are fan-triangulated; volume cells are skipped.

Some meshio formats are deliberately absent: ansys, cgns, su2, and ugrid cannot roundtrip their own output in meshio 5.3.5; exodus fails writing under wasm; flac3d holds volume cells only; wkt's reader hangs on non-toy meshes; tetgen spans two files; svg is write-only.

A built-in sample mesh (a rainbow torus with normals and vertex colors) is available from the UI for trying things out without a file, and examples/ holds it pre-exported in a few formats. An on-demand "estimate export sizes" action serializes the loaded mesh to every format in memory and shows the resulting file sizes in the format table and export dropdown.

A loaded mesh can be shared as a self-contained link: "Copy share link" packs the original uploaded file (byte-identical, in its original format) together with the chosen export format and view mode into the URL fragment — deflate-compressed and base64url-encoded after #share=. Nothing is uploaded; the data lives in the URL itself, so whoever opens the link sees the mesh and can download it in any format. Links are capped at 65,000 characters (roughly a 100–300 KB mesh file, depending on how well it compresses); beyond that the app says the mesh is too large to share by URL.

Development#

npm install
npm run dev      # local dev server
npm run build    # static build in dist/

Built with Vite, React, TypeScript, and three.js (react-three-fiber).

How it works#

  • src/mesh/bridge.py runs inside Pyodide: it reads/writes mesh files with meshio and exchanges arrays with JS as raw little-endian buffers through Pyodide's in-memory filesystem.
  • src/mesh/meshio.ts loads Pyodide (script tag in index.html), installs meshio via micropip, and wraps the bridge in typed async parseMeshFile/serializeMesh functions built on the internal MeshData representation (typed arrays of positions, triangle indices, optional normals/colors).
  • src/mesh/formats.ts declares the supported formats and which attributes each preserves; the upload, capability table, and loss-warning UI derive from it. To add a meshio-supported format, add a descriptor there (with pyodidePackages if it needs extra prebuilt packages such as h5py) and, if it stores normals/colors in a format-specific way, teach bridge.py how to map them.
↑↓ move↵openescclose