Files
dwg-dxf-viewer-sample/apps/viewer-3d/tools/README.md
T
lectom bedb357259 chore(monorepo): import hmwebviewer history at a717900
git-subtree-dir: apps/viewer-3d
git-subtree-mainline: 5e10bb1be4
git-subtree-split: a71790070d
2026-07-29 09:04:52 +09:00

3.0 KiB

tools/ — Offline asset pipeline

Offline tooling for preparing 3D assets served by the hmwebviewer. Nothing here ships to the browser at runtime; these produce the optimized assets and pre-rendered placeholders that the viewer consumes.

preprocess.mjs — Draco + KTX2 compression

Compresses a .glb/.gltf into a single self-contained .optimized.glb using gltf-transform: Draco for geometry, KTX2/Basis Universal for textures, in one pass. Output loads directly in the viewer's GLTFLoader (with DRACOLoader + KTX2Loader wired on the shared loader).

Install (once)

These dev dependencies are not in package.json yet. Run before first use:

npm install -D @gltf-transform/core @gltf-transform/functions \
                @gltf-transform/extensions @gltf-transform/cli

The CLI package provides the KTX2 encoder wiring. gltf-transform fetches the platform basis encoder automatically on first KTX2 run (network needed once).

Usage

node tools/preprocess.mjs <input.glb> [output.glb] [--draco-bits N] [--ktx2|--no-ktx2]
  • Default output: <input>.optimized.glb (e.g. model.glbmodel.optimized.glb).
  • --draco-bits N — position quantization bits, 8..16 (default 14). Lower = smaller file, lossier geometry. Tune per asset.
  • --ktx2 / --no-ktx2 — texture encoding toggle (default on).

Prints before/after byte sizes and reduction %.

Outputs

  • Compressed GLBs land in samples/ (samples/*.optimized.glb).
  • Pre-rendered WebP placeholders land in public/previews/ (*.webp) — see the pre-render section below.

If a required package is missing at runtime, the script prints the install command above and exits non-zero (no silent skip).

Sample assets

Place source .glb files under samples/ (suggested split: small / medium / large). Compress with preprocess.mjs and commit the .optimized.glb outputs. Samples are not committed yet — to be added when a sample asset is available.

Pre-render pipeline (360° animated WebP placeholder)

For Path A (server asset) the server ships a pre-rendered 360° turntable so the page shows motion instantly while the real model decodes in the background. Output: public/previews/<asset>.webp (animated, with alpha).

Status: to be implemented when a sample asset is available. Two options:

  1. Blender headless CLI (preferred). Camera parented to an empty at the model origin, Z axis 0→360° keyframed over N frames. Render frames:

    blender -b scene.blend -o //frame_### -f 1..N -F PNG
    

    Assemble to animated WebP (alpha) or WebM VP9 via ffmpeg:

    ffmpeg -framerate 24 -i frame_%03d.png -loop 0 -plays 0 out.webp
    
  2. Puppeteer + headless three.js (fallback). Spin a minimal three.js page, rotate the model, and call page.screenshot({ type: 'webp' }) per rotation step. Stitch frames into an animated WebP.

Both options need a committed sample asset first; blocked on P4-2.