You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

5.1 KiB

Blockbench UV Packer

A Blockbench plugin that auto-packs per-face UV models with ML-assisted share-merge suggestions, mirror detection, multi-variant texture support, and pow2 canvas cropping. One button, end-to-end.

Originally built for the Decocraft project's bbmodel corpus (~600 models). The ML model in ml/share_model.json is trained on that corpus; you can retrain on your own corpus with the scripts in ml/.

What it does

When you click Tools → Pack UVs (Decocraft), the plugin:

  1. Collects all per-face-UV cubes in the project (skips box-UV cubes; works in mixed-mode projects)
  2. Heuristic share-merge — faces with the same UV rect (modulo flip) collapse to one packed slot. Median 80% rect dedupe across the training corpus.
  3. ML share-merge suggestions (if share_model.json is loaded) — surfaces candidate merges the heuristic missed. A pixel-similarity gate filters out false positives. Each suggestion shows a thumbnail preview before you accept.
  4. Mirror-orientation detection — for cross-rect merges, the planner samples each member's pixels in 4 orientations and picks the one that minimizes RGBA diff against the canonical, so mirror-painted symmetric regions stay mirror-correct after merging.
  5. Skyline pack — biggest-first, top-to-bottom, left-to-right. Outliner-group ordering clusters same-group faces. Auto-expands the working canvas if rects don't fit.
  6. Variant texture rearrangement — alternate skin textures (any texture in the project with no faces pointing to it) get the same pixel rearrangement as the driver texture, so swapping skins still lines up.
  7. Pow2 crop — final texture canvas is shrunk to next-power-of-2 of the actual packed bbox.
  8. Single Undo entry covers everything.

Install

  1. In Blockbench: File → Plugins → Load Plugin from File
  2. Pick decocraft_uv_packer.js
  3. (One-time) Tools → Load Share Model JSON → pick both ml/share_model.json and ml/inference_test_cases.json (multi-select). The model is cached to localStorage after first load. The plugin self-tests the JS LightGBM evaluator against the test cases on every load — if it doesn't match LightGBM exactly, it refuses to use the model.

Workflow

  • Open a project that uses per-face UVs
  • Tools → Pack UVs (Decocraft)
  • If the ML model finds candidates, a dialog opens with thumbnails. Uncheck any pair where the previews disagree visually. Click Accept & Pack (or Pack without merging to skip ML suggestions).
  • The plugin packs, crops to pow2, and rearranges variants. Toast reports Packed N faces into M slots · canvas A×B → C×D.

Retraining the ML model on your own corpus

If you have your own bbmodel collection and want a model trained on its conventions:

# 1. Inspect the corpus statistics (optional)
node analyze_uvs.mjs path/to/your/bbmodel/folder

# 2. Extract face-pair training data (~250k labeled pairs from ~600 models)
node ml/extract_pairs.mjs path/to/your/bbmodel/folder
# → produces ml/pairs.csv (~30 MB on a 600-model corpus)

# 3. Train (Python: pip install lightgbm pandas scikit-learn)
cd ml
python train_share_classifier.py
# → updates share_model.json, eval_report.txt, inference_test_cases.json

# 4. In Blockbench: Tools → Load Share Model JSON → pick the new files

The training script splits by model (not by pair) for held-out evaluation — so the precision/recall numbers in eval_report.txt reflect actual generalization to unseen models, not just unseen pairs from already-seen models. The bundled share_model.json was trained on the Decocraft corpus and reaches AUC 0.985 / precision 0.96 @ recall 0.88 on 123 held-out models.

File layout

blockbench-uv-packer/
├── decocraft_uv_packer.js        Blockbench plugin (single file)
├── analyze_uvs.mjs               Corpus stats (per-model density, group overlap, share fraction…)
└── ml/
    ├── extract_pairs.mjs         Build pairs.csv from a bbmodel directory
    ├── train_share_classifier.py LightGBM trainer + eval + JSON export
    ├── validate_js_eval.mjs      Verifies the JS evaluator matches LightGBM bit-for-bit
    ├── share_model.json          Trained model (350 trees, ~2.5 MB)
    ├── inference_test_cases.json 50 self-test cases for the plugin
    └── eval_report.txt           Precision/recall sweep + feature importance from last train

Limitations / non-goals

  • Per-face UV only. Cubes set to box-UV mode are skipped (counted in the success toast).
  • Same-dimension share-merges only. The merger collapses faces whose source rects have the same dims (with optional 90°-mirror); it doesn't rotate-to-fit different aspect ratios.
  • Reorient-cubes feature was attempted and dropped. Auto-rotating cubes for tighter packing fights against either Blockbench's cube.roll() (which rotates visually, breaking model assemblies) or requires deriving the full per-(perm × slot) D4-symmetry texture transform (which kept hitting subtle bugs across iterations). If you want a cube reoriented, use Blockbench's built-in Transform → Rotate tools manually before running Pack UVs.

License

TBD — add the license your project uses.