Skip to content

Commands ​

Global Options ​

xconvert [OPTIONS] COMMAND [ARGS]...
OptionDescription
--license PATHPath to .lic license file (overrides XVIEWR_LICENSE_KEY and the default location)
--versionPrint version and exit (e.g. xconvert, version 4.0.6)
-v, --verboseIncrease log verbosity (-v = INFO, -vv = DEBUG). Logs go to stderr; JSON protocol lines go to stdout
--helpShow 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_FILE

Arguments ​

ArgumentRequiredDescription
INPUT_FILEYesPath to the source 3D file. Must exist and be a file.

Options ​

OptionTypeDefaultDescription
-o, --outpath<input>.<format> next to inputOutput file path
-f, --formatglb|fbx|obj|stlglbOutput format
--file-typecad|mesh|pointcloudauto-detectedOverride file-type detection
--optimize / --no-optimizeflagdisabledRun a mesh decimation pass after conversion
--target-ratiofloat 0.01–1.0—Face retention ratio (used with --optimize)
--rmsfloat 0.01–0.200.04RMS error budget as fraction of bounding-box diagonal — lower = higher quality
--hausdorfffloat (µm)—Hausdorff tolerance in microns; enables geometric-error-guided decimation
--lodsint 1–3—Number of LOD levels to generate alongside the main output
--chunk / --no-chunkflagdisabledSpatially chunk output for browser streaming
--chunk-sizefloatautoWorld-space chunk cube size override
-w, --workersint4Parallel worker threads (capped at 2 × CPU cores)
--work-dirpathsystem tempTemp directory for intermediates
--jsonflagdisabledEmit 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/null

xconvert decimate ​

Adaptively decimate a GLB into a two-tier LOD set (LOD0 exact / LOD1 navigation).

xconvert decimate [OPTIONS] INPUT_GLB

Arguments ​

ArgumentRequiredDescription
INPUT_GLBYesPath to source GLB file (10 GB max)

Options ​

OptionTypeDefaultDescription
-o, --out-dirpath<input>_decimated/Output directory
--rmsfloat—RMS quality budget as fraction of bbox diagonal. Pass 0 to keep LOD0 as the exact original mesh. Required unless --hausdorff is set.
--hausdorfffloat (µm)—Hausdorff tolerance in µm; switches to HDB (Hausdorff-Distance-Bounded) mode
--initial-factorfloat—Starting face-count fraction for the binary search (expert)
-w, --workersint4Parallel worker processes
--jsonflagdisabledEmit 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):

ClassInitial factorMin factorRMS ceiling
FLAT0.080.030.06
CURVED (default)0.180.080.06
DETAILED0.220.100.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_GLB

Arguments ​

ArgumentRequiredDescription
INPUT_GLBYesPath to source GLB file (10 GB max)

Options ​

OptionTypeDefaultDescription
-o, --out-dirpath<input>_chunks/Output directory for chunks
--obj-dirpath—Pre-built OBJ decimation directory from xconvert decimate; skips re-decimation
--rmsfloat—RMS quality target for auto-decimation. Required when --obj-dir is not supplied. Pass 0 for exact original LOD0.
--min-cubesint8Minimum number of spatial chunks
--max-cubesint512Maximum number of spatial chunks
--target-primsint80Target primitives per chunk
--max-vertsint120000Max vertices per chunk
-w, --workersint4Worker threads
--jsonflagdisabledEmit 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 ​

ArgumentRequiredDescription
INPUT_FILENoPath to 3D file to inspect (omit when using --check-binaries)

Options ​

OptionDescription
--jsonOutput inspection results as JSON
--check-binariesReport status of bundled native binaries and Python libraries, then exit (no input file required)
--helpShow 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>
  ✓ DracoPy

JSON 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:

  1. Env var override: XCONVERT_XCAD_BIN, XCONVERT_FBX2GLTF_BIN
  2. System PATH
  3. Bundled bin/<platform>/ next to the installed package
  4. 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] FOLDER

LOD0 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 ​

ArgumentRequiredDescription
FOLDERYesDirectory containing mesh files

Options ​

OptionTypeDefaultDescription
--lod0-hausdorfffloat (µm)—Hausdorff tolerance for LOD0 HDB decimation. Omit to keep LOD0 as the exact original. Recommended 50–200 µm for mechanical parts.
--lod1-ratiofloat 0.0–1.00.55Base face fraction for LOD1 QEM decimation. Class-scaled per mesh.
-o, --outputpath<folder>_xconvert/Output root directory
--model-unitsm|mm|cm|inchmSpatial unit of input meshes — used to convert --lod0-hausdorff µm to model units
-w, --workersint4Parallel threads (capped at 2 × CPU cores)
--formatsstringstl,obj,plyComma-separated extensions to include
--recursive / --no-recursiveflagdisabledScan subdirectories recursively
--skip-existingflagdisabledSkip a part if its output GLBs already exist
--crease-anglefloat 1–90°30.0Dihedral angle for hard-edge normal splitting (crease-normals mode)
--smooth-normalsflagdisabledPlain smooth vertex normals + Draco. Smallest files, softer edges.
--split-normalsflagdisabledFull vertex splitting at crease boundaries. Non-indexed GLB (no Draco), 8–10× larger. Overrides --smooth-normals.
--lod0-onlyflagdisabledOnly generate LOD0 (skip LOD1)
--lod1-onlyflagdisabledOnly generate LOD1 (skip LOD0). Mutually exclusive with --lod0-only.
--jsonflagdisabledNDJSON 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.json

Examples ​

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,obj

JSON 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 --json

Common event types:

typeFieldsDescription
startfile, formatConversion started
progressstage, progress (0–100), messageStage update
resultfiles (list of output paths)Completed successfully
errormessage, codeFailed

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 ​

VariableDescription
XVIEWR_LICENSE_KEYXVR1 token string or path to a .lic file
XVIEWR_PROD_PUBLIC_KEY_PEMOverride the bundled ES256 public key (CI/Docker)
XCONVERT_XCAD_BINOverride path to StepParserOCCT binary
XCONVERT_FBX2GLTF_BINOverride path to FBX2glTF binary
DISPLAYX display for headless rendering on Linux (set to :99 in Docker)

XViewr SDK and xConvert CLI documentation.