chore: import upstream snapshot with attribution

This commit is contained in:
wehub-resource-sync
2026-07-13 13:18:05 +08:00
commit acd8e21031
297 changed files with 56514 additions and 0 deletions
+169
View File
@@ -0,0 +1,169 @@
---
name: use-aholo-viewer
description: Guide external npm package users and AI coding agents integrating @manycore/aholo-viewer into web applications. Use when asked to install, bootstrap, render 3D Gaussian Splatting or mesh content, configure cameras, scenes, lighting, viewer pipeline options, or write TypeScript examples for the public @manycore/aholo-viewer npm package.
---
# Use Aholo Viewer
Use this skill to build or modify user applications that consume the public `@manycore/aholo-viewer` npm package. Treat it as a full-featured browser rendering package, not as this repository's internal renderer source.
## Source Docs
Before generating non-trivial code, read the AI-oriented docs advertised by `https://aholojs.dev/llms.txt`:
- `https://aholojs.dev/llm/manual/getting-started.md` for installation and the minimal Vite setup.
- `https://aholojs.dev/llm/manual/basic-concepts.md` for scenes, objects, cameras, viewports, and the render flow.
- `https://aholojs.dev/llm/api/index.md` to confirm public exports.
- `https://aholojs.dev/llm/examples/index.md` for runnable TypeScript patterns.
Prefer these Markdown docs over scraping rendered HTML pages.
## Integration Workflow
1. Install the package in a browser app:
```bash
npm install --save @manycore/aholo-viewer
npm install --save-dev vite typescript
```
2. Import only public package exports from `@manycore/aholo-viewer`.
3. Create a real DOM container with stable dimensions before calling `createViewer`. Attach application DOM event listeners to this container, not to the engine canvas.
4. Create a camera, position it, call `lookAt`, add objects to `viewer.getScene()`, then call `viewer.setCamera(camera)`.
5. Configure rendering with `setViewerConfig(viewer, { pipeline: ... })`.
6. Render explicitly with `viewer.render()`. If the app relies on viewer-triggered invalidation, set `viewer.requestRenderHandler` to schedule another render with `requestAnimationFrame`.
7. Clean up when removing content: detach scene objects, stop render/update loops that still reference them, then release GPU resources or owned resources according to the cleanup rules below.
## Minimal Splat Example
Use this pattern for a Vite/TypeScript browser entry:
```ts
import {
BackgroundMode,
Color,
PerspectiveCamera,
SplatLoader,
SplatUtils,
Vector3,
createViewer,
setViewerConfig,
} from '@manycore/aholo-viewer';
const SPLAT_URL = 'https://holo-cos.aholo3d.cn/aholo-opensource/gs_file/bear/bear.3d71a266.sog';
const container = document.createElement('div');
container.style.width = '500px';
container.style.height = '500px';
document.body.appendChild(container);
async function main() {
const viewer = createViewer('example-viewer', container, {});
const camera = new PerspectiveCamera(60, 1, 0.1, 2000);
const response = await fetch(SPLAT_URL);
const buffer = await response.arrayBuffer();
const data = await SplatLoader.parseSplatData(
SplatLoader.SplatFileType.SOG,
new Uint8Array(buffer),
SplatLoader.SplatPackType.Compressed,
);
const splat = await SplatUtils.createSplat(data);
camera.up.set(0, -1, 0);
camera.position.set(-1.5, -0.5, 0);
camera.lookAt(new Vector3(0, 0, 0));
viewer.getScene().add(splat);
viewer.setCamera(camera);
setViewerConfig(viewer, {
pipeline: {
Background: {
background: {
active: BackgroundMode.BasicBackground,
basic: { color: new Color(0, 0, 0) },
},
ground: { enabled: false },
},
Splatting: { enabled: true },
TAA: { enabled: false },
},
});
const render = () => viewer.render();
viewer.requestRenderHandler = () => requestAnimationFrame(render);
requestAnimationFrame(render);
}
main();
```
## Common Public Exports
- Viewer setup: `createViewer`, `setViewerConfig`, `Viewer`, `Viewport`.
- Cameras and math: `PerspectiveCamera`, `OrthographicCamera`, `Vector2`, `Vector3`, `Vector4`, `Color`, `Matrix4`, `Quaternion`.
- Scene objects: `Object3D`, `Scene3D`, `Mesh`, `Splat`, `AmbientLight`, `DirectionalLight`, `PointLight`, `SpotLight`.
- Mesh content: `BufferGeometry`, `BufferAttribute`, `MeshBasicMaterial`, `MeshPhongMaterial`, `Side`, `downloadTexture`.
- Splat content: `SplatLoader`, `SplatUtils`, `CompressedSplat`, `SuperCompressedSplat`, `SogSplat`.
- Optional loaders/utilities: `GLTFLoader`, `DracoLoader`, `Animation`, `Events`.
Confirm exact symbols in `/llm/api/index.md` when using less common APIs.
## Patterns
For 3DGS content:
- Use `SplatLoader.parseSplatData(...)` to parse supported splat formats.
- Use `SplatUtils.createSplat(data)` to create a renderable splat.
- Enable `pipeline.Splatting`.
- Set camera up vectors deliberately. OpenCV-style 3DGS data commonly uses `camera.up.set(0, -1, 0)`.
For mesh content:
- Build geometry with `BufferGeometry`, `BufferAttribute`, and optional indices.
- Use `MeshPhongMaterial` with lights for shaded meshes, or `MeshBasicMaterial` for unlit objects.
- Add lights such as `AmbientLight`, `DirectionalLight`, or `PointLight` before rendering lit materials.
For interactive apps:
- Tie camera controls or animations to a frame loop that calls `viewer.render()`.
- Keep viewer container size stable and update rendering after layout changes.
- Register pointer, wheel, keyboard focus, drag/drop, resize, and custom DOM event listeners on the viewer container or another application-owned element.
- Cache large splat data when appropriate, but keep the first example simple unless the user asks for caching.
## DOM Events and Canvas Access
Treat the container as the stable application boundary:
- Listen for DOM events on the `container` passed to `createViewer(...)`, or on another element owned by the application.
- Do not attach event listeners to the viewer canvas. The canvas is managed internally by the engine and may be replaced.
- Do not persistently store the engine canvas element in application state, class fields, module globals, framework refs, or closures intended to outlive the current operation.
- If direct canvas access is unavoidable, read it just-in-time from the current viewer/container state, use it immediately, and discard the reference.
- Remove container-level event listeners during teardown before releasing viewer or scene resources.
## Resource Cleanup
Use the lightest cleanup method that matches ownership and lifecycle:
- Use `freeGPU()` when the goal is to release GPU memory while keeping the object instance logically reusable. The object may upload GPU resources again if it is rendered or updated later.
- Use `freeAllGpuResourceOwned()` when the object owns related GPU resources that should also be released. For example, `geometry.freeAllGpuResourceOwned()` releases the geometry GPU resource plus its attribute and index GPU resources; `drawable.freeAllGpuResourceOwned()` releases its materials, geometry, and drawable GPU resources.
- Use `destroy()` only when the object is permanently retired. Before calling `destroy()`, ensure the object is removed from the scene, no frame callback, async load, event listener, control, viewport, material, geometry, or app state will use it again, and it is not currently participating in a render/update pass.
- Prefer `freeGPU()` or `freeAllGpuResourceOwned()` for memory-pressure cleanup. Prefer `destroy()` for final teardown after references are severed.
- In component frameworks, cancel pending async work and stop animation/requestRender callbacks before releasing resources in unmount cleanup.
## Guardrails
- Do not hand-write code against private renderer internals or repository-only paths.
- Do not assume a server-side runtime; the viewer needs browser DOM and WebGL/WebGL2-capable canvas support.
- Do not construct `Splat` directly. Use loader and utility APIs.
- Do not register app DOM events on the engine canvas. Register on the container because the engine owns the canvas lifecycle and may replace it.
- Do not hold persistent references to the engine canvas. Read it only when needed, use it immediately, and release the reference.
- Do not call `destroy()` on resources that shared objects, cached data, render callbacks, or pending async work may still reference.
- Do not use `destroy()` as the default GPU-memory cleanup method. Use `freeGPU()` for the object's own GPU state, or `freeAllGpuResourceOwned()` when owned child resources should also release GPU state.
- Do not omit cleanup in component frameworks. In React, Vue, Svelte, or similar frameworks, dispose viewer-owned objects and cancel pending async work during unmount.
- Do not invent package exports. Check the LLM API index or installed package types.
@@ -0,0 +1,50 @@
# Claude Instructions: Use Aholo Viewer
Use these instructions when Claude is helping a user integrate the public `@manycore/aholo-viewer` npm package into a browser application.
## Activation
Apply this guidance when the user asks Claude to install, bootstrap, debug, or extend an app that uses `@manycore/aholo-viewer`, especially for:
- 3D Gaussian Splatting (3DGS) rendering.
- Mesh rendering with `BufferGeometry`, `Mesh`, lights, and materials.
- Viewer setup, camera setup, scene composition, render-loop wiring, or cleanup.
- React, Vue, Svelte, Vite, or plain TypeScript browser integrations.
## Read First
Before writing non-trivial code, read the AI-facing docs listed by `https://aholojs.dev/llms.txt`.
Preferred reading order:
1. `https://aholojs.dev/llm/manual/getting-started.md`
2. `https://aholojs.dev/llm/manual/basic-concepts.md`
3. `https://aholojs.dev/llm/api/index.md`
4. `https://aholojs.dev/llm/examples/index.md`
Use the Markdown docs instead of scraping rendered HTML.
## Implementation Rules
- Import only public exports from `@manycore/aholo-viewer`; never import internal `@qunhe/*` packages.
- Create a stable application-owned container before calling `createViewer(...)`.
- Attach DOM event listeners to the container or another app-owned element, not to the engine canvas.
- Do not persistently store the engine canvas. If canvas access is unavoidable, read it only at the point of use and discard the reference immediately.
- Use `PerspectiveCamera` or `OrthographicCamera`, then call `viewer.setCamera(camera)`.
- Add objects to `viewer.getScene()`.
- Configure the pipeline with `setViewerConfig(viewer, { pipeline: ... })`.
- Trigger rendering with `viewer.render()` or schedule rendering through `viewer.requestRenderHandler`.
- Do not construct `Splat` directly; load splat data with `SplatLoader` and create renderable splats with `SplatUtils.createSplat(...)`.
## Cleanup Rules
- Stop render loops, event listeners, controls, and pending async work before releasing resources.
- Use `freeGPU()` to release an object's own GPU resources while keeping the object reusable.
- Use `freeAllGpuResourceOwned()` when owned child resources should also release GPU state. For example, `geometry.freeAllGpuResourceOwned()` also releases attribute and index GPU resources.
- Use `destroy()` only for final teardown after the object is detached from the scene and no callback, async task, viewport, material, geometry, or app state can use it again.
## Output Style
- Prefer concise TypeScript examples over long explanations.
- For full setup steps, link to `https://aholojs.dev/en-US/manual/getting-started/` instead of duplicating the complete tutorial.
- Confirm less common exports against `https://aholojs.dev/llm/api/index.md` before using them.
@@ -0,0 +1,4 @@
interface:
display_name: 'Use Aholo Viewer'
short_description: 'Guide AI agents to integrate @manycore/aholo-viewer'
default_prompt: 'Use $use-aholo-viewer to build a Vite integration with @manycore/aholo-viewer.'
+90
View File
@@ -0,0 +1,90 @@
# Vibe Coding Guide
Concise source for AI-assisted product writing, collaboration, and handoff rules.
## Work Loop
1. Read `AGENTS.md`.
2. Use the narrowest project skill for the task.
3. Read `docs/architecture.md` only for package boundaries, generated API docs, build flow, or directory structure.
4. Run `git status --short` before editing and preserve user changes.
5. When reading Chinese files, use `rg` or `Get-Content -Encoding utf8` to avoid PowerShell encoding ambiguity.
## Product Brief
- Audience: frontend engineers, SDK documentation readers, and product-demo evaluators.
- Positioning: high-performance 3D Gaussian Splatting (3DGS) rendering for web applications.
- Stage: preparing for public release.
- Visual direction: simple, refined, spacious, comfortable, technical.
- Primary manual-check browser: Chrome.
Core value:
- Focused renderer experience for web-based 3DGS scenes.
- High-performance 3DGS rendering.
- Surrounding 3DGS facilities: examples, preview, debugging, docs, and integration support.
## Skill Map
- `aholo-viewer`: cross-area work, repo cleanup, workspace scripts, and validation routing.
- `aholo-site`: Astro website, examples, docs UI, Playground, Monaco, runner, preview, presets, URL state.
- `aholo-renderer`: renderer package, public API, build, declarations, release checks.
- `aholo-docs`: docs, manual content, bilingual copy, AI collaboration notes.
- `frontend-design`: Aholo website visual direction, responsive styling, and UI polish.
## Writing Rules
- Keep copy concise, concrete, and tool-oriented.
- Avoid placeholders, broad marketing claims, and invented API names.
- Do not compare the renderer to third-party engines or frameworks unless explicitly asked.
- Use actual public renderer exports in snippets.
- Keep Chinese copy technical and concise.
- Keep English copy in an SDK documentation style.
- Keep zh-CN and en-US manual pages structurally parallel.
## Terms
```text
3D Gaussian Splatting (3DGS) / 3DGS
Mesh / 网格
Renderer / 渲染器
Scene / 场景
Camera / 相机
Material / 材质
Render loop / 渲染循环
Playground / Playground
Examples / 示例
Manual / 手册
API Reference / API 参考
```
## Non-Negotiables
- Renderer public API exports are user-owned.
- Do not modify `packages/renderer/src/index.ts` exports unless explicitly asked.
- Do not hand-edit `external/egs-core`, `website/.generated/api/`, or generated `dist` folders.
- Do not delete `external/splat-transform`; it is a required workspace package.
- Keep Monaco route-local.
- Keep examples as paired JSON metadata and TypeScript source files.
## Validation
```text
Site/Playground/style pnpm.cmd check:website
Renderer/API/release pnpm.cmd check
Package/release pnpm.cmd build
Docs-only repo notes path/reference scan unless imported by website
```
If esbuild cannot read the workspace in a sandboxed run, rerun the same command with approved workspace access.
For browser-based website checks, prefer an already running website service and reuse its URL/port before starting a new dev server.
## Handoff
End with:
- What changed.
- Validation result.
- Skipped checks, risks, or assumptions.
- Follow-up suggestions only when useful.
+211
View File
@@ -0,0 +1,211 @@
# Project Architecture
## Overview
Aholo Viewer is split into two main products:
- `@manycore/aholo-viewer`: the TypeScript renderer package.
- `@manycore/aholo-viewer-website`: the Astro documentation and playground website.
The root package coordinates build, check, API generation, and packaging through pnpm workspace scripts.
## Workspace Layout
```text
./
package.json
pnpm-workspace.yaml
AGENTS.md
website/
package.json
astro.config.mjs
.generated/
api/
src/
components/
config/
content/
i18n/
layouts/
pages/
playground/
styles/
utils/
packages/
renderer/
package.json
tsconfig.json
src/
dist/
scripts/
build-package.mjs
check-content.mjs
clean-package.mjs
ensure-submodules.mjs
package-utils.mjs
prepare-egs-types.mjs
generate-api-docs.mjs
docs/
architecture.md
ai/
vibe-coding-guide.md
external/
egs-core/
splat-transform/
```
## Structural Roles
- Root package: workspace entry point for dependency preparation, renderer build, API generation, website checks, and release packaging.
- `packages/renderer/`: public renderer package source. `src/index.ts` is the public API barrel; package-local files hold math, events, animation, loader, and utility namespaces.
- `website/`: Astro application for home, manual, API reference, examples, and Playground. Route modules live under `pages/`; shared UI lives under `layouts/` and `components/`; route-independent data helpers live under `utils/`.
- `website/src/playground/`: route-local Playground runtime, Monaco integration, renderer adapter, camera control, and example-facing types.
- `website/src/content/`: manual pages, manual assets, and paired example metadata/source files.
- `scripts/`: shared Node automation for submodule readiness, EGS declarations, renderer packaging, API HTML generation, content validation, and clean tasks.
- `external/egs-core`: upstream submodule consumed by workspace packages and renderer packaging scripts.
- `external/splat-transform`: required workspace package used by the manual and examples workflow.
## Dependency Direction
```text
external/egs-core workspace packages
-> scripts/prepare-egs-types.mjs
-> renderer type checks and declaration bundling
packages/renderer/src/index.ts
-> scripts/build-package.mjs
-> packages/renderer/dist
-> website Playground runtime, examples, and type hints
packages/renderer/src/index.ts
-> scripts/generate-api-docs.mjs
-> website/.generated/api/
-> website pages
```
`website/` may depend on `@manycore/aholo-viewer` through the workspace package. The renderer package should not depend on the website. Website `dev`, `build`, and `check` first run the renderer build, then regenerate API HTML and manifest data.
`external/egs-core` is an upstream dependency submodule. `external/splat-transform` is a required workspace package. Scripts may read external sources and generate dependency outputs needed for local builds, but repository changes should not hand-edit upstream code unless a task explicitly targets that package.
## Root Command Graph
Root scripts keep the workspace build order explicit:
```text
pnpm dev
-> .egs:types
-> .renderer:build
-> .docs:api
-> check:content
-> .site:dev
pnpm check
-> .egs:types
-> .renderer:check
-> .renderer:build
-> .docs:api
-> check:content
-> .site:check
pnpm build
-> build:website
-> .egs:types
-> .renderer:build
-> .docs:api
-> .site:build
```
Targeted commands preserve the same boundaries: `check:renderer` prepares EGS types and runs the renderer type check, `check:website` prepares renderer/API outputs before Astro checks, and `docs:api` prepares EGS types before generating API HTML and manifest data.
## API Documentation Flow
1. Export public API from `packages/renderer/src/index.ts`.
2. Add concise JSDoc comments to public classes, functions, interfaces, and types.
3. Run `pnpm docs:api`.
4. The generated HTML fragments are written to the ignored local directory `website/.generated/api/{locale}/`.
5. A generated manifest beside those fragments drives API navigation, metadata, and table-of-contents data.
6. Astro API routes inline the TypeDoc HTML through the same DocsLayout flow used by the Manual.
Do not edit generated API HTML or manifest data by hand. `pnpm dev`, `pnpm build`, and `pnpm check` regenerate it before the website starts.
## Playground Flow
Examples live in the Astro content tree as paired metadata and source files:
```text
website/src/content/examples/
basic-scene.json
basic-scene.ts
```
The JSON file holds title, description, tags, accent, and order. The same-named TypeScript file is imported with `?raw`, passed to Monaco, and rendered in the Playground preview. Playground URLs support:
- `example`: selected preset slug.
- `code`: `lz-string` compressed editor source.
Resetting or switching presets clears custom `code` and returns to a clean example URL.
Playground type hints use `packages/renderer/dist/index.d.ts` through the workspace package. Do not add a second handwritten renderer declaration file under `website/src/playground/`.
## Content Validation
`pnpm check:content` scans manual pages, localized slugs, heading-depth parity, example source pairs, manual image references, orphan manual images, and internal-only documentation links. `pnpm check` and `pnpm check:website` run it before Astro checks.
## Website Style Layers
Website styles are split by responsibility so global changes stay small and feature surfaces remain easy to reason about:
```text
website/src/styles/
theme.css Design tokens: color, type, radii, shadows, layout widths
global.css Reset, base document styles, buttons, code, simple primitives
site.css Header, language/theme controls, listing-page shell
home.css Immersive home page and home-only interaction states
examples.css Examples list and example detail viewer chrome
docs.css Manual/API documentation layout and prose
playground.css Playground workspace, editor, preview, inspector chrome
```
`BaseLayout.astro` imports `theme.css`, `global.css`, and `site.css`. Feature pages import their own feature stylesheet only when needed. Avoid moving feature-specific selectors back into `global.css`.
The home page intentionally keeps a darker immersive style around the 3D canvas. Docs, API, examples, and Playground should stay lighter, more restrained, and tool-like.
## Build Outputs
- Website output: `website/dist/`
- Astro cache: `website/.astro/`
- Renderer output: `packages/renderer/dist/`
- `index.js`: bundled public runtime.
- `index.d.ts`: bundled public declarations, including upstream EGS types used by exported symbols.
- `splat-worker.js`: bundled worker referenced by the runtime.
Root-level `dist/` and `.astro/` are stale and should not exist after the workspace split.
Ignored generated folders can be removed when a clean workspace is needed, but they should be produced by commands rather than hand-edited.
## Architecture Improvement Opportunities
1. Keep API navigation metadata generated from the same source as API HTML.
`scripts/generate-api-docs.mjs` derives API namespaces, categories, entries, and TOC data from `packages/renderer/src/index.ts`. Keep any future API navigation changes in that generated manifest flow to avoid drift when public namespaces change.
2. Keep Playground integration behind the website adapter.
`website/src/playground/renderer-adapter.ts` is the boundary between Monaco-transpiled examples, preview lifecycle, camera control, runtime stats, and `@manycore/aholo-viewer`. New preview behavior should stay in the website adapter unless it is a reusable renderer capability that belongs in `packages/renderer/`.
3. Make external EGS consumption more declarative.
`prepare-egs-types.mjs` discovers and prepares EGS declarations, while `build-package.mjs` discovers runtime packages for esbuild aliases. A small allow-list or manifest for consumed EGS packages would make renderer packaging easier to audit and less dependent on directory traversal.
4. Treat generated output ownership as an architectural contract.
`packages/renderer/dist/`, `website/.generated/api/`, and temporary API cache folders are command-owned. Any new generated surface should also have an owning script, stale-file cleanup, and a validation path before it is referenced by website routes or package exports.
5. Keep validation mapped to changed surfaces.
Current checks are well split between renderer, website, content, and package build flows. As the site grows, add new validation to the narrowest existing command first, then wire it into `check` only when it protects a cross-area contract.