High-performance OBJ to Cesium 3D Tiles converter with adaptive octree tiling and parallel processing.
This pipeline automates the conversion of OBJ meshes into optimized 3D Tiles compatible with Cesium for streaming in Unreal Engine. The v2.0 update features intelligent adaptive tiling, parallel processing, and native Blender-based GLB export.
- Adaptive Octree Tiling: Intelligent spatial partitioning based on geometry density
- Parallel Processing: Multi-worker texture baking and GLB conversion
- Blender-Native Export: Reliable GLB generation with embedded textures and Draco compression
- Automatic Texture Baking: Per-tile UV unwrapping and texture generation
- Mesh Optimization: Non-manifold edge removal and aggressive decimation
- Batch Processing: Process entire directories of OBJ files
Input OBJ(s)
↓
Adaptive Octree Tiling (4 LOD levels, 20k triangles/tile)
↓
Parallel Texture Baking (4 workers)
↓
Parallel Blender GLB Export (4 workers)
↓
Cesium Tileset JSON Generation
↓
Optional Gzip Compression
↓
3D Tiles Output
- Python 3.9+ — Download
- Blender 4.4+ — Download (auto-detected from PATH and common install locations)
- Node.js 18+ — Download (provides npx for 3d-tiles-tools)
git clone <repo-url>
cd mesh2Tile_repo
pip install -e .mesh2tile --version
mesh2tile --helpmesh2tile -i path/to/obj/directory -o path/to/output --gzip --longitude -75.7 --latitude 45.4 --height 77.5mesh2tile -i path/to/obj/directory -o path/to/output --gzip --continue-on-errormesh2tile -i input/ -o output/ --temp| Option | Short | Description | Default |
|---|---|---|---|
--input |
-i |
Input OBJ file or directory (required) | - |
--output |
-o |
Output directory (required) | - |
--lods |
-l |
Number of LOD levels to generate | 3 |
--gzip |
- | Enable gzip compression | False |
--temp |
- | Preserve temp folder after processing | False |
--force |
- | Force overwrite existing output directory | False |
--compress |
-c |
Texture compression level (0-3) | 0 |
--continue-on-error |
- | Continue processing on file failure | False |
--max-bake-workers |
- | Parallel baking workers | CPU/2 (max 4) |
--max-conversion-workers |
- | Parallel conversion workers | CPU/2 (max 4) |
--longitude |
- | Longitude in degrees for tileset positioning | 0.0 |
--latitude |
- | Latitude in degrees for tileset positioning | 0.0 |
--height |
- | Height in meters for tileset positioning | 0.0 |
--config |
- | Path to JSON config file | - |
--save-config |
- | Save resolved config to file and exit | - |
--blender-path |
- | Override Blender auto-detection | - |
--triangle-threshold |
- | Triangles per tile | 20000 |
--bake-samples |
- | Cycles bake samples | 128 |
--texture-max-size |
- | Max bake texture dimension | 1024 |
--version |
- | Show version and exit | - |
Save your preferred settings to a JSON file:
mesh2tile -i input/ -o output/ --triangle-threshold 50000 --bake-samples 64 --save-config my_settings.jsonReuse saved settings:
mesh2tile -i input/ -o output/ --config my_settings.jsonExample config file:
{
"triangle_threshold": 50000,
"bake_samples": 64,
"longitude": "-75.703833",
"latitude": "45.417139",
"height": "77.572"
}All settings from the config file can be overridden by CLI arguments.
Default geolocation is 0.0, 0.0, 0.0. Set coordinates for your project:
mesh2tile -i input/ -o output/ --longitude -75.7 --latitude 45.4 --height 77.5Or via config file for reuse across runs.
output_directory/
├── model_name/
│ ├── tileset.json # Cesium tileset manifest
│ ├── 0_0_0_0.glb # Root tile (LOD 0)
│ ├── 1_*.glb # LOD 1 tiles (8 tiles)
│ ├── 2_*.glb # LOD 2 tiles (64 tiles)
│ ├── 3_*.glb # LOD 3 tiles (variable)
│ └── temp/ # Intermediate files (if --temp used)
│ ├── tiles/ # OBJ tiles by LOD
│ │ ├── TileLevel_0/
│ │ ├── TileLevel_1/
│ │ ├── TileLevel_2/
│ │ └── TileLevel_3/
│ └── texture/ # Original textures
The pipeline uses the 3d-tiles-tools npm package for tileset.json generation and optional gzip compression:
# No installation needed - npx will automatically download when first used
# The pipeline calls: npx 3d-tiles-tools createTilesetJson
# And optionally: npx 3d-tiles-tools gzip- RAM: 16GB+ recommended for large meshes
- CPU: Multi-core processor (parallel processing scales with cores)
- GPU: Optional (can improve Blender baking performance)
- Baking Workers: Default is CPU cores / 2, max 4 (good for GPU baking)
- Conversion Workers: Default is CPU cores / 2, max 4 (Blender instances)
- Adjust with
--max-bake-workersand--max-conversion-workersflags
Adjust via CLI or config file:
--triangle-threshold 20000- Triangles per tileMAX_TILE_LEVEL = 3- Maximum octree depthMERGE_DISTANCE = 0.001- Non-manifold edge merge distance
- Output Size: 1.1 GB (462 GLB files)
- Processing Time: ~1.5 hours
- LOD Levels: 4 (0-3)
- Tiles Generated: 462
- Use
--gzipfor web delivery (additional 50-70% size reduction) - Adjust
TRIANGLE_THRESHOLDbased on target platform performance - Use
--continue-on-errorfor batch processing large datasets - Monitor GPU memory if using GPU baking (reduce
--max-bake-workersif needed)
Main Pipeline (mesh2tile.py)
- Entry point and orchestration
- Batch processing and error handling
- Parallel worker management
Pipeline Modules (pipeline/)
triggerBlender.py- Blender script execution wrapperblender_obj2glb.py- Blender-based GLB conversionflip_obj_axes.py- Axis transformation utilitiescreateTilesetJson.py- Cesium tileset manifest restructuringnode_processes.py- Node.js 3d-tiles-tools integration (tileset.json generation and gzip)
Blender Scripts (BlenderScripts/)
adaptiveTiling.py- Adaptive octree spatial tilingbakeTextures.py- Per-tile texture bakingobj2glb.py- Native Blender GLB export
- Entry point:
main.py→mesh2tile.py - Node.js/npm no longer required
- Old pipeline archived in
_archive/
- Tiling: Fixed grid → Adaptive octree
- GLB Export: obj23dtiles (npm) → Blender native
- Processing: Serial → Parallel (4 workers)
- Mesh Cleanup: Added non-manifold edge removal
See CHANGELOG.md for detailed changes.
"Blender not found"
- Ensure Blender is on your PATH or installed in a standard location
"Out of memory during baking"
- Reduce
--max-bake-workersto 1 or 2 - Process smaller batches
"GLB files are empty/corrupt"
- Check Blender version is 4.4+
- Verify OBJ has valid UVs and textures
"Process hangs during conversion"
- Reduce
--max-conversion-workers - Check system resources (CPU/RAM)
"testAdaptiveTiling directory still present"
- Background processes may be using it
- Safe to delete manually after processes complete
See LICENSE for details.
- Adaptive tiling algorithm: Octree-based spatial partitioning
- GLB export: Blender Python API with Draco compression
- Parallel processing: Python ProcessPoolExecutor
- Previous versions: See
_archive/for legacy implementation
For issues, feature requests, or contributions, please open an issue on the project repository.
Version: 2.1.0 Last Updated: 2025-11-03 Python: 3.8+ Blender: 4.5+