Files
dwg-dxf-viewer-sample/CLAUDE.md
T
kimminsungandClaude Opus 4.8 a71790070d feat: multi-format 3D viewer with large-file OBJ streaming, Z-up, projection/outline UI
Three.js viewer supporting glb/gltf/obj/fbx/dae/ifc/ply via both server (SSR)
and drag&drop (CSR) paths.

- Streaming OBJ parser (src/viewer/objStream.ts) for files past the V8 max
  string length (>~1GB text) that OBJLoader can't handle; indexed geometry,
  per-vertex color from MTL Kd, float64 recenter baked in.
- In-viewer float64 recenter (objRecenter.ts) for huge CAD/survey coordinates
  (~1e8) so float32 vertex buffers keep precision (no cracked faces).
- Z-up right-handed world; Y-up formats rotated on load.
- OBJ+MTL+texture drag&drop (LoadingManager URL-modifier maps dropped images).
- OrbitControls ground-plane panning (road/rail alignment workflow).
- UI: Zoom Fit, perspective/orthographic toggle, feature-edge outline.
- DoubleSide for CAD OBJ; PLY mesh + point-cloud support.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 13:54:46 +09:00

5.9 KiB

CLAUDE.md — hmwebviewer (Three.js 3D Viewer)

Hybrid SSR+CSR web 3D model viewer. Spec: 3d_viewer_architecture_spec.pdf.

⚠️ First action on EVERY session / agent start

Read these two files before doing anything:

  1. PLAN.md — what work remains, who owns what, task breakdown.
  2. PROGRESS.md — what is done, current state, blockers, decisions log.

If either file is missing or empty, treat the project as not started and bootstrap from the spec.

What we are building

A browser 3D model viewer with two load paths:

  • Path A — Server asset (SSR + CSR): server ships a pre-rendered 360° animated WebP/WebM placeholder + HTML/CSS skeleton. Three.js loads + decodes the real Draco/KTX2 model in the background. On ready, fade WebP → canvas (opacity 0.5s).
  • Path B — Local file (Drag & Drop, CSR only): user drops a .glb/.gltf. URL.createObjectURL(file)GLTFLoader.load → decode → add to scene → URL.revokeObjectURL.

Target: perceived load < 3s, no frame drops, smooth GPU.

Locked technical decisions

These are decided. Do not relitigate without explicit user approval.

  • Three.js + GLTFLoader + DRACOLoader + KTX2Loader on ONE shared loader instance each (multiple DRACOLoader instances crash — three.js #22445).
  • Geometry: Draco. Textures: KTX2 / Basis Universal. Both compatible on same loader.
  • Decoder hosting: CDN by default; copy WASM to public/draco + public/basis if offline/CSP required. Pin decoder version to the three.js version in use.
  • Local file: createObjectURL + revoke after load. For repeat/cached loads, FileReaderArrayBufferGLTFLoader.parse().
  • Build: Vite. Draco worker spawns via BLOB URL — decoder files must be reachable at the configured path at runtime.
  • Asset pre-processing (offline): gltf-transform (Draco + KTX2) — preferred over gltf-pipeline. Meshopt is a viable Draco alternative.
  • Pre-render pipeline (offline): Blender headless CLI 360° turntable frames → assemble to animated WebP (alpha) / WebM VP9. OR Puppeteer + headless Three.js page.screenshot({type:'webp'}) per rotation step.
  • Renderer: WebGLRenderer (stable baseline). WebGPU renderer = future option, not now.

Full rationale in user memory: ~/.claude/projects/d--MYCLAUDE-PROJECT-hmwebviewer/memory/.

Architecture map (target)

src/
  viewer/
    ThreeDViewer.ts        # core class: init, loadServerAsset, loadLocalFile, executeHydration, toggleUI
    loaders.ts             # singleton GLTFLoader + DRACOLoader + KTX2Loader setup
    hydration.ts           # WebP placeholder -> canvas fade coordination
  dnd/
    dropzone.ts            # HTML5 drag&drop, file validation, createObjectURL/revoke
  ui/
    progress.ts            # load progress bar
  scenes/                  # per-model scene configs
public/
  draco/                   # decoder WASM (if bundled)
  basis/                   # KTX2 decoder WASM (if bundled)
  previews/                # pre-rendered WebP/WebM placeholders
tools/
  preprocess.mjs           # gltf-transform Draco+KTX2 pipeline
  prerender/               # Blender/Puppeteer turntable -> WebP

How to work here (rules)

  • Surgical changes. Touch only what a task requires. Match existing style.
  • Simplicity first. Minimum code that solves the task. No speculative features/config.
  • Verify before claiming done. Run the relevant check (build / typecheck / load test) and quote real output.
  • Keep PLAN.md + PROGRESS.md current. Update the task status when you start/finish a unit of work. Other agents depend on it.
  • Memory is durable; PLAN/PROGRESS are working state. Stable decisions → memory (via the memory dir). Transient task state → PLAN/PROGRESS.

Commands (see .claude/commands/)

  • /bootstrap — scaffold project from spec (run once, when PLAN says not started).
  • /next-task — read PLAN + PROGRESS, pick the next ready task, assign self.
  • /report — append current status to PROGRESS.md.
  • /optimize-asset <file> — run gltf-transform Draco+KTX2 on an asset.
  • /verify-viewer — build + load smoke test.

Agents (see .claude/agents/)

Specialized subagents for parallelizable work — viewer-core, dnd-handler, asset-pipeline, hydration, reviewer. Invoke via the Agent tool / Task delegation. Details in each agent file.

Reinforced structure — agent ↔ skill ↔ command ↔ task map

PLAN task(s) Owning agent Skill to load Command
P0 task-lead → setup threejs-viewer /bootstrap
P1-1..P1-4 viewer-core threejs-viewer /verify-viewer
P2-1,P2-2 dnd-handler threejs-viewer /verify-viewer
P3-1..P3-3 hydration threejs-viewer /verify-viewer
P4-1..P4-3 asset-pipeline threejs-viewer /optimize-asset
P5-* reviewer threejs-viewer /verify-viewer, /report
(any) task-lead task-graph /next-task, /report

Load the threejs-viewer skill whenever touching runtime viewer/dnd/asset/hydration code — it holds the locked patterns (singleton loaders, Blob URL lifecycle, hydration gating). Load task-graph when picking up or dispatching work.

Runbook — how a work session goes

  1. SessionStart hook reminds you. Read PLAN.md + PROGRESS.md.
  2. Run /next-task (or have task-lead agent do it) → get the next ready task + owning agent.
  3. Dispatch the owning agent with task ID, scope, acceptance criteria. Dispatch independent agents in ONE message (parallel).
  4. On completion: owning agent flips PLAN row → done, runs /report to append PROGRESS.md.
  5. reviewer runs after functional waves; /verify-viewer gates release.

Hooks

  • SessionStart.claude/hooks/session-start.sh prints the "read PLAN + PROGRESS" reminder.
  • progress-nudge.sh exists under .claude/hooks/ for PostToolUse nudge to update PROGRESS after runtime edits — add its PostToolUse entry to settings.json if desired (not auto-wired).