Skip to content

Latest commit

 

History

History
199 lines (139 loc) · 9.4 KB

File metadata and controls

199 lines (139 loc) · 9.4 KB

Agentic Spec — 3D Model Viewer (Babylon.js, TypeScript)

Last updated: 2025-11-08

This document captures the agentic specification for a small TypeScript web project that lets a user drag-and-drop a 3D model into the browser and inspect it with PBR rendering using Babylon.js. It is intended to be a developer-facing specification: it defines goals, UX flows, data shapes, acceptance criteria, file layout, API contracts, edge cases, dev setup and verification plan.

Code Quality Principles

  • Write minimal, focused code that solves the problem directly
  • Follow language-specific conventions and style guides
  • Keep functions small and single-purpose
  • Use meaningful names for variables, functions, and classes
  • Avoid code duplication through reusable abstractions
  • Handle errors explicitly and gracefully
  • Document complex logic with inline comments
  • Remove dead code and unused dependencies

User Experience Consistency

  • Maintain consistent UI patterns across features
  • Provide clear feedback for user actions
  • Use consistent terminology and messaging
  • Ensure accessibility standards are met
  • Design for mobile and desktop experiences
  • Handle loading and error states gracefully
  • Validate user input with helpful error messages

High-level goals

  • Provide a minimal, robust in-browser 3D viewer powered by Babylon.js and TypeScript.
  • Support drag-and-drop of local 3D files (glTF/GLB primary; OBJ/MTL fallback). Optionally support other formats via loaders.
  • Render using PBR (metallic-roughness) with texture support (base color, normal, metallicRoughness, occlusion, emissive, alpha).
  • Provide user interactions: orbit/zoom/pan camera, rotate model, toggle lighting, adjust environment intensity, change exposure/tonemapping.
  • Show progress and error feedback for loading.
  • Be easy to run locally (Vite-based dev server) and easy to extend.

Non-goals (explicit)

  • This is not a full 3D editor. No persistent saving or complex scene editing.
  • No server-side model processing — all loading is client-side.

Tech stack

  • Language: TypeScript
  • Bundler/dev server: Vite
  • Renderer: babylonjs (core) + @babylonjs/loaders (GLTF/OBJ) — use the published packages under the modern names (e.g., "@babylonjs/core" and "@babylonjs/loaders")
  • UI: Plain HTML/CSS with small UI controls (no heavy UI framework required). Optionally add a tiny UI library later (e.g., vanilla-floating controls or a lightweight component lib).
  • Dev tools: ESLint, Prettier optional, basic unit tests with Vitest (optional, minimal smoke tests).

Suggested minimal dependencies (for package.json):

  • vite
  • typescript
  • @babylonjs/core
  • @babylonjs/loaders
  • @types/node (dev)
  • vitest (dev) (optional)

Pin versions at implementation time.

UX flows / behavior

  1. User opens the app; sees a centered canvas and a drag-and-drop hint area.
  2. The scene initializes with a neutral environment (HDR skybox or procedural environment) and a default camera and light.
  3. User drags a supported 3D file onto the drop area or clicks a fallback file picker.
  4. App parses the file locally using Babylon loaders. Show progress spinner and percent where available.
  5. On success: the model is shown, camera frames the model, and controls are enabled (orbit/zoom/pan). The UI shows basic model info (file name, mesh count, texture count).
  6. User can change lighting intensity/color, switch environment maps, toggle ground/grid, and adjust exposure/tonemapping.
  7. User can re-drop a new model to replace the scene.
  8. On error (unsupported file, corrupt file, missing textures), show clear error with possible remediation (e.g., "Try exporting as glTF/GLB").

Accessibility and input modalities

  • Support mouse and touch for camera controls.
  • Keyboard shortcuts: reset camera (R), toggle UI visibility (H), zoom to fit (F).

File formats & loader strategy

  • Primary supported format: glTF (.gltf) and binary glTF (.glb) via Babylon's GLTF loader.
  • Secondary: OBJ + MTL using Babylon OBJ loader. Textures must be provided alongside.
  • For other formats (FBX, STL) we will not implement first — mention as future work (FBX is proprietary/complex).

When loading, handle these cases:

  • glb: single-file, embedded textures — load directly from File blob using URL.createObjectURL.
  • gltf + external resources: when user drops a .gltf with separate files (textures), support drop of multiple files simultaneously; resolve relative URIs by mapping file names to blobs.
  • OBJ + MTL: accept both files in one drop, or if only OBJ is dropped use default material.

Security & privacy

  • All model parsing and rendering is client-side only. Do not upload dropped files off the user's machine.
  • Be careful with using URL.createObjectURL and revokeObjectURL after use.
  • Limit file size for UX safety (e.g., warn > 200 MB) but allow loading if browser supports it.

API / internal contracts

Contract for the viewer module (minimal public surface)

  • initialize(options): Promise
    • Inputs: { canvas: HTMLCanvasElement, engineOptions?: object, sceneOptions?: object }
    • Output: Promise resolves when scene & defaults are ready
  • loadFiles(files: FileList | File[]): Promise
    • Inputs: an array-like of File objects (from drag/drop or file input). Implementation maps names/URIs for glTF resources.
    • Output: { success: boolean, message?: string, metadata?: { meshes: number, materials: number, textures: number } }
  • dispose(): void
    • Clean up Babylon engine, revoke object URLs, free GPU resources.

Error modes

  • Unsupported extension: return success:false with message.
  • Parse error: return message and console.error stack.

Data shapes

  • LoadResult:
    • success: boolean
    • message?: string
    • metadata?: { meshes: number, nodes: number, materials: number, textures: number, fileName?: string }

Acceptance criteria / tests

The feature is acceptable when the following manual tests pass:

  • Load a glb (single-file) model — textures render correctly and camera frames model.
  • Load a gltf with external textures passed in the same drop — textures render and relative URIs resolved.
  • Zoom/rotate/pan work on mouse and touch.
  • Toggle environment intensity and see visible material response.
  • Drop an unsupported file extension and see an error message.

Automated tests (suggested, low effort):

  • Unit: viewer.initialize returns without throwing when given a canvas mock.
  • Unit: loadFiles rejects with unsupported file type for a .txt file.

Manual verification checklist

  • Verify PBR materials respond to environment HDR/intensity.
  • Verify embedded and external textures load and are applied.
  • Verify that object URLs are revoked when model replaced or viewer disposed.

Edge cases & failure modes

  • Very large files (100s MB) may crash or hang the browser. Mitigation: display a warning and allow cancel.
  • glTF with absolute external URIs — these must be fetched; prefer local mapping (warn user) or block cross-origin requests.
  • Missing resources in a multi-file drop — show partial load and list missing files.
  • Multiple files dropped where none is a recognized model — show error and suggest file picker.
  • Models with many materials/meshes — combine or flatten where possible for performance (future optimization).

Performance considerations

  • Use hardware-accelerated WebGL via Babylon engine.
  • Limit default texture sizes by downscaling very large images (optional enhancement).
  • Dispose unused scenes and textures when loading new model to avoid memory leaks.

UI/UX layout (files & responsibilities)

  • index.html — minimal shell with canvas and controls.
  • src/main.ts — bootstraps app, wires DOM events (drag/drop, file input) and attaches the viewer.
  • src/viewer.ts — Babylon wrapper: init engine, scene, camera, lights, environment, loader logic, public API described above.
  • src/ui/controls.ts — lightweight UI for toggles/sliders (exposure, env intensity, ground, reset).
  • src/styles.css — minimal styling.
  • public/ — sample environment maps, sample models for development.

Developer setup & run instructions (quick)

  1. Clone repo locally.
  2. npm install
  3. npm run dev (start Vite). Open http://localhost:5173

This will be turned into an explicit README.md during scaffold.

QA & verification plan

  • Create a small set of sample models (FBX / GLB / glTF with external textures) to manually test loaders.
  • Test in latest Chrome, Firefox, and Edge. Ensure touch interaction works on a mobile device.
  • Smoke-test memory with Chrome DevTools when repeatedly loading/unloading models.

Milestones for implementation (iteration plan)

  1. Project scaffold and canonical viewer that shows a built-in sample glb.
  2. Drag-and-drop + local file glTF/glb loading (single-file) implemented.
  3. Multi-file drop and URI mapping for external textures.
  4. OBJ/MTL support.
  5. UI controls for lighting/environment/exposure.
  6. Small performance & memory leak fixes, tests, README.

Future enhancements

  • Add model library and presets, implement GLB streaming for large models, add analytics (opt-in), add share/upload features (explicit consent), multi-file drag-and-drop with zip support.

Notes for maintainers

  • Keep third-party packages up to date and watch for major changes in the Babylon package split (imports under @babylonjs/core vs legacy bundles). Use ESM-compatible package imports (Vite-friendly).

Next step: scaffold the TypeScript + Vite project with minimal viewer skeleton and an example glb; wire drag-and-drop. See TODO in workspace task list.