---
url: /orchestration/recipes/3d.md
---

> Documentation index: https://developer.civitai.com/llms.txt — every page on this site has a markdown version at its URL + `.md`.

# 3D model generation

The `polyGen` step turns a text prompt or a reference image into a downloadable 3D model. Three engines are available, picked with the `engine` + `model` discriminator pair:

| `engine` / `model` | Best for | Notes |
|--------------------|----------|-------|
| `comfy` / `hunyuan3D` | **Image → 3D on Civitai's own workers** | Tencent Hunyuan3D (open model, v2 / v2.1 / v2-mini). `imageTo3D` plus a `shapeGen` → `texGen` split. Lowest Buzz cost and the most knobs (steps, cfg, sampler, octree). Image-only; no rigging. |
| `fal` / `meshy` | Text-to-3D, rigging & animation | Meshy, FAL-hosted, in two versions picked with `version`. **v6** (default) does `textTo3D` **and** `imageTo3D`; **v7** does `imageTo3D` and `multiImageTo3D` with an `ultraMode` fidelity tier, but has no text path. GLB + FBX + preview thumbnail, optionally a rigged, animation-ready character with walk/run clips. The only text-capable engine. |
| `fal` / `tripo` | Fast hosted image → 3D with fine texture control | Tripo v2.5, FAL-hosted. `imageTo3D` only. GLB (or FBX with `quad`) + preview image. `HD`/PBR texturing and quad topology. |

**Default choice**: for image-to-3D, lead with `engine: "comfy", model: "hunyuan3D"` — it runs on Civitai's own Comfy workers, costs the least, and exposes the most control. Reach for `model: "meshy"` when you need a text prompt, rigging, or animation (its only home), and `model: "tripo"` for fast hosted image-to-3D with quad topology or HD/PBR textures.

Every generation returns a GLB in the step's `output.model`. 3D generation runs for **minutes**, not seconds — always submit with `wait=0` and either poll `GetWorkflow` or register a webhook (see [Results & webhooks](https://developer.civitai.com/orchestration/guide/results-and-webhooks.md)).

## Prerequisites

* For any `imageTo3D` call: a publicly reachable source image URL (a Civitai CDN URL or your own hosted image)

## Meshy — text-to-3D

Meshy's text path generates geometry and textures from a prompt alone. `mode: "preview"` returns untextured geometry fast for iteration; `mode: "full"` (default) adds textures.

```http
POST https://orchestration.civitai.com/v2/consumer/workflows?wait=0
Authorization: Bearer <your-token>
Content-Type: application/json

{
  "steps": [{
    "$type": "polyGen",
    "input": {
      "engine": "fal",
      "model": "meshy",
      "operation": "textTo3D",
      "prompt": "a low-poly viking helmet with engraved runes",
      "mode": "full",
      "topology": "triangle",
      "targetPolycount": 30000
    }
  }]
}
```

## Meshy — image-to-3D

Reconstruct a model from a single reference image. Set `shouldTexture: false` for a bare mesh.

```http
POST https://orchestration.civitai.com/v2/consumer/workflows?wait=0
Authorization: Bearer <your-token>
Content-Type: application/json

{
  "steps": [{
    "$type": "polyGen",
    "input": {
      "engine": "fal",
      "model": "meshy",
      "operation": "imageTo3D",
      "imageUrl": "https://image.civitai.com/xG1nkqKTMzGDvpLrqFT7WA/dd4b4ad5-040f-4f0e-baa3-6e1ff00add65/original=true,quality=90,optimized=true/26781018.jpeg",
      "shouldTexture": true,
      "topology": "quad",
      "targetPolycount": 50000,
      "enablePbr": true
    }
  }]
}
```

### Rigging & animation (Meshy only)

Set `enableRigging: true` to get an armature-bound character plus basic walk/run clips; add `enableAnimation: true` for a full animated take. These populate the extra `output` blobs described in [Reading the result](#reading-the-result). Works best on a full-body humanoid subject in an A-pose.

```http
POST https://orchestration.civitai.com/v2/consumer/workflows?wait=0
Authorization: Bearer <your-token>
Content-Type: application/json

{
  "steps": [{
    "$type": "polyGen",
    "input": {
      "engine": "fal",
      "model": "meshy",
      "operation": "textTo3D",
      "prompt": "a friendly cartoon wizard in robes, full body, A-pose",
      "mode": "full",
      "topology": "quad",
      "targetPolycount": 60000,
      "enablePbr": true,
      "enableRigging": true
    }
  }]
}
```

## Meshy v7 — image-to-3D

Meshy v7 is a newer generation of the same model. Opt in with `version: "v7"`; omit `version` and you stay on v6. It takes everything v6's `imageTo3D` takes, plus `ultraMode` for higher-fidelity geometry and `modelType: "lowpoly"` for a cleaner low-poly mesh. It has **no text-to-3D path** — `textTo3D` stays on v6.

```http
POST https://orchestration.civitai.com/v2/consumer/workflows?wait=0
Authorization: Bearer <your-token>
Content-Type: application/json

{
  "steps": [{
    "$type": "polyGen",
    "input": {
      "engine": "fal",
      "model": "meshy",
      "version": "v7",
      "operation": "imageTo3D",
      "imageUrl": "https://image.civitai.com/xG1nkqKTMzGDvpLrqFT7WA/dd4b4ad5-040f-4f0e-baa3-6e1ff00add65/original=true,quality=90,optimized=true/26781018.jpeg",
      "ultraMode": true,
      "topology": "quad",
      "targetPolycount": 50000,
      "enablePbr": true
    }
  }]
}
```

Unlike v6, v7 prices per feature — a bare mesh is cheaper than a textured one, and `ultraMode`, rigging and animation each add to the bill. See [Cost](#cost).

## Meshy v7 — multi-image-to-3D

Give v7 up to four views of the **same** object and it reconstructs from all of them, which resolves geometry a single view can't. `ultraMode` and `modelType` aren't available on this operation; everything else matches `imageTo3D`.

```http
POST https://orchestration.civitai.com/v2/consumer/workflows?wait=0
Authorization: Bearer <your-token>
Content-Type: application/json

{
  "steps": [{
    "$type": "polyGen",
    "input": {
      "engine": "fal",
      "model": "meshy",
      "version": "v7",
      "operation": "multiImageTo3D",
      "imageUrls": [
        "https://example.com/front.png",
        "https://example.com/side.png",
        "https://example.com/back.png"
      ],
      "topology": "quad",
      "targetPolycount": 50000
    }
  }]
}
```

### Meshy parameters

Shared by both versions unless noted:

| Field | Required | Default | Notes |
|-------|----------|---------|-------|
| `version` | | `v6` | `v6` or `v7`. Omit to stay on v6. |
| `operation` | ✅ | — | v6: `textTo3D` or `imageTo3D`. v7: `imageTo3D` or `multiImageTo3D`. |
| `prompt` | `textTo3D` only | — | Max 600 chars. |
| `imageUrl` | `imageTo3D` only | — | Public source image URL. |
| `mode` | | `full` | v6 `textTo3D` only. `preview` = untextured geometry (fast), `full` = textured. |
| `enablePromptExpansion` | | `false` | v6 `textTo3D` only. Expands the prompt with an LLM before generation. |
| `shouldTexture` | | `true` | Not on v6 `textTo3D`. `false` returns a bare mesh. |
| `topology` | | `triangle` | `triangle` or `quad`. |
| `targetPolycount` | | `30000` | Range `100`–`300000`. |
| `symmetryMode` | | `auto` | `off`, `auto`, or `on`. |
| `shouldRemesh` | | `true` | Remesh to the target topology/polycount. |
| `enablePbr` | | `false` | Generate PBR (metallic/roughness) texture maps. |
| `texturePrompt` | | — | Optional text guidance for texturing (max 600 chars). |
| `enableRigging` | | `false` | Produce a rigged character + basic walk/run animations. |
| `enableAnimation` | | `false` | Produce an animated GLB/FBX. **Requires `enableRigging`.** |
| `seed` | | random | **v6 only.** Reproducibility. Assigned automatically when omitted. |

v7 adds:

| Field | Required | Default | Notes |
|-------|----------|---------|-------|
| `imageUrls` | `multiImageTo3D` only | — | 1–4 public URLs, all showing the same object from different angles. |
| `ultraMode` | | `false` | `imageTo3D` only. Higher-fidelity geometry with finer surface detail. |
| `modelType` | | `standard` | `imageTo3D` only. `lowpoly` produces cleaner low-poly geometry and makes Meshy **ignore** `topology`, `targetPolycount` and `shouldRemesh`. |
| `poseMode` | | `none` | `none`, `a-pose`, or `t-pose`. |
| `textureImageUrl` | | — | Reference image guiding the texturing pass. |
| `riggingHeightMeters` | | `1.7` | Approximate character height. Only used with `enableRigging`. |
| `animationActionId` | | `92` | Meshy animation preset, `0`–`696` (`0` is "Idle"). Only used with `enableAnimation`. See Meshy's [animation library](https://docs.meshy.ai/en/api/animation-library). |

## Tripo — image-to-3D

Tripo reconstructs a model from a single image with fine control over texturing. `texture` picks the fidelity (`no`/`standard`/`HD`); `pbr` adds PBR maps; `quad` switches the mesh to quad topology (and produces FBX instead of GLB).

```http
POST https://orchestration.civitai.com/v2/consumer/workflows?wait=0
Authorization: Bearer <your-token>
Content-Type: application/json

{
  "steps": [{
    "$type": "polyGen",
    "input": {
      "engine": "fal",
      "model": "tripo",
      "imageUrl": "https://image.civitai.com/xG1nkqKTMzGDvpLrqFT7WA/dd4b4ad5-040f-4f0e-baa3-6e1ff00add65/original=true,quality=90,optimized=true/26781018.jpeg",
      "texture": "HD",
      "pbr": true,
      "orientation": "align_image"
    }
  }]
}
```

Quad topology yields cleaner edge loops for downstream editing. Because Tripo emits FBX (not GLB) in quad mode, read the result from `output.fbxModel` rather than `output.model`:

```http
POST https://orchestration.civitai.com/v2/consumer/workflows?wait=0
Authorization: Bearer <your-token>
Content-Type: application/json

{
  "steps": [{
    "$type": "polyGen",
    "input": {
      "engine": "fal",
      "model": "tripo",
      "imageUrl": "https://image.civitai.com/xG1nkqKTMzGDvpLrqFT7WA/dd4b4ad5-040f-4f0e-baa3-6e1ff00add65/original=true,quality=90,optimized=true/26781018.jpeg",
      "texture": "standard",
      "quad": true,
      "autoSize": true
    }
  }]
}
```

### Tripo parameters

| Field | Required | Default | Notes |
|-------|----------|---------|-------|
| `imageUrl` | ✅ | — | Public source image URL. |
| `texture` | | `standard` | `no` (mesh only), `standard`, or `HD`. |
| `pbr` | | `false` | Generate PBR maps. Implies a textured result even when `texture: "no"`. |
| `faceLimit` | | adaptive | Cap the output face count. Range `1000`–`500000`. |
| `autoSize` | | `false` | Scale the model to real-world dimensions (metres). |
| `quad` | | `false` | Quad topology. **Produces an FBX mesh instead of GLB** (read `output.fbxModel`). |
| `textureAlignment` | | `original_image` | `original_image` or `geometry`. |
| `orientation` | | `default` | `align_image` auto-rotates the model to match the input image. |
| `seed` | | random | Geometry reproducibility. Assigned automatically when omitted. |
| `textureSeed` | | random | Texture reproducibility. |

## Hunyuan3D — image-to-3D

Tencent's open Hunyuan3D running on Civitai's own Comfy workers — the cheapest 3D path and the one with the most control. Image-only. The default `imageTo3D` operation generates the mesh and (when `shouldTexture` is true) textures it in one submission. Pick fidelity with `modelVersion`:

| `modelVersion` | Notes |
|----------------|-------|
| `v2` | **Default.** Fast — 5 steps, 3072 shape resolution. |
| `v2.1` | Highest quality — 30 steps, 4096 shape resolution. |
| `v2-mini` | Smallest/fastest variant, same defaults as `v2`. |

```http
POST https://orchestration.civitai.com/v2/consumer/workflows?wait=0
Authorization: Bearer <your-token>
Content-Type: application/json

{
  "steps": [{
    "$type": "polyGen",
    "input": {
      "engine": "comfy",
      "model": "hunyuan3D",
      "operation": "imageTo3D",
      "modelVersion": "v2.1",
      "imageUrl": "https://image.civitai.com/xG1nkqKTMzGDvpLrqFT7WA/dd4b4ad5-040f-4f0e-baa3-6e1ff00add65/original=true,quality=90,optimized=true/26781018.jpeg",
      "shouldTexture": true,
      "octreeResolution": 256
    }
  }]
}
```

`v2-mini` is the quickest way to preview a mesh:

### Split shapeGen / texGen (advanced)

The `imageTo3D` operation runs shape then texture internally. To cache or reuse an untextured mesh — or to re-texture one mesh several times — run the two operations as separate steps and reference the shape output from the texture step. `mesh` takes a step `$ref` to the shape step's GLB:

```http
POST https://orchestration.civitai.com/v2/consumer/workflows?wait=0
Authorization: Bearer <your-token>
Content-Type: application/json

{
  "steps": [
    {
      "$type": "polyGen",
      "name": "shape",
      "input": {
        "engine": "comfy",
        "model": "hunyuan3D",
        "operation": "shapeGen",
        "modelVersion": "v2.1",
        "imageUrl": "https://.../reference.jpg"
      }
    },
    {
      "$type": "polyGen",
      "name": "texture",
      "input": {
        "engine": "comfy",
        "model": "hunyuan3D",
        "operation": "texGen",
        "modelVersion": "v2.1",
        "imageUrl": "https://.../reference.jpg",
        "mesh": { "$ref": "shape", "path": "output.model.url" },
        "enablePbr": true
      }
    }
  ]
}
```

### Hunyuan3D parameters

| Field | Required | Default | Notes |
|-------|----------|---------|-------|
| `operation` | | `imageTo3D` | `imageTo3D` (mesh + texture), `shapeGen` (mesh only), or `texGen` (texture an existing mesh). |
| `modelVersion` | | `v2` | `v2`, `v2.1`, or `v2-mini`. |
| `imageUrl` | ✅ | — | Public source image URL. |
| `prompt` | | — | Optional guidance for `imageTo3D`/`shapeGen` (max 600 chars). |
| `mesh` | `texGen` only | — | AIR or step `$ref` to the mesh to texture. |
| `shouldTexture` | | `true` | `imageTo3D` only. `false` returns a bare mesh (and bills as shape-only). |
| `shouldRemesh` | | `false` | `imageTo3D`/`texGen`. Remesh before texturing. |
| `enablePbr` | | `true` | `imageTo3D`/`texGen`. Generate PBR maps. |
| `steps` | | 5 (`v2`/`v2-mini`), 30 (`v2.1`) | Range `1`–`150`. Scales cost linearly (see below). |
| `cfgScale` | | 5 (`v2`/`v2-mini`), 7.5 (`v2.1`) | Range `0`–`30`. |
| `octreeResolution` | | `256` | Range `16`–`512`. Higher = finer mesh; scales cost linearly. |
| `resolution` | | 3072 (`v2`/`v2-mini`), 4096 (`v2.1`) | Shape resolution. Range `1`–`8192`. |
| `sampler` | | `euler` | ComfyUI sampler (e.g. `dpmpp_2m`, `uni_pc`). |
| `scheduler` | | `normal` | `normal`, `karras`, `exponential`, `sgm_uniform`, `simple`, `ddim_uniform`, `beta`. |
| `vaeNumChunks` | | `8000` | Range `1000`–`500000`. VAE decode chunking. |
| `meshThreshold` | | `0.6` | Range `0`–`1`. Surface extraction threshold. |
| `shift` | | `1` | Timestep shift. |
| `modelAir` | | version default | Override the model checkpoint AIR (`urn:air:hy3d:repository:huggingface:...`). |
| `seed` | | random | Assigned automatically when omitted. |

## Reading the result

A succeeded `polyGen` step carries the model blobs in `output`. The required `model` is always a GLB; the other blobs appear only when the engine produced them (FBX, thumbnail, and Meshy's rigging/animation outputs).

```json
{
  "status": "succeeded",
  "steps": [{
    "name": "0",
    "$type": "polyGen",
    "status": "succeeded",
    "output": {
      "model":     { "id": "blob_abc.glb", "available": true, "url": "https://.../signed.glb", "format": "glb" },
      "fbxModel":  { "id": "blob_abc.fbx", "available": true, "url": "https://.../signed.fbx", "format": "fbx" },
      "thumbnail": { "id": "blob_abc-thumbnail.png", "available": true, "url": "https://.../signed.png" }
    }
  }]
}
```

Fields:

* **`model`** — the generated model in GLB format (always present). For Tripo `quad` runs the GLB is empty (`available: false`) and the mesh lands in `fbxModel` instead.
* **`fbxModel`** — FBX export, when the engine produced one.
* **`thumbnail`** — preview image of the model, when available.
* **`riggedModel` / `riggedFbxModel`** — Meshy rigging output (`enableRigging: true`).
* **`animatedModel` / `animatedFbxModel`** — Meshy animation output (`enableAnimation: true`).
* **`basicAnimations`** — Meshy walk/run clips (`walkingModel`, `runningModel`, …) bundled when rigging is enabled.

Hunyuan3D populates `model` only (the textured GLB) — no FBX or thumbnail.

Blob URLs expire — see [Reading results](https://developer.civitai.com/orchestration/recipes.md#reading-results).

## Runtime

3D generation is minutes-scale, so a single long-poll won't cover it — submit with `wait=0` and poll `GetWorkflow` (or use a webhook). Meshy holds its worker claim for up to 20 minutes; textured and rigged runs sit at the higher end of that. Tripo is typically faster. Hunyuan3D is compute-intensive and depends on Comfy GPU worker availability — it can queue before it runs, and `v2.1` at high `octreeResolution`/`steps` is the slowest path; `v2` and `v2-mini` are the quickest.

## Cost

Preview the exact charge with `whatif=true` ([Payments (Buzz)](https://developer.civitai.com/orchestration/guide/submitting-work.md#payments-buzz)).

**Meshy v6** is a flat rate — rigging, animation, PBR, topology, and polycount don't change the price:

| Shape | Buzz |
|-------|------|
| Any v6 `textTo3D` or `imageTo3D` run | **1040** |

**Meshy v7** prices per feature instead. Start from the base mesh and add each option you enable:

```
buzz = 1040                          base mesh
     + 520   if shouldTexture        (default on)
     + 260   if ultraMode            (imageTo3D only)
     + 260   if enableRigging
     + 156   if enableAnimation
```

| Shape | Buzz |
|-------|------|
| `shouldTexture: false` (bare mesh) | 1040 |
| textured (default) | **1560** |
| textured + `ultraMode` | 1820 |
| textured + rigged | 1820 |
| textured + `ultraMode` + rigged + animated | 2236 |

`multiImageTo3D` uses the same schedule minus `ultraMode`, and the number of input images doesn't change the price. `topology`, `targetPolycount`, `symmetryMode`, `enablePbr`, `poseMode` and `modelType` are all free.

**Tripo** is driven by texture fidelity plus the quad surcharge:

```
buzz = textureBuzz + (quad ? 65 : 0)
textureBuzz = 260 (no) | 390 (standard, or "no" with pbr) | 520 (HD)
```

| Shape | Buzz |
|-------|------|
| `texture: "standard"` (default) | **390** |
| `texture: "no"` (mesh only) | 260 |
| `texture: "HD"` | 520 |
| `+ quad` (any texture) | +65 |
| `texture: "HD"` + `quad` | 585 |

`faceLimit`, `autoSize`, `orientation`, `textureAlignment`, and both seeds don't affect Tripo's price.

**Hunyuan3D** bills a base shape charge scaled by mesh resolution and step count, plus a flat texturing charge when a texture is produced:

```
shape  = 60 × (octreeResolution / 256) × (steps / defaultSteps)
texGen = 100  (added when texturing; the whole cost for the texGen operation)
defaultSteps = 30 (v2.1), 5 (v2 / v2-mini)
```

| Shape | Buzz |
|-------|------|
| `imageTo3D`, textured, defaults | **160** |
| `imageTo3D`, `shouldTexture: false` (mesh only) | 60 |
| `shapeGen` only | 60 |
| `texGen` only | 100 |
| `imageTo3D` textured, `octreeResolution: 512` | 220 |

`modelVersion` shifts the step baseline but not the price at defaults (each version's default `steps` normalises the `steps` factor to 1). Doubling `octreeResolution` or `steps` doubles the shape charge; the `texGen` charge is flat.

## Troubleshooting

Timeouts, moderation blocks and expired blob URLs: see [Common troubleshooting](https://developer.civitai.com/orchestration/recipes.md#common-troubleshooting).

| Symptom | Likely cause | Fix |
|---------|--------------|-----|
| `400` — "Prompt is required" / "ImageUrl is required" | `operation`/`model` doesn't match the field you sent | `textTo3D` needs `prompt`; every `imageTo3D` and all Tripo calls need `imageUrl`. |
| `400` — "No derived type found for discriminator value 'textTo3D'" | `version: "v7"` with a text prompt | v7 has no text path. Drop `version` to use v6, or switch to `imageTo3D`. |
| `400` — "enableAnimation requires enableRigging" | v7 animation without an armature | Set `enableRigging: true` as well; Meshy animates the rigged character. |
| `400` — "multiImageTo3D requires between one and four source images" | `imageUrls` empty or longer than 4 | Send 1–4 views of the same object. |
| v7 `lowpoly` ignores your polycount | `modelType: "lowpoly"` overrides the remesh controls | Expected — use `modelType: "standard"` if you need `targetPolycount`/`topology` honoured. |
| `output.model.available` is `false` | Tripo `quad` run (mesh went to FBX), or the source image was rejected | Read `output.fbxModel` for quad runs; otherwise check the source image is reachable. |
| Hunyuan3D step sits `unassigned` / queued | No free Comfy worker holds the model | Wait for capacity, or fall back to hosted `model: "meshy"` / `"tripo"`. |
| Request timed out (`wait` expired) | 3D generation exceeds the long-poll window | Submit with `wait=0` and poll, or register a webhook. |

## Related

* [`InvokePolyGenStepTemplate`](https://developer.civitai.com/orchestration/reference/operations/InvokePolyGenStepTemplate.md) — the per-recipe endpoint
* [`SubmitWorkflow`](https://developer.civitai.com/orchestration/reference/operations/SubmitWorkflow.md) (generic path, for chaining) · [`GetWorkflow`](https://developer.civitai.com/orchestration/reference/operations/GetWorkflow.md)
* [`GetBlob`](https://developer.civitai.com/orchestration/reference/operations/GetBlob.md) — refetch an expired model/thumbnail URL
* [Results & webhooks](https://developer.civitai.com/orchestration/guide/results-and-webhooks.md) — handling long-running workflows
* Full parameter catalog: the `PolyGenInput` schema in the [API reference](https://developer.civitai.com/orchestration/reference.md)
* [`polyGen` OpenAPI spec](https://orchestration.civitai.com/v2/consumer/recipes/polyGen/openapi.yaml)
