QtMeshEditor
Automate your 3D asset pipeline โ scan, validate, convert, fix, and merge 3D assets with GUI + CLI + CI/CD support.
Open 3D files from your OS โ after install, double-click .fbx, .glb, .gltf, .obj, .dae, .stl, .ply, .mesh, and PS1 .rsd/.tmd in Finder, Explorer, or your Linux file manager (or use Open With). QtMeshEditor loads the model in the running window; a second launch focuses the existing instance instead of spawning another process. Portable Windows ZIP users can run bin/scripts/register-windows-file-associations.ps1 to register handlers without admin rights.
Star if you like it!

QtMesh Cloud Badges
๐ CI/CD โ GitHub Actions
Available on the GitHub Actions Marketplace.

Versioning
- Always follow the latest GitHub release โ use the Marketplace floating tag
fernandotonon/QtMeshEditor@v1 (same pattern as the Marketplace example). The composite action defaults to image-tag: latest, so the Docker CLI tracks the newest published ghcr.io/fernandotonon/qtmesh image.
- Reproducible builds โ pin the action and the container to the same semver as this repositoryโs
project(QtMeshEditor VERSION โฆ) in CMakeLists.txt (currently 3.38.0). After bumping the version in CMake, run ./scripts/sync-doc-versions-from-cmake.sh to refresh the pinned refs in README.md and the docs site fallback; CI enforces the match with ./scripts/sync-doc-versions-from-cmake.sh --check.
Pinned workflow template (action + ghcr.io image aligned):
name: QtMesh Scan
on:
push:
branches: [ "master" ]
jobs:
scan-assets-qtmesh:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Run QtMesh scan
uses: fernandotonon/QtMeshEditor@3.38.0
with:
command: scan
image-tag: "3.38.0"
env:
QTMESH_CLOUD_TOKEN: ${{ secrets.QTMESH_CLOUD_TOKEN }}
Floating ref (auto-updates when the v1 tag moves on release):
- name: Run QtMesh scan
uses: fernandotonon/QtMeshEditor@v1
with:
command: scan
QTMESH_CLOUD_TOKEN is forwarded into the container and used by scan upload. GitHub Actions metadata (GITHUB_*) is also forwarded so uploads include meta fields (branch/commit/run and context used by QtMesh Cloud).
To fail CI when upload fails, add qtmesh-strict-upload: true (or pass --strict-upload in options).
Release tags are listed on the releases page (also referenced in QtMesh Cloud onboarding).
More CI examples
# Validate a specific mesh
- uses: fernandotonon/QtMeshEditor@3.38.0
with:
command: validate
input-file: ./models/character.fbx
image-tag: "3.38.0"
# Convert FBX โ glTF
- uses: fernandotonon/QtMeshEditor@3.38.0
with:
command: convert
input-file: ./models/character.fbx
output-file: ./output/character.gltf2
image-tag: "3.38.0"
# Resample Mixamo animations (200+ keyframes โ 30)
- uses: fernandotonon/QtMeshEditor@3.38.0
with:
command: anim
input-file: ./animations/dance.fbx
output-file: ./output/dance_optimized.fbx
options: --resample 30
image-tag: "3.38.0"
# Get mesh info as JSON
- uses: fernandotonon/QtMeshEditor@3.38.0
id: info
with:
command: info
input-file: ./models/character.fbx
options: --json
image-tag: "3.38.0"
# Docker (alternative โ :latest tracks newest image; pin :3.4.0 to match semver action ref)
# The image is multi-arch (linux/amd64 + linux/arm64), so it runs natively on
# both Intel and Apple Silicon Macs โ no --platform flag or QEMU needed.
docker run --rm -v $(pwd):/workspace ghcr.io/fernandotonon/qtmesh:latest scan ./assets --fail-on error
โ๏ธ QtMesh Cloud Badges
- Sign in at qtmesh.dev and create a project.
- Create a project token in QtMesh Cloud.
- Add the token as a GitHub secret named
QTMESH_CLOUD_TOKEN.
- Run the scan command from Github Actions example above.
Badge markdown (replace and):
[](https://qtmesh.dev)
[](https://qtmesh.dev)
[](https://qtmesh.dev)
๐ง CLI Pipeline (qtmesh)
Same commands locally, in Docker, or in CI:
# Scan a directory for asset issues
qtmesh scan ./assets --fail-on warning
qtmesh scan ./assets --json --report report.json
# Inspect a mesh
qtmesh info model.fbx --json
# Validate geometry
qtmesh validate model.fbx
# Convert between formats
qtmesh convert model.fbx -o model.gltf2
# Convert + Draco-compress the glTF (smaller .glb; needs a Draco-enabled build)
qtmesh convert model.fbx -o model.glb --compress draco
# Fix / optimize
qtmesh fix model.fbx -o fixed.fbx --all
# Animation tools
qtmesh anim model.fbx --list
qtmesh anim model.fbx --rename "Take 001" "Idle" -o renamed.fbx
qtmesh anim model.fbx --resample 30 -o optimized.fbx
qtmesh anim base.fbx --merge walk.fbx run.fbx -o merged.fbx
# Export animation pose as static mesh (3D printing)
qtmesh pose model.fbx --animation "Dance" --count 4 -o pose_%02d.stl
# LOD generation
qtmesh lod model.fbx --auto
# Bake vertex colors โ texture (with UV-seam dilation)
qtmesh bake-vertex-colors model.fbx -o color_map.png --resolution 1024 --dilation 4
qtmesh paint-bake model.fbx --target unreal -o out/ # repack the mesh's PBR textures into an engine layout + sidecar JSON
qtmesh paint-bake model.fbx --target unity -o out/ --resolution 2048 --prefix hero # Unity: metallic+smoothness RGBA, DirectX (+Y down) normal
qtmesh paint-bake --list-targets # generic | unity | unreal | godot | gltf
qtmesh paint --list-stamps # brush stamps (also --list-presets, --list-palettes; all take --json)
qtmesh paint model.fbx --layer list --json # paint layers (layers are a live-session concept; bake to write pixels)
qtmesh paint model.fbx --bake --engine unity -o out/ # alias of paint-bake --target
qtmesh paint model.fbx --apply-stencil decal.png --camera "0,1,4,0,1,0" -o out.mesh # project an image through an explicit camera
# Auto UV unwrap (xatlas โ same library Blender/Godot use)
qtmesh uv model.fbx --unwrap -o unwrapped.glb # overwrite UV0
qtmesh uv model.fbx --unwrap --channel 1 -o lightmap.glb # keep UV0, write UV1 (lightmap workflow)
qtmesh uv model.fbx --info --json # report UV channels + coverage
# Quad retopology (triangle-pairing โ no new deps)
qtmesh retopo model.fbx -o quads.glb # pair every viable triangle into quads
qtmesh retopo model.fbx --target-faces 5000 -o lo.glb # stop early once near target face count
qtmesh retopo model.fbx --max-angle 15 -o conservative.glb # tighter coplanarity gate
# Compute skin weights (inverse-distance heuristic; mesh must have a skeleton)
qtmesh skin model.fbx -o skinned.glb # default 4 influences, falloff 4
qtmesh skin model.fbx --max-influences 8 --falloff 6 -o skinned.glb
qtmesh skin model.fbx --skip-unweighted --merge -o filled.glb # fill missing weights only
# Auto-generate the 52 ARKit blendshapes on a humanoid FACE mesh (for face capture)
qtmesh facerig head.glb -o rigged.glb # fit ARKit template + transfer 52 shapes
qtmesh facerig head.fbx -o rigged.glb --max-shapes 20 --json # cap shapes / machine-readable report
๐จ Paint Tools
ZBrush-style polypaint and full PBR channel texture painting โ Base Color,
Normal, Roughness, Metallic, AO and Emissive โ with a 2D preview panel,
multiple brush tools (paint, erase, fill, color picker, smudge), layers, a
channel picker, channel-aware presets (scratches into roughness, emissive
sparks, edge wear, dirt build-up, sticker), and a one-click bake that turns
vertex colors into a UV-space texture. Every bake merges with the slot's
existing texture rather than overwriting it โ scalar channels collapse into
their lane of the packed ORM map, and Normal-channel sculpts Sobel-convert to a
tangent-space normal and blend onto the existing normal map, all rendering live
under IBL. Symmetry mirrors every stroke in real time across the local or
world X/Y/Z planes (combine axes for 4- or 8-way mirroring; a topology-aware
mode keeps mirrors correct on meshes with an asymmetric UV unwrap), and a
line stabilizer (moving-average or trailing) smooths mouse jitter for clean
strokes. Projection painting projects an image onto the mesh through the
camera โ brush through a stencil, lock the projection to a camera pose, or
project a photo straight onto the visible surface (with backface culling,
depth-limit and per-texel occlusion so it only lands where the camera can see);
and the decal tool drops a placeable image rectangle (drag to move / rotate
/ scale, Enter to commit) onto the surface. Each projection lands in its own
layer.
Quick start (texture paint, GUI):
- Switch to Material Mode (mode bar at the top).
- Select a mesh entity. The Inspector's Texture Paint section
shows a slot picker (every paintable TUS across submeshes) and a 256ร256
live preview of the active texture.
- Click the paint brush button in the toolbar to enable painting. The
first click on the mesh auto-creates a paint session against the active
slot (or you can pre-create with Create / Attach Texture).
- Pick a tool from the row at the top of the panel: โ Paint, โซ Erase, โง Fill,
โฐ Pick (eyedropper), โฟ Smudge. Brush color/radius/strength/falloff comes
from the shared Paint Brush section above the toolbar's brush popup.
- Left-click-drag on either the 3D mesh or the 2D preview panel. Both
drive the same paint buffer; the 2D preview updates in real time and a
brush ring shows where the cursor maps on the 3D surface (and vice versa).
- Saveโฆ / Loadโฆ round-trips the buffer to disk as PNG (or any format
QImage can write).
Vertex paint (GUI):
Same flow, but vertex paint operates in Edit Mode instead. Press Tab
on a selected mesh to enter Edit Mode, then tick Vertex Color Preview in
the Edit Mode Tools section to see vertex colors live.
Bake Vertex Colors โ Texture rasterizes the active mesh's vertex colors
into a UV-space PNG via barycentric interpolation, then dilates the result
outward by N pixels to mask UV-seam bleed at MIP-map time.
Headless (CLI):
qtmesh bake-vertex-colors model.fbx -o color_map.png --resolution 1024 --dilation 4
qtmesh paint-bake model.fbx --target unreal -o out/ # repack the mesh's PBR textures into an engine layout + sidecar JSON
qtmesh paint-bake model.fbx --target unity -o out/ --resolution 2048 --prefix hero # Unity: metallic+smoothness RGBA, DirectX (+Y down) normal
qtmesh paint-bake --list-targets # generic | unity | unreal | godot | gltf
qtmesh paint --list-stamps # brush stamps (also --list-presets, --list-palettes; all take --json)
qtmesh paint model.fbx --layer list --json # paint layers (layers are a live-session concept; bake to write pixels)
qtmesh paint model.fbx --bake --engine unity -o out/ # alias of paint-bake --target
qtmesh paint model.fbx --apply-stencil decal.png --camera "0,1,4,0,1,0" -o out.mesh # project an image through an explicit camera
Export. Vertex colors are preserved on export to formats that support
them (glTF preferred โ verified round-trip).
Notes / limitations.
- Brush size is in local mesh units (shared with vertex paint). For texture
paint we divide by mesh bounding-box extent and clamp to a UV-friendly
range, so 0.25 produces a sensible stamp on both a unit cube and a
100-unit character.
- Painting auto-rebinds every TUS named
albedo or diffuse_map on the
active material โ imported PBR materials alias the diffuse texture under
both, and rebinding only one would leave the other pointing at the
original.
- Bake uses fan triangulation of n-gon faces; concave faces should be
pre-triangulated.
โจ Merge Mixamo Animations in Seconds
Download animations from Mixamo, drop them into QtMeshEditor, and merge into a single file โ export as glTF, FBX, Collada, OBJ, or Ogre Mesh.

๐ฌ More in Action
| Split View | Skeleton Animation Controls |
|---|
 |  |
| MCP tools (AI Agent Control) | Bone Weight Visualization |
 |  |
๐ค AI-enhanced Material Editor

๐ฎ Features
- Asset scanning โ ESLint for 3D assets: check naming, complexity, skeletons, formats
- QtMesh Cloud โ sign in, upload asset projects (model + textures + materials + animations), browse/open from qtmesh.dev; CLI (
qtmesh cloud โฆ) and MCP (cloud_* tools) parity
- 40+ format support โ FBX, glTF, OBJ, Collada, STL, Ogre Mesh, and more
- Animation merge โ combine Mixamo clips into one file
- Animation resampling โ reduce keyframe density for game engines
- Pose export โ bake animation frames as static meshes (3D printing)
- LOD generation โ automatic level-of-detail mesh reduction
- Paint tools โ vertex paint, texture paint (BaseColor), bake vertex colors to texture with seam dilation
- Material editor โ visual editing with AI-assisted generation; PBR + HDR/IBL materials look correct on first import (bundled studio HDRI, ACES tonemap, env intensity/tint per material)
- Skeleton inspection โ bone weights, debug overlays, animation preview
- AI part segmentation & PartOps โ detect a character's parts (head/torso/arms/legs), then split into named submeshes, explode into separate scene nodes, join them back, or solidify thin-shell parts; GUI +
qtmesh segment --split-parts / --explode-parts + MCP (split_mesh_by_segments, explode_mesh_parts, join_mesh_parts) โ see docs/PART_OPS.md
- Scene management โ duplicate (Ctrl+D), group (Ctrl+G), snap, pivot modes
- Performance capture โ video/webcam โ facial morph animation (ARKit blendshapes), head pose, and full-body skeletal capture onto humanoid rigs; live preview + record in the editor,
qtmesh mocap on the CLI (-DENABLE_MOCAP builds)
- AI chat โ natural language scene editing via local LLMs
- MCP server โ 57+ tools for AI agents (Claude, Cursor, etc.), including HDR/IBL (
set_hdr_environment, set_tonemap, โฆ) and QtMesh Cloud (cloud_*)
- REST API โ HTTP interface for external automation
๐ฆ Install
| Platform | Command |
|---|
| Windows | winget install FernandoTonon.QtMeshEditor |
| macOS | brew tap fernandotonon/qtmesheditor && brew trust fernandotonon/qtmesheditor && brew install qtmesheditor |
| Linux | sudo snap install qtmesheditor |
| Docker | docker run --rm ghcr.io/fernandotonon/qtmesh --help |
๐ฅ Download latest release ยท ๐ Website & docs
๐ Format Support
| Format | Extension | Import | Export | Skeleton/Animation |
|---|
| FBX Binary | .fbx | โ
| โ
| โ
|
| glTF 2.0 | .gltf2 / .glb2 | โ
| โ
| โ
|
| Collada | .dae | โ
| โ
| โ
|
| OBJ | .obj | โ
| โ
| โ |
| STL | .stl | โ
| โ
| โ |
| Ogre Mesh | .mesh / .mesh.xml | โ
| โ
| โ
|
| PlayStation TMD | .tmd | โ
| โ
| โ |
| PlayStation RSD | .rsd | โ
| โ
| โ |
| 3DS | .3ds | โ
| โ
| โ |
| Stanford PLY | .ply | โ
| โ
| โ |
| Psy-Q PLY (PlayStation) | .ply | โ
| โ
| โ |
.ply is dispatched by content: Stanford (ply header) vs Psy-Q (@PLYโฆ header). See documentation/playstation-rsd-ply.md.
Import supports all formats provided by Assimp (40+).
๐ Documentation ยท ๐ Build from source ยท ๐ Report issues ยท ๐ฌ Contribute