Skip to content

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.

grit_meshy_image_to_3d(image_path="/assets/anvil_reference.png")
# → Returns a task_id

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

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:

grit/3d_models/{group}/{element}/
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 terms
  • generatormeshy-ai-text-to-3d or meshy-ai-image-to-3d
  • prompt — The text prompt or reference image used for generation
  • poly_count — Final polygon count after post-processing
  • issue — GitLab issue reference for traceability

UE5 Integration

Static Mesh Import

  1. Import — Drag the exported FBX into UE5's Content Browser (Content/Meshes/).
  2. Materials — Assign or create materials based on the baked Meshy textures.
  3. Collision — Generate simple collision (box, convex, or auto-convex) for gameplay interaction.
  4. 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