# 3D Model Pre-flight: GLB Checker & Optimizer (`meshpreflight/3d-model-preflight`) Actor

Check whether an AI-generated 3D model is print-ready or game-ready, then download an optimized version. Detects non-watertight meshes, missing tangents, over-budget geometry and textures.

- **URL**: https://apify.com/meshpreflight/3d-model-preflight.md
- **Developed by:** [dada gou](https://apify.com/meshpreflight) (community)
- **Categories:** AI, Developer tools, Other
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $20.00 / 1,000 model checkeds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## 3D Model Pre-flight: GLB Checker & Optimizer

**Check whether an AI-generated 3D model is actually usable — before it breaks your pipeline or wastes a print.**

AI generators (Meshy, Tripo, Hunyuan3D) produce models that *look* fine but are often not usable: meshes with thousands of open edges that no 3D printer can accept, missing tangent data, geometry 30x over a game budget. Opening each file in Blender to find out does not scale.

This Actor checks a `.glb` file for you and — if you want — hands back an optimized copy.

### What you get

For every model:

1. **A plain-language verdict** — `game_ready`, `needs_fixes`, or `not_usable`
2. **A list of concrete problems** — e.g. *"Mesh has 68,746 open boundary edges — not watertight. It cannot be sent to a 3D printer as-is."*
3. **An optimized `.glb`** (optional) — real-world results: **88–90% smaller**, still valid per the official glTF validator

### Input

| Field | What to put |
|---|---|
| **Model URL** | A direct link to a `.glb` file, or to a `.zip` containing up to 50 `.glb` files. Leave the default `bundled:sample` to try the Actor on the small sample model that ships with it |
| **Target platform budget** | `mobile_prop` / `pc_prop` / `character` / `hero_asset` — or `report_only` for statistics without pass/fail |
| **Also produce an optimized file** | On by default. Turn off if you only want the report |
| **Texture format** | `keep` (safest — works in any engine) or `webp` (smaller, needs engine support) |
| **Max models from a zip** | Cost guard, default 10 |

### What it detects

| Check | Why it matters |
|---|---|
| **Not watertight** | Open edges mean a 3D printer cannot build it |
| Non-manifold edges | Slicers and engines behave unpredictably |
| Degenerate triangles | Shading artifacts |
| **Missing tangents** | Normal maps render differently (or slower) in every engine |
| Missing normals / UVs | Lighting or textures will not display correctly |
| Over triangle budget | Too heavy for the target platform |
| Over texture budget | Too much VRAM |
| Uncompressed textures | File size can be cut further |
| glTF specification errors | Some engines will refuse to load the file |

### How to read the result

Every model produces one row in the run's dataset:

- `verdict` — the one-word answer
- `issues[]` — each problem, in buyer language, with a severity (`error` / `warn` / `info`)
- `geometry`, `topology`, `materials` — the raw numbers behind the verdict
- `optimized` — download key, size before/after, and the verification result

A batch summary is stored under the `OUTPUT` key.

### Notes

- Optimized files are written to this run's key-value store; download them from the run's **Output** tab.
- **Every optimized file is re-checked with the official Khronos glTF validator before delivery.** If a file fails verification, it is not delivered.
- Draco compression is lossy by a very small amount (typically under 0.02% of triangles). Use `optimize: false` if you need bit-exact geometry.

### Pricing

Pay-per-event:

| Event | When |
|---|---|
| Run start | once per run |
| Model checked | per model analyzed |
| Model optimized | per optimized file delivered |
| Size surcharge | per 10 MB of input above 10 MB |

Billing events are triggered as the work actually happens: the run start is charged immediately, each model is charged once it has been checked, and an optimized file is charged only if it was delivered.

# Actor input Schema

## `modelUrl` (type: `string`):

Direct link to a .glb file, or to a .zip archive containing up to 50 .glb files. The file must be publicly downloadable. Leave the default 'bundled:sample' to try the Actor on the small sample model that ships with it.

## `targetPreset` (type: `string`):

Which platform the model is intended for. Budgets decide the geometry and texture limits used in the report. Choose 'report_only' to get statistics without pass/fail verdicts.

## `optimize` (type: `boolean`):

When enabled, an optimized copy of each model is uploaded and a download link is returned. Real-world results: 88-90% smaller files.

## `textureFormat` (type: `string`):

Keep = safest, works in any engine (textures are only downscaled). WebP = smaller files, requires engine support for EXT_texture_webp.

## `maxModels` (type: `integer`):

Safety limit for cost control when the input is a zip archive. Upper bound is 50.

## `webhookUrl` (type: `string`):

If set, a POST request with the run summary (total / game_ready / needs_fixes / not_usable) is sent to this URL when the run finishes. Useful for CI pipelines.

## Actor input object example

```json
{
  "modelUrl": "bundled:sample",
  "targetPreset": "pc_prop",
  "optimize": true,
  "textureFormat": "keep",
  "maxModels": 10
}
```

# Actor output Schema

## `report` (type: `string`):

One row per processed model: the verdict (game_ready / needs_fixes / not_usable), the concrete problems found, and the raw geometry and topology statistics behind them.

## `optimizedModels` (type: `string`):

Every optimized model that was delivered. Each file is re-checked with the official Khronos glTF validator before delivery, and is typically 88-90% smaller than the input.

## `runSummary` (type: `string`):

Totals for the whole run, counted by verdict.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "modelUrl": "bundled:sample"
};

// Run the Actor and wait for it to finish
const run = await client.actor("meshpreflight/3d-model-preflight").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = { "modelUrl": "bundled:sample" }

# Run the Actor and wait for it to finish
run = client.actor("meshpreflight/3d-model-preflight").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "modelUrl": "bundled:sample"
}' |
apify call meshpreflight/3d-model-preflight --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,meshpreflight/3d-model-preflight"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/TIXJ7HxDzzju0d7gp/builds/38Q9g4dIq3eLyuNew/openapi.json
