·
81 commits
to sroberge/1_0
since this release
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
ViewerApiabstraction: Both WebGL and Ultra viewers now expose a unifiedViewerApihandle (WebglViewerApi/UltraViewerApi) throughVIM.React.Webgl.createViewer()andVIM.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.settingsremoved: Settings are consumed at construction time only — exposing them as a field was misleading. Removed fromIWebglViewer.- Material API cleanup:
IMaterialsnow only exposes user-facing properties (ghostOpacity,ghostColor,outlineOpacity,outlineThickness,outlineColor,clippingPlanes). Internal system materials are hidden behind asystemgetter. Element3Dinterface:IElement3Dexposes only BIM-facing properties; mesh internals are hidden.- Input API: Inputs organized under
viewer.core.inputswith typedPointerModeenum, configurable key handlers, and clean mouse/touch callbacks. Removed spacebar bindings. - Camera API: Fluent
snap()/lerp(duration)API for instant vs animated camera moves. Unifiedframe(),orbit(),orbitTowards(),zoomTo(). RemovedlookAtparameter. Rotation axes clarified (x = horizontal/yaw, y = vertical/pitch). - Framing renamed:
viewer.react.camera→viewer.framingfor clarity. - Signal interfaces:
onXxxevent 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 (
packedIdattribute withMARKER_VIM_INDEXsentinel). GpuPickerreads 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
maskMaterialto a dedicated render target. Edge detection runs on the mask, not the depth buffer — eliminates depth precision artifacts at long range. scene.backgroundfix: 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
thicknessuniform (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) andoutlineColorexposed onIMaterials. Both live on the merge pass for clean separation. - Dead properties removed:
camera,depthBuffer,color,precisionand associated uniforms removed fromOutlineMaterial.OutlinePassno longer receives or wires a camera.
Material System Cleanup
StandardMaterialremoved:_opaque/_transparentStandardMaterialfields deleted fromMaterials. VIM meshes have always usedModelMaterial(custom GLSL3 shader) —StandardMaterialwas never in the rendering path.- Dead settings removed:
skybox,skylight,sunlights— defined, parsed, never consumeduseFastMaterials,materials.standard.color— toggle with no effectmaterials.section.strokeWidth/Falloff/Color— only applied toStandardMaterialshader, which was unused
modelColor,sectionStroke*removed fromIMaterials— dead wiring to removed materials.MaterialSettingsnow contains onlyghostandoutline.MaterialSet: New value type{ opaque, transparent, hidden }for per-mesh material assignment.applyMaterial()helper is the single place that callsMaterialSet.get().
Geometry Loading & Performance
- Color palette texture: Per-element colors stored in a shared 128×128
DataTexture(25³ = 15,625 quantized colors).ModelMaterialreads colors viatexelFetch— no per-vertex color upload on color changes. texelFetch/ WebGL2: Replacedtexture2DwithtexelFetchin shaders for direct texel access.G3dSubsetand offsets: IntroducedG3dSubsetas a filtered view of G3d instances.G3dMeshOffsetspre-computes vertex/index counts per mesh for buffer allocation.InsertableGeometrychunking: Merged mesh geometry split at 16M indices to stay within buffer limits.InstancedMeshFactory: Instanced meshes (>5 instances) built with per-instancepackedIdandignoreattributes 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 onViewerSettings.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. nodeState→state: 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
packedIdattribute 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.
@internaltags: System-only classes and methods marked throughout.- TypeDoc comments: Cleaned up and expanded across public API.
Breaking Changes
viewer.core.settingsremoved fromIWebglViewerStandardMaterial,modelColor,sectionStroke*removed fromIMaterialsMaterialSettings.useFastMaterials,.standard,.sectionremovedskybox,skylight,sunlightsremoved fromViewerSettingsviewer.react.camerarenamed toviewer.framingnodeStaterenamed tostate(Ultra); useVisibilityStateenum- Input key binding API changed — register via
inputs.keyboard.registerKeyDown() - Camera
lookAtparameter removed — useorbitTowards()orset(position, target)