Appearance
Commands
Global Options
xconvert [OPTIONS] COMMAND [ARGS]...| Option | Description |
|---|---|
--license PATH | Path to .lic license file (overrides XVIEWR_LICENSE_KEY and the default location) |
--version | Print version and exit (e.g. xconvert, version 4.0.6) |
-v, --verbose | Increase log verbosity (-v = INFO, -vv = DEBUG). Logs go to stderr; JSON protocol lines go to stdout |
--help | Show help and exit |
The top-level command group exposes five subcommands: convert, decimate, chunk, info, batch.
xconvert convert
Convert a 3D file to GLB (or FBX / OBJ / STL).
xconvert convert [OPTIONS] INPUT_FILEArguments
| Argument | Required | Description |
|---|---|---|
INPUT_FILE | Yes | Path to the source 3D file. Must exist and be a file. |
Options
| Option | Type | Default | Description |
|---|---|---|---|
-o, --out | path | <input>.<format> next to input | Output file path |
-f, --format | glb|fbx|obj|stl | glb | Output format |
--file-type | cad|mesh|pointcloud | auto-detected | Override file-type detection |
--optimize / --no-optimize | flag | disabled | Run a mesh decimation pass after conversion |
--target-ratio | float 0.01–1.0 | — | Face retention ratio (used with --optimize) |
--rms | float 0.01–0.20 | 0.04 | RMS error budget as fraction of bounding-box diagonal — lower = higher quality |
--hausdorff | float (µm) | — | Hausdorff tolerance in microns; enables geometric-error-guided decimation |
--lods | int 1–3 | — | Number of LOD levels to generate alongside the main output |
--chunk / --no-chunk | flag | disabled | Spatially chunk output for browser streaming |
--chunk-size | float | auto | World-space chunk cube size override |
-w, --workers | int | 4 | Parallel worker threads (capped at 2 × CPU cores) |
--work-dir | path | system temp | Temp directory for intermediates |
--json | flag | disabled | Emit newline-delimited JSON progress on stdout |
--help | — | — | Show help and exit |
When --chunk is used with --format glb, one of --rms or --hausdorff is required (error code MISSING_QUALITY_TARGET).
Examples
bash
# Basic conversion
xconvert convert assembly.step --out assembly.glb
# With 3 LODs and spatial chunking (for XViewr viewer)
xconvert convert assembly.step --out assembly.glb --lods 3 --chunk --rms 0.04
# Aggressive decimation
xconvert convert large.glb --optimize --target-ratio 0.2
# Hausdorff-bounded decimation (preserves geometry within 50 µm)
xconvert convert precise.step --hausdorff 50
# CI with JSON progress stream
xconvert convert model.step --json 2>/dev/nullxconvert decimate
Adaptively decimate a GLB into a two-tier LOD set (LOD0 exact / LOD1 navigation).
xconvert decimate [OPTIONS] INPUT_GLBArguments
| Argument | Required | Description |
|---|---|---|
INPUT_GLB | Yes | Path to source GLB file (10 GB max) |
Options
| Option | Type | Default | Description |
|---|---|---|---|
-o, --out-dir | path | <input>_decimated/ | Output directory |
--rms | float | — | RMS quality budget as fraction of bbox diagonal. Pass 0 to keep LOD0 as the exact original mesh. Required unless --hausdorff is set. |
--hausdorff | float (µm) | — | Hausdorff tolerance in µm; switches to HDB (Hausdorff-Distance-Bounded) mode |
--initial-factor | float | — | Starting face-count fraction for the binary search (expert) |
-w, --workers | int | 4 | Parallel worker processes |
--json | flag | disabled | Emit newline-delimited JSON progress |
--help | — | — | Show help and exit |
One of --rms or --hausdorff is required.
Output
out-dir/
├── lod0.glb # Exact original by default (or HDB-bounded when --hausdorff is set)
├── lod1.glb # Navigation-quality binary-search decimation from the original
├── <part>_lod0.obj # Per-primitive OBJ intermediates
└── <part>_lod1.obj # (reused by `xconvert chunk --obj-dir`)Only lod0 and lod1 are produced by decimate — lower LODs are generated by the chunker or by convert --lods. LOD1 defaults per class (from lod_config.py):
| Class | Initial factor | Min factor | RMS ceiling |
|---|---|---|---|
| FLAT | 0.08 | 0.03 | 0.06 |
| CURVED (default) | 0.18 | 0.08 | 0.06 |
| DETAILED | 0.22 | 0.10 | 0.06 |
LOD1 is capped at 500_000 faces per primitive and skips primitives with fewer than 4 faces.
Examples
bash
xconvert decimate model.glb --out-dir model_lods/ --rms 0.04
# Tighter quality (fewer faces removed)
xconvert decimate model.glb --rms 0.01 --out-dir model_lods/
# Hausdorff-bounded (preserves geometry within 100 µm)
xconvert decimate model.glb --hausdorff 100 --out-dir model_lods/xconvert chunk
Spatially partition a GLB into browser-streamable Draco chunks with LOD.
xconvert chunk [OPTIONS] INPUT_GLBArguments
| Argument | Required | Description |
|---|---|---|
INPUT_GLB | Yes | Path to source GLB file (10 GB max) |
Options
| Option | Type | Default | Description |
|---|---|---|---|
-o, --out-dir | path | <input>_chunks/ | Output directory for chunks |
--obj-dir | path | — | Pre-built OBJ decimation directory from xconvert decimate; skips re-decimation |
--rms | float | — | RMS quality target for auto-decimation. Required when --obj-dir is not supplied. Pass 0 for exact original LOD0. |
--min-cubes | int | 8 | Minimum number of spatial chunks |
--max-cubes | int | 512 | Maximum number of spatial chunks |
--target-prims | int | 80 | Target primitives per chunk |
--max-verts | int | 120000 | Max vertices per chunk |
-w, --workers | int | 4 | Worker threads |
--json | flag | disabled | Emit newline-delimited JSON progress |
--help | — | — | Show help and exit |
One of --rms or --obj-dir is required.
Output
out-dir/
├── manifest.json
├── lod0/
│ ├── chunk_0000_lod0.glb
│ ├── chunk_0001_lod0.glb
│ └── ...
└── lod1/
├── chunk_0000_lod1.glb
└── ...Chunk GLBs are Draco-compressed (KHR_draco_mesh_compression): LOD0 at compression level 7 / 14-bit position quantization, LOD1 at level 10 / 11-bit.
Examples
bash
# Chunk an existing GLB (runs decimation automatically)
xconvert chunk model.glb --out-dir model_chunks/ --rms 0.04
# Reuse decimation output from a previous decimate run (faster)
xconvert chunk model.glb --obj-dir model_lods/ --out-dir model_chunks/xconvert info
Inspect a 3D file or verify tool availability.
xconvert info [OPTIONS] [INPUT_FILE]Arguments
| Argument | Required | Description |
|---|---|---|
INPUT_FILE | No | Path to 3D file to inspect (omit when using --check-binaries) |
Options
| Option | Description |
|---|---|
--json | Output inspection results as JSON |
--check-binaries | Report status of bundled native binaries and Python libraries, then exit (no input file required) |
--help | Show help and exit |
Examples
bash
# Check native binaries + Python libs are present
xconvert info --check-binaries
# Inspect a file
xconvert info model.glb
xconvert info model.step --json--check-binaries output
Human-readable form:
── Native Binaries ──────────────────────────────────────
✓ StepParserOCCT <path or "not found">
✓ FBX2glTF <path or "not found">
── Python Libraries ─────────────────────────────────────
✓ trimesh v<version>
✓ DracoPyJSON form:
json
{
"binaries": {
"StepParserOCCT": { "found": true, "path": "..." },
"FBX2glTF": { "found": true, "path": "..." }
},
"python_libs": {
"trimesh": { "available": true, "version": "4.x.x" },
"DracoPy": { "available": true }
}
}Native binary resolution order:
- Env var override:
XCONVERT_XCAD_BIN,XCONVERT_FBX2GLTF_BIN - System
PATH - Bundled
bin/<platform>/next to the installed package - Docker fallback:
/usr/local/bin/StepParserOCCT,/usr/local/bin/FBX2glTF
File-inspection fields
Regular mode prints File, Type, Size, Vertices, Faces, Meshes, glTF, Prims, Draco, BBox, Watertight. JSON mode emits the equivalent flat object with keys file, path, size_bytes, size_mb, file_type, extension, and — for meshes — vertices, faces, bounding_box, is_watertight, and — for GLB — gltf_version, mesh_primitives, nodes, materials, extensions, draco_compressed.
xconvert batch
Bulk-convert a folder of mesh files (STL/OBJ/PLY by default) into paired dual-LOD GLBs. For each input part it produces <part>_lod0.glb and <part>_lod1.glb, plus a top-level manifest.json.
xconvert batch [OPTIONS] FOLDERLOD0 is either the exact original geometry (default) or an HDB-accurate decimation when --lod0-hausdorff is supplied. LOD1 is always produced via single-pass QEM decimation with a class-scaled ratio (FLAT × 0.70, CURVED × 1.00, DETAILED × 1.40). Files are processed with a size-interleaved thread pool so all workers get a mix of small and large parts.
Arguments
| Argument | Required | Description |
|---|---|---|
FOLDER | Yes | Directory containing mesh files |
Options
| Option | Type | Default | Description |
|---|---|---|---|
--lod0-hausdorff | float (µm) | — | Hausdorff tolerance for LOD0 HDB decimation. Omit to keep LOD0 as the exact original. Recommended 50–200 µm for mechanical parts. |
--lod1-ratio | float 0.0–1.0 | 0.55 | Base face fraction for LOD1 QEM decimation. Class-scaled per mesh. |
-o, --output | path | <folder>_xconvert/ | Output root directory |
--model-units | m|mm|cm|inch | m | Spatial unit of input meshes — used to convert --lod0-hausdorff µm to model units |
-w, --workers | int | 4 | Parallel threads (capped at 2 × CPU cores) |
--formats | string | stl,obj,ply | Comma-separated extensions to include |
--recursive / --no-recursive | flag | disabled | Scan subdirectories recursively |
--skip-existing | flag | disabled | Skip a part if its output GLBs already exist |
--crease-angle | float 1–90° | 30.0 | Dihedral angle for hard-edge normal splitting (crease-normals mode) |
--smooth-normals | flag | disabled | Plain smooth vertex normals + Draco. Smallest files, softer edges. |
--split-normals | flag | disabled | Full vertex splitting at crease boundaries. Non-indexed GLB (no Draco), 8–10× larger. Overrides --smooth-normals. |
--lod0-only | flag | disabled | Only generate LOD0 (skip LOD1) |
--lod1-only | flag | disabled | Only generate LOD1 (skip LOD0). Mutually exclusive with --lod0-only. |
--json | flag | disabled | NDJSON progress on stdout — line types: progress, part_done, error, result |
--help | — | — | Show help and exit |
Output
<folder>_xconvert/
├── <part1>_lod0.glb
├── <part1>_lod1.glb
├── <part2>_lod0.glb
├── <part2>_lod1.glb
├── ...
└── manifest.jsonExamples
bash
# Basic batch: LOD0 exact, LOD1 at ~55% (class-scaled)
xconvert batch ./parts/ --model-units mm
# HDB LOD0 + tight LOD1
xconvert batch ./parts/ --lod0-hausdorff 100 --lod1-ratio 0.25 --model-units mm
# Recurse, use 8 workers, JSON progress
xconvert batch ./parts/ --lod1-ratio 0.20 --recursive --workers 8 --json
# Skip parts that were processed before
xconvert batch ./parts/ --lod0-hausdorff 200 --skip-existing --formats stl,objJSON Progress Protocol
All commands support --json to emit newline-delimited JSON events on stdout. Logs always go to stderr, keeping the JSON stream clean.
bash
xconvert convert model.step --jsonCommon event types:
type | Fields | Description |
|---|---|---|
start | file, format | Conversion started |
progress | stage, progress (0–100), message | Stage update |
result | files (list of output paths) | Completed successfully |
error | message, code | Failed |
xconvert batch --json additionally emits part_done events for each completed input file.
Example stream:
json
{"type":"start","file":"model.step","format":"glb"}
{"type":"progress","stage":"convert","progress":15,"message":"Parsing STEP geometry"}
{"type":"progress","stage":"convert","progress":80,"message":"Exporting GLB"}
{"type":"result","files":["model.glb","model.edges.json"]}Environment Variables
| Variable | Description |
|---|---|
XVIEWR_LICENSE_KEY | XVR1 token string or path to a .lic file |
XVIEWR_PROD_PUBLIC_KEY_PEM | Override the bundled ES256 public key (CI/Docker) |
XCONVERT_XCAD_BIN | Override path to StepParserOCCT binary |
XCONVERT_FBX2GLTF_BIN | Override path to FBX2glTF binary |
DISPLAY | X display for headless rendering on Linux (set to :99 in Docker) |