Aholo Viewer

repository·master·Indexed 21 days ago

https://github.com/manycoretech/aholo-viewer

A high-performance 3D renderer specialized for 3D Gaussian Splatting (3DGS) and Meshes, featuring a Chunked Streaming LOD schema for large-scale datasets. The ecosystem includes the @manycore/aholo-viewer rendering runtime for WebGL/WebGL2 browsers, the splat-dev-server for asset development, and the @manycore/aholo-splat-transform CLI for Gaussian Splatting modifications and LOD generation.

Tokens
43.2K
Snippets
134
Records
186
Agent score
75%

What's inside aholo-viewer

  1. Overview of Aholo Viewer

    master

    Viewer is an online tool built with @manycore/aholo-viewer designed to import and display supported 3D assets. It is compatible with standard formats and LOD-format data generated by @manycore/aholo-splat-transform.

    Important Note on Data Access: Because browsers cannot access local files directly, chunk-lod data must be hosted via a server or CDN. For local development and validation, use @manycore/aholo-splat-dev-server to host your assets.

  2. Adhere to project Non-Negotiables and constraints

    master

    To maintain repository integrity, observe these strict constraints:

    • API Integrity: The Renderer public API exports are user-owned. Do not modify packages/renderer/src/index.ts exports unless explicitly requested.
    • Generated Files: Never hand-edit external/egs-core, website/.generated/api/, or any generated dist folders.
    • Workspace Dependencies: Do not delete external/splat-transform; it is a required workspace package.
    • Monaco: Keep Monaco route-local.
    • Examples: Maintain examples as paired JSON metadata and TypeScript source files.
  3. How the Playground examples work

    master

    The Playground uses a paired file system for examples located in website/src/content/examples/. Each example requires two files with the same name:

    1. .json file: Contains metadata such as title, description, tags, accent, and order.
    2. .ts file: Contains the actual TypeScript code for the scene. This file is imported using the ?raw suffix to be passed into the Monaco editor.

    Example structure:

    website/src/content/examples/
      basic-scene.json
      basic-scene.ts

    Playground URLs can include example (the preset slug) and code (the lz-string compressed editor source).

  4. Configure Geometry and Materials

    master

    Geometry

    Geometry defines the shape of a Drawable. Most common geometry is rendered as a Mesh using triangle faces. Geometry data is organized into attributes:

    • position: Vertex positions.
    • uv: Texture sampling coordinates.
    • normal: Used for lighting calculations.
    • index: Used to reduce duplicated vertex data by indexing into position.
    • PopBufferGeometry: A specialized geometry type that supports PopBuffer and Level of Detail (LOD). It should be used in conjunction with PopMesh.

    Materials

    Materials determine how light interacts with geometry. Common types include:

    • MeshPhongMaterial: A lighting-aware material.
    • MeshBasicMaterial: A basic material that does not react to light.
  5. Understand Viewports and the Rendering Flow

    master

    Viewport

    A viewport is a rendering output unit with its own bounds. A single Viewer can contain multiple viewports.

    • A viewport can cover the full canvas or a specific bounded region.
    • Each viewport can own an independent camera.
    • Each viewport has an independent pipeline configuration.
    • By default, a Viewer contains one viewport covering the full canvas.

    Internal Rendering Flow

    The rendering process follows this pipeline:

    1. Config: User-provided Config affects the pipeline.
    2. Render Pipeline: Generates a DrawcallList.
    3. DrawcallList: Stores information for each draw command. Each drawcall maps to a low-level graphics API call (WebGL/WebGL2).

    Note: The number of drawcalls typically correlates with CPU cost. You can inspect this flow using the Spector Chrome extension.

  6. How the Aholo Viewer project is structured

    master

    Aholo Viewer is a monorepo split into two primary products:

    1. @manycore/aholo-viewer: The TypeScript renderer package (located in packages/renderer/). This is the core engine.
    2. @manycore/aholo-viewer-website: An Astro-based application (located in website/) that hosts the documentation, API reference, and an interactive Playground.

    The root package manages the entire workspace using pnpm, coordinating builds, API generation, and content validation via specialized scripts in the scripts/ directory.

  7. How to handle DOM events and Canvas access

    master

    When building interactive applications with Aholo Viewer, follow these rules to ensure stability:

    1. Use a stable container: Attach all application DOM event listeners (pointer, wheel, keyboard, etc.) to the container element passed to createViewer, not to the engine's canvas.
    2. Avoid persistent canvas references: The engine manages the canvas lifecycle and may replace it. Do not store the canvas element in application state, class fields, or long-lived closures.
    3. Just-in-time access: If you must access the canvas directly, read it from the current viewer/container state just-in-time, use it immediately, and discard the reference.
    4. Teardown: Remove container-level event listeners during your application's cleanup phase before releasing viewer or scene resources.
  8. Use Lights and Shadows in a scene

    master

    Lights are Object3D instances that interact with materials to determine object appearance.

    Common Light Types

    • DirectionalLight: Simulates a distant source (like sunlight) emitting light in a specific direction.
    • AmbientLight: Provides non-directional ambient light to simulate diffuse indirect lighting.

    Tip: A common setup involves one AmbientLight and four DirectionalLight instances from different directions.

    Shadows

    • Light Shadows: Controlled via the shadow field on a light instance.
    • Casting: Controlled via the castShadow field on a Drawable.
    • Planar Shadows: A special type of shadow that does not depend on lights; it must be enabled via configuration through planarShadow.
  9. Configure the rendering pipeline with PipelineConfig

    master

    The pipelineConfig property within IViewerConfig allows you to control various pipeline features. Each major section of the pipeline can be toggled on or off using an enable option. The available pipeline sections are:

    • Background (IBackgroundPluginConfig): Manages background rendering, including skyboxes and ground grids.
    • Composite (ICompositePluginConfig): Manages composition before output, typically used to optimize performance for multi-view rendering.
    • Splatting (ISplattingPluginConfig): Manages 3DGS (3D Gaussian Splatting) rendering behavior. For specific parameter details, refer to the 3dgs-preset-config documentation.
    • TAA (ITaaPluginConfig): Manages static temporal supersampling anti-aliasing.
    // Conceptual structure of pipelineConfig
    const config: IViewerConfig = {
      pipelineConfig: {
        Background: { enable: true, /* ... */ },
        Composite: { enable: true, /* ... */ },
        Splatting: { enable: true, /* ... */ },
        TAA: { enable: true, /* ... */ }
    };
  10. Manage GPU and Object resource cleanup

    master

    To prevent memory leaks, choose the appropriate cleanup method based on the object's lifecycle:

    • freeGPU(): Use this to release GPU memory while keeping the object instance logically reusable. The object will re-upload resources to the GPU if it is rendered or updated again.
    • freeAllGpuResourceOwned(): Use this when an object owns related GPU resources that should also be released.
      • Example: geometry.freeAllGpuResourceOwned() releases the geometry GPU resource plus its attributes and indices.
      • Example: drawable.freeAllGpuResourceOwned() releases its materials, geometry, and drawable GPU resources.
    • destroy(): Use this only when the object is being permanently retired.
      • Requirement: Before calling destroy(), ensure the object is removed from the scene and is no longer referenced by any frame callbacks, async loads, event listeners, viewports, materials, geometries, or application state.

    Best Practice: In component frameworks (React, Vue, Svelte), always cancel pending async work and stop animation/render loops before performing cleanup during the unmount phase.