A text-to-3D model returns a spec-valid GLB fast, and that is exactly the problem: "valid glTF" says nothing about whether the asset is 38 meters tall, sunk below the ground plane, or rotated 90 degrees on the wrong axis. In this walkthrough I use GPT-6 Astra Text To 3D on Voor to produce a candidate GLB, then run a small, reproducible gate before the file is allowed into a build.
The conversion route is short: open the text-to-3D route, describe the object and its subject size, generate, then validate. The current route uses GPT 6 Astra Text To 3D, shows a 3D brief, Prompt and Subject size (metres) input, and estimates 2,787 credits at the default settings with public, watermarked output.
What the generator gives you
- A textured GLB you can orbit in the viewer.
- A written prompt and a metric "subject size" hint you supply yourself.
- No guarantee about units, pivot, up-axis or triangle budget beyond what the file declares.
Everything below is about turning that output into a decision.
Step 1 — Generate one candidate and record the request
Keep the brief concrete and give the subject size in metres so you have an expected number to compare against later.
- Brief:
compact probe droid on four struts, brushed metal and off-white panels, no text - Subject size:
1.2metres
Save the returned GLB locally. Do not skip the expected-size note; it is the only fixed reference you get.
Step 2 — Read the declared bounding box
Parse the GLB's accessors and compute the world-space bounding box. A dependency-free check is enough to start:
import { readFileSync } from "node:fs";
const glb = readFileSync("droid.glb");
// glTF 2.0 binary header: magic, version, length (12 bytes),
// then chunks: length, type, data.
const jsonLen = glb.readUInt32LE(12);
const jsonType = glb.readUInt32LE(16);
if (glb.readUInt32LE(0) !== 0x46546c67) throw new Error("not a GLB");
const json = JSON.parse(glb.subarray(20, 20 + jsonLen).toString("utf8"));
console.log("meshes", json.meshes.length, "nodes", json.nodes.length);
For a real gate, run the file through the Khronos gltf-validator and read asset.minVersion, then compute min/max per axis. The declared bounds are in metres only if the exporter wrote them that way; many AI exporters write unitless numbers.
Step 3 — Compare declared size against the brief
const box = { x: [ -0.55, 0.55 ], y: [ 0, 1.15 ], z: [ -0.5, 0.6 ] }; // from the validator
const height = box.y[1] - box.y[0];
const expected = 1.2;
if (Math.abs(height - expected) / expected > 0.25) {
throw new Error(`scale off: ${height.toFixed(2)}m vs ${expected}m`);
}
A 25 percent tolerance catches the classic failures: a part exported in inches (25.4x) or in metres read as millimetres (1000x). If the check fails by a clean factor, fix the import units rather than scaling the mesh by eye.
Step 4 — Gate orientation and pivot
Two more assertions belong in the same script:
-
Up-axis: the file should stand on its lowest plane with
min.ynear zero. Ifmin.yis far negative, the pivot floats above the mesh and the asset will drop through the floor. - Facing: confirm a forward axis convention (for example, -Z forward) and assert the nose vertex sits on the expected side. Rotate once at import time if the exporter disagrees, and record the transform.
Step 5 — Run the checks in CI
Wrap steps 2 to 4 in one function and fail the build on the first violation. Log { triangles, materials, textures, bbox, upAxis, pivot } so a rejected asset has a diffable record. This is the same posture as linting: a cheap gate that stops one bad export from reaching every scene.
Review checklist
- GLB magic and version parse without a thrown error.
- Declared bounding box within 25 percent of the briefed subject size.
-
min.yat or near the ground plane, pivot at the base. - Forward axis matches the engine convention, or a documented import rotation is applied.
- Triangle count inside the target platform budget.
Limitations
GPT 6 Astra returns one candidate per pass at a fixed credit cost; it does not expose units or a transform contract, so the numbers above come from your own validation, not the model. AI meshes can also carry very thin features that survive a bounding-box check but fail a print or collision test. Treat validation as necessary, not sufficient.
Next step
Generate one asset, run the gate, and keep the version that passes. When you want a second candidate to compare, open the text-to-3D generator and re-run the same brief with one variable changed.

Top comments (0)