Skip to content

1.0.0-alpha.0

Latest

Choose a tag to compare

@vim-sroberge vim-sroberge released this 10 Mar 19:05
· 81 commits to sroberge/1_0 since this release
ffb082f

This branch is a major architectural overhaul preparing vim-web for the 1.0 release. It covers five broad areas: a new public API surface, a complete outline rendering rewrite, a GPU picking system, geometry loading performance, and a thorough dead code purge.


Public API & Exports

  • ViewerApi abstraction: Both WebGL and Ultra viewers now expose a unified ViewerApi handle (WebglViewerApi / UltraViewerApi) through VIM.React.Webgl.createViewer() and VIM.React.Ultra.createViewer(). Direct class access is no longer needed for any common use case.
  • Interface-driven: Core types are now backed by I-prefixed interfaces (IVim, ICamera, ISelectable, IMarker, IMaterials, etc.). Concrete classes are @internal.
  • Tighter barrel files: Internal modules are no longer leaked through re-exports. The public surface is intentionally narrow.
  • Unique class names: Renamed internal classes for cleaner API bundles and better TypeScript declaration output.
  • viewer.core.settings removed: Settings are consumed at construction time only — exposing them as a field was misleading. Removed from IWebglViewer.
  • Material API cleanup: IMaterials now only exposes user-facing properties (ghostOpacity, ghostColor, outlineOpacity, outlineThickness, outlineColor, clippingPlanes). Internal system materials are hidden behind a system getter.
  • Element3D interface: IElement3D exposes only BIM-facing properties; mesh internals are hidden.
  • Input API: Inputs organized under viewer.core.inputs with typed PointerMode enum, configurable key handlers, and clean mouse/touch callbacks. Removed spacebar bindings.
  • Camera API: Fluent snap() / lerp(duration) API for instant vs animated camera moves. Unified frame(), orbit(), orbitTowards(), zoomTo(). Removed lookAt parameter. Rotation axes clarified (x = horizontal/yaw, y = vertical/pitch).
  • Framing renamed: viewer.react.cameraviewer.framing for clarity.
  • Signal interfaces: onXxx event properties typed as read-only signal interfaces, not mutable dispatchers.
  • Ultra API tightened: Ultra viewer API aligned with WebGL — matching fields (container, isolation, sectionBox, etc.), control bar customization via hook param, no leaked RPC internals.

GPU Picking (WebGL)

Replaced CPU raycasting as the primary picking method with a GPU-based approach:

  • Float32 render target stores packed element ID (vimIndex << 24 | elementIndex), depth, and surface normals per fragment.
  • packPickingId() / unpackPickingId() utilities pre-pack IDs at mesh build time — zero overhead per frame.
  • Markers support GPU picking (packedId attribute with MARKER_VIM_INDEX sentinel).
  • GpuPicker reads a 1×1 region on click, resolves vim + element in one readback.
  • CPU raycaster (raycaster.ts) retained as fallback.

Outline Rendering Rewrite

The outline effect was completely rewritten from depth-based to mask-based silhouette detection:

Pipeline: Scene (MSAA) → Selection Mask → Outline Edge Detect → Merge → Screen

  • Mask-based: Selected objects render with a flat white maskMaterial to a dedicated render target. Edge detection runs on the mask, not the depth buffer — eliminates depth precision artifacts at long range.
  • scene.background fix: Background color was leaking into the mask buffer and breaking edge detection. Background is now nulled during the outline composer render and restored after.
  • Configurable thickness: New thickness uniform (range 1–5) controls how many Chebyshev ring levels are sampled per fragment. Higher values = thicker outlines at a proportional sampling cost.
  • Full grid (Chebyshev ring) sampling: Replaced 8-point star sampling with a full NxN grid ring. Eliminates diagonal artifacts from the star pattern.
  • Opacity and color: outlineOpacity (0–1) and outlineColor exposed on IMaterials. Both live on the merge pass for clean separation.
  • Dead properties removed: camera, depthBuffer, color, precision and associated uniforms removed from OutlineMaterial. OutlinePass no longer receives or wires a camera.

Material System Cleanup

  • StandardMaterial removed: _opaque / _transparent StandardMaterial fields deleted from Materials. VIM meshes have always used ModelMaterial (custom GLSL3 shader) — StandardMaterial was never in the rendering path.
  • Dead settings removed:
    • skybox, skylight, sunlights — defined, parsed, never consumed
    • useFastMaterials, materials.standard.color — toggle with no effect
    • materials.section.strokeWidth/Falloff/Color — only applied to StandardMaterial shader, which was unused
  • modelColor, sectionStroke* removed from IMaterials — dead wiring to removed materials.
  • MaterialSettings now contains only ghost and outline.
  • MaterialSet: New value type { opaque, transparent, hidden } for per-mesh material assignment. applyMaterial() helper is the single place that calls MaterialSet.get().

Geometry Loading & Performance

  • Color palette texture: Per-element colors stored in a shared 128×128 DataTexture (25³ = 15,625 quantized colors). ModelMaterial reads colors via texelFetch — no per-vertex color upload on color changes.
  • texelFetch / WebGL2: Replaced texture2D with texelFetch in shaders for direct texel access.
  • G3dSubset and offsets: Introduced G3dSubset as a filtered view of G3d instances. G3dMeshOffsets pre-computes vertex/index counts per mesh for buffer allocation.
  • InsertableGeometry chunking: Merged mesh geometry split at 16M indices to stay within buffer limits.
  • InstancedMeshFactory: Instanced meshes (>5 instances) built with per-instance packedId and ignore attributes pre-packed at build time.
  • Faster element mapping, bounding boxes, and array lookups: Hot paths replaced with typed array maps.
  • Removed vimx: Legacy vimx loading code removed.
  • No empty meshes: Meshes with zero instances are no longer created.

Camera & Controls

  • Orbit target on select: Orbit target snaps to selected element center.
  • Zoom resets orbit target: Scroll-to-zoom updates the orbit target to the cursor hit point.
  • Floating target fix: Orbit target no longer drifts after camera reset.
  • Touch: Pinch and pan gestures both fire correctly. Faster scroll.
  • lockMovement / lockRotation: Per-axis movement and rotation locks on ViewerSettings.camera.
  • Delta time: Fixed camera animation delta time calculation.

Ultra Viewer Updates

  • Color overrides: Ultra viewer supports element.color = new RGBA32(...) overrides, aligned with WebGL API.
  • nodeStatestate: Renamed for clarity. element.state = VisibilityState.GHOSTED (enum: VISIBLE, HIDDEN, GHOSTED, HIGHLIGHTED).
  • Remove overrides: Ultra viewer supports removing overrides, matching WebGL.
  • Error messages: Improved error/status display. Errors not minimized by default.
  • Ultra 6.0.0 RPC: Updated RPC client to match Ultra 6 protocol.

Gizmos

  • Marker GPU picking: Markers register packedId attribute for GPU picker hit detection.
  • Orbit gizmo: Camera gizmo rebuilt to match Ultra's visual style. Uses sphere coordinates.
  • Section box / axes cleanup: Gizmo classes tightened, internals hidden behind IGizmo* interfaces.

Developer Experience

  • CLAUDE.md: Comprehensive architecture documentation. Covers loading pipeline, rendering pipeline, GPU picker, mesh type hierarchy, React patterns, and camera API.
  • INPUT.md: Dedicated input system documentation.
  • @internal tags: System-only classes and methods marked throughout.
  • TypeDoc comments: Cleaned up and expanded across public API.

Breaking Changes

  • viewer.core.settings removed from IWebglViewer
  • StandardMaterial, modelColor, sectionStroke* removed from IMaterials
  • MaterialSettings.useFastMaterials, .standard, .section removed
  • skybox, skylight, sunlights removed from ViewerSettings
  • viewer.react.camera renamed to viewer.framing
  • nodeState renamed to state (Ultra); use VisibilityState enum
  • Input key binding API changed — register via inputs.keyboard.registerKeyDown()
  • Camera lookAt parameter removed — use orbitTowards() or set(position, target)