3D Models Pipeline (Meshy AI + Blender)¶
End-to-end pipeline for generating 3D models with Meshy AI and cleaning them up into game-ready assets with clean topology, proper materials, and UE5-correct orientation using Blender in headless mode.
End-to-End Flow¶
flowchart TD
subgraph Generate["1. Meshy AI"]
PROMPT[Text / Image Prompt] --> MESHY[Meshy AI]
MESHY --> GEN["Generate Stage<br/>(geometry + textures)"]
GEN --> POLL[grit_meshy_check]
POLL -->|Pending| POLL
POLL -->|Complete| RAW[Raw .glb Model]
end
subgraph PostProcess["2. Blender Post-Processing"]
RAW --> IMPORT[grit_meshy_remesh<br/>Import to .blend]
IMPORT --> INSPECT[mesh_inspect<br/>Poly/vertex counts]
INSPECT --> DECI{High poly?}
DECI -->|Yes| DEC[mesh_decimate<br/>Reduce poly count]
DECI -->|No| RETOPO
DEC --> RETOPO[mesh_retopo<br/>Clean quad topology]
RETOPO --> FBX[mesh_export_fbx<br/>UE5-ready FBX]
end
subgraph Deliver["3. Deliver"]
FBX --> INGEST[grit_mesh_ingest]
INGEST --> S3[S3 Upload + .meta.json]
S3 --> SLACK[Slack Review]
SLACK -->|Approved| UE[Game-Ready Asset]
end
Unlike the Audio SFX Pipeline which is fully synchronous, 3D generation via Meshy AI is asynchronous — the generation call submits a task and returns immediately. You must poll grit_meshy_check until the task completes before downloading or post-processing the result.
MCP Tool Reference¶
Nine MCP tools form the 3D models pipeline, spanning generation, post-processing, and delivery:
Generation Tools (Meshy AI)¶
| Tool | Depends On | Description |
|---|---|---|
grit_meshy_text_to_3d |
Meshy AI API | Generate a 3D model from a text prompt via Meshy AI. Returns a task ID for status polling. |
grit_meshy_image_to_3d |
Meshy AI API | Generate a 3D model from a reference image via Meshy AI. Returns a task ID for status polling. |
grit_meshy_check |
Meshy AI API | Check the status of a Meshy generation task. Returns pending, processing, completed, or failed. |
grit_meshy_remesh |
Meshy AI API + Blender | Re-mesh a Meshy output — downloads the .glb, imports into Blender as a .blend file for further processing. |
Post-Processing Tools (Blender Headless)¶
| Tool | Depends On | Description |
|---|---|---|
mesh_inspect |
Blender (headless) | Open a .blend file and return polygon/vertex counts per object plus totals. |
mesh_decimate |
Blender (headless) | Reduce polygon count using the Decimate modifier (COLLAPSE type). Accepts either a target_poly_count or a ratio (0.0–1.0). |
mesh_retopo |
Blender (headless) | Retopologize mesh objects to clean quad topology. Two methods: QuadriFlow and Voxel. |
mesh_export_fbx |
Blender (headless) | Export a .blend file to FBX with Unreal Engine-friendly settings. |
Delivery Tool¶
| Tool | Depends On | Description |
|---|---|---|
grit_mesh_ingest |
boto3 (S3) | Upload processed 3D model to S3 with provenance .meta.json sidecar. |
See Grit Tooling — 3D Mesh Pipeline and Grit Tooling — 3D Model Generation for full parameter details.
Prerequisites¶
| Dependency | Install | Notes |
|---|---|---|
| Blender | System install | Must be configured via blender_path in GritMCPConfig. Runs headless (no GUI). |
| Meshy AI API key | Environment variable | Required by grit_meshy_text_to_3d, grit_meshy_image_to_3d, grit_meshy_check |
| boto3 / S3 credentials | Environment variable | Required by grit_mesh_ingest |
Generation Workflow¶
Text-to-3D¶
Generate a 3D model directly from a text description.
grit_meshy_text_to_3d(prompt="medieval blacksmith anvil, weathered iron, fantasy style")
# → Returns a task_id
Prompt tips for text-to-3D
- Be specific about the object, material, and style (e.g., "weathered iron" not just "metal").
- Include art direction cues like "fantasy style", "low-poly", or "realistic".
- Single objects produce better results than complex multi-object scenes.
Image-to-3D¶
Generate a 3D model from a reference image for more precise control over the output shape and style.
Source image tips for image-to-3D
- Use a clean image with a single object on a plain background.
- Provide multiple angles if supported, or choose the most representative view.
- Higher resolution input images yield better geometry detail.
Polling for Completion¶
3D generation is asynchronous and typically takes 60–180 seconds depending on Meshy queue depth and model complexity.
grit_meshy_check(task_id="<task_id>")
# → { "status": "processing", "progress": 45 }
# ... wait and retry ...
grit_meshy_check(task_id="<task_id>")
# → { "status": "completed", "model_url": "https://..." }
| Status | Meaning |
|---|---|
pending |
Task is queued, waiting for GPU allocation |
processing |
Generation in progress |
completed |
Model is ready for download / remesh |
failed |
Generation failed — check error message and retry with adjusted prompt |
Polling etiquette
Wait 15–20 seconds between status checks to avoid rate-limiting. Most tasks complete within 3 minutes.
Import to Blender¶
Once the Meshy task completes, remesh the output into a Blender .blend file for post-processing:
grit_meshy_remesh(task_id="<task_id>",
output_file="/tmp/anvil_raw.blend")
# → Downloads .glb from Meshy, imports into Blender, saves as .blend
Post-Processing Workflow¶
Meshy AI output is typically a high-polygon mesh (100k–400k triangles) with baked textures but poor topology — unsuitable for direct game use. The Blender post-processing tools clean up the geometry into artist-ready, UE5-compatible assets.
Step 1: Inspect¶
Check the raw mesh properties to determine the post-processing strategy.
mesh_inspect(blend_file="/tmp/anvil_raw.blend")
# → { "objects": [{"name": "anvil", "polygons": 250000, "vertices": 125000}],
# "total_polygons": 250000, "total_vertices": 125000 }
Step 2: Topology Cleanup¶
The recommended approach depends on the raw polygon count and target quality.
Retopology Decision Tree¶
What is the raw polygon count?
├── Under 50k tris
│ └── Direct QuadriFlow retopo to target
│ mesh_retopo(method="quadriflow", target_poly_count=5000)
│
├── 50k–400k tris (typical Meshy output)
│ └── Two-step approach (recommended):
│ 1. Voxel remesh → manifold geometry (~15k polys)
│ 2. QuadriFlow → clean quads at target count
│
└── Over 400k tris
└── Decimate first, then two-step retopo
mesh_decimate(target_poly_count=50000)
→ then voxel → QuadriFlow
Two-Step Retopo (Recommended for Meshy Output)¶
Raw Meshy meshes contain non-manifold geometry, near-duplicate vertices, and inconsistent normals that cause QuadriFlow to fail silently. The recommended workflow is:
# Step 1: Voxel remesh — produces manifold geometry (~15k polys)
mesh_retopo(blend_file="/tmp/anvil_raw.blend",
output_file="/tmp/anvil_voxel.blend",
method="voxel")
# Step 2: QuadriFlow — produces 100% clean quads at target poly count
mesh_retopo(blend_file="/tmp/anvil_voxel.blend",
output_file="/tmp/anvil_retopo.blend",
method="quadriflow", target_poly_count=5000)
Direct QuadriFlow on raw Meshy output
Direct QuadriFlow on raw Meshy output often fails silently due to non-manifold geometry. The tool reports FINISHED but does not modify the mesh. Always voxel remesh first for high-poly GenAI meshes.
Retopo Method Comparison¶
| Method | Speed | Output Quality | Use Case |
|---|---|---|---|
| Voxel | Fast (~10s) | Uniform quads, good for manifold cleanup | First pass on raw GenAI meshes |
| QuadriFlow | Slow (30–60s) | 100% clean quads, better edge flow | Final retopo after voxel cleanup |
QuadriFlow ceiling
Voxel divisor /80 (~15k voxel polys) is the highest resolution where QuadriFlow reliably succeeds. At /90+ (~19.5k+ polys), it tends to fail silently.
Step 3: Decimate (Optional)¶
If the retopologized mesh is still above your polygon budget, apply decimation:
mesh_decimate(blend_file="/tmp/anvil_retopo.blend",
output_file="/tmp/anvil_decimated.blend",
target_poly_count=3000)
Decimate behavior
When target_poly_count is provided, the ratio is computed automatically from the current total. The same ratio is applied to each mesh object individually, so unevenly sized meshes may not hit the exact target total.
Step 4: Export to FBX¶
Export the final .blend file to FBX with UE5-compatible settings:
mesh_export_fbx(blend_file="/tmp/anvil_retopo.blend",
output_file="/tmp/anvil_final.fbx")
# → FBX with forward: −Y, up: Z, apply modifiers, no leaf bones, no animation bake
The export settings are preconfigured for Unreal Engine 5:
| Setting | Value | Reason |
|---|---|---|
| Forward axis | −Y | UE5 coordinate system |
| Up axis | Z | UE5 coordinate system |
| Apply modifiers | Yes | Bakes Decimate/Retopo into the geometry |
| Leaf bones | Disabled | Prevents empty bones from cluttering the skeleton |
| Animation bake | Disabled | Static meshes only; animations handled separately |
S3 Ingestion¶
Upload to S3¶
Ingest the processed model to S3 with provenance metadata:
grit_mesh_ingest(file_path="/tmp/anvil_final.fbx",
group="props", element="anvil")
# → s3://<asset-bucket>/3d_models/props/anvil/
S3 Naming Convention¶
3D model assets are stored under a consistent S3 path:
| Segment | Example | Description |
|---|---|---|
{group} |
props |
Content category (props, characters, environment) |
{element} |
anvil |
Specific model name |
Each uploaded model is accompanied by a provenance sidecar (.meta.json) containing:
license— Rights / usage termsgenerator—meshy-ai-text-to-3dormeshy-ai-image-to-3dprompt— The text prompt or reference image used for generationpoly_count— Final polygon count after post-processingissue— GitLab issue reference for traceability
UE5 Integration¶
Static Mesh Import¶
- Import — Drag the exported FBX into UE5's Content Browser (
Content/Meshes/). - Materials — Assign or create materials based on the baked Meshy textures.
- Collision — Generate simple collision (box, convex, or auto-convex) for gameplay interaction.
- LODs — Configure LOD levels if the model will be viewed at varying distances.
Coordinate System¶
The FBX export uses UE5-native orientation (forward: −Y, up: Z), so models should import with correct orientation without manual rotation.
Known Limitations¶
| Limitation | Impact | Workaround |
|---|---|---|
| High raw poly count | Meshy output is typically 100k–400k tris — far too high for real-time game use. | Use the two-step retopo workflow (voxel → QuadriFlow) to reduce to game-ready poly budgets. |
| QuadriFlow silent failures | QuadriFlow reports FINISHED but doesn't modify the mesh when input is non-manifold. |
Always voxel remesh first. The tool reports warnings in the result under a "warnings" key. |
| QuadriFlow poly ceiling | At voxel /90+ (~19.5k polys), QuadriFlow consistently fails silently. |
Stay at or below voxel /80 (~15k polys) before running QuadriFlow. |
| Async generation | Meshy tasks take 60–180 seconds; no streaming preview. | Poll with grit_meshy_check at 15–20 second intervals. |
| Texture quality | Baked Meshy textures may have seams or low resolution. | Touch up textures in Substance Painter or re-project UVs in Blender. |
| Single object focus | Multi-object scenes produce inconsistent geometry between components. | Generate one object per prompt for best results. |
| No rigging | Pipeline produces static meshes only. | Rig and animate separately in Blender after retopo. |
| Decimate ratio distribution | Same ratio applied per-object; unevenly sized meshes may not hit exact target total. | Inspect per-object counts after decimation and adjust individually if needed. |
Typical Operator Workflow¶
A step-by-step example for producing a "medieval blacksmith anvil" prop:
# 1. Generate via text prompt
grit_meshy_text_to_3d(prompt="medieval blacksmith anvil, weathered iron, fantasy RPG style")
# → task_id: "task_abc123"
# 2. Poll for completion
grit_meshy_check(task_id="task_abc123")
# → { "status": "processing", "progress": 60 }
# ... wait 20 seconds ...
grit_meshy_check(task_id="task_abc123")
# → { "status": "completed" }
# 3. Import to Blender
grit_meshy_remesh(task_id="task_abc123",
output_file="/tmp/anvil_raw.blend")
# 4. Inspect raw mesh
mesh_inspect(blend_file="/tmp/anvil_raw.blend")
# → total_polygons: 250000
# 5. Voxel remesh (manifold cleanup)
mesh_retopo(blend_file="/tmp/anvil_raw.blend",
output_file="/tmp/anvil_voxel.blend",
method="voxel")
# 6. QuadriFlow retopo (clean quads)
mesh_retopo(blend_file="/tmp/anvil_voxel.blend",
output_file="/tmp/anvil_retopo.blend",
method="quadriflow", target_poly_count=5000)
# 7. Verify final mesh
mesh_inspect(blend_file="/tmp/anvil_retopo.blend")
# → total_polygons: 5012
# 8. Export to FBX
mesh_export_fbx(blend_file="/tmp/anvil_retopo.blend",
output_file="/tmp/anvil_final.fbx")
# 9. Ingest to S3
grit_mesh_ingest(file_path="/tmp/anvil_final.fbx",
group="props", element="anvil")
# → s3://<asset-bucket>/3d_models/props/anvil/
See Also¶
- Grit Tooling — 3D Mesh Pipeline — Blender headless tool parameter reference
- Grit Tooling — 3D Model Generation — Meshy AI tool parameter reference
- Asset Production Pipelines — Architecture overview and shared infrastructure
- Instrument Case Inventory — Design pitch for diegetic 3D inventory system
- Audio SFX Pipeline — Audio generation and post-processing
- Video (Wan2.2 I2V) — Image-to-video generation pipeline