voxelkloudBack to the project

DOCS / TECHNICAL REFERENCE

One index,
one guide per package.

This index keeps the architecture notes in one place and sends each package to its own guide. The selection path, the culling rules, and the package examples are all here, but the longer package docs live under their own route so they stay easy to link.

How the stack is
split.

LOD selection

The selector spends from pointBudget until projected screen error falls under targetScreenError. When there is room left, minScreenError keeps refinement bounded.

Frustum culling

A node outside the frustum means every descendant is outside too, so the selector drops the branch. Intersecting nodes keep descending; inside nodes stop paying the plane test for their children.

Loader responsibilities

The loader picks the driver from the URL and returns the neutral source/tree/openPoints contract. The renderer never needs to know whether the data came from Potree, COPC, EPT, or a single-file build.

Precision stays relative

Large CRS coordinates stay in float64 at the tree and camera level. Per-point positions are rebased relative to the cloud origin so the shader sees small numbers instead of the whole globe.

LOD selection
and the result it returns.

`@voxelkloud/view/lod` stays importable anywhere because it has no dependency on three, the DOM, or a GPU. The selector walks the tree best-first, spends the point budget, and stops when the projected error reaches the target.

Basic use

Resolve the knobs once per frame, reuse the scratch buffers, and let the selector tell you whether budget, headroom, or the error floor stopped refinement.

import {
  createLodScratch,
  createLodSelection,
  resolveLodOptions,
  selectVisible,
} from '@voxelkloud/view/lod'

const opts = resolveLodOptions({ targetScreenError: 1.35, pointBudget: 3_000_000 })
const scratch = createLodScratch(tree.nodeCount)
const selection = createLodSelection(opts.maxNodes)

selectVisible(tree, cameraState, opts, scratch, selection)

Selection result

`selection.limitedBy` says which ceiling won. `selection.achievedScreenError` says how much error the current frame actually left on screen.

if (selection.limitedBy === 'budget') {
  console.log('Spend more or lower the target.')
}

console.log(selection.achievedScreenError)

Frustum culling
and depth range handling.

A node outside the frustum means its descendants are outside too, so the branch can be pruned immediately. The frustum planes are extracted once, then every box is classified against them with plain numbers.

Plane extraction and box tests

The view hands the selector a camera snapshot. The low-level helpers then turn the clip-from-world matrix into six normalised planes and classify each box against them.

import {
  Containment,
  classifyAabb,
  extractFrustumPlanes,
} from '@voxelkloud/view/lod'

const planes = new Float64Array(24)
extractFrustumPlanes(clipFromWorld, planes, 'zero-to-one', false)

const state = classifyAabb(planes, minX, minY, minZ, maxX, maxY, maxZ)
if (state === Containment.Outside) return

Depth convention

WebGPU and WebGL do not share the same depth range, so the renderer resolves the convention from the live backend before the selection step runs.

const depthRange = renderer.coordinateSystem === 2000
  ? 'zero-to-one'
  : 'minus-one-to-one'

extractFrustumPlanes(clipFromWorld, planes, depthRange, false)

Package guides,
one link each.

Each card below opens a guide dedicated to one package. Public packages and source-only drivers stay on the same page so the implementation notes are never far from the code.

Runtime packages

Core types, loading, rendering, and thin framework adapters. This is the surface most apps touch first.

@voxelkloud/corepublic

Neutral vocabulary and octree math

Shared types, bounding boxes, Morton codes, and CRS declarations.

npm install @voxelkloud/core

Use core when you need the shared data model or the tree math without a loader or renderer attached.

@voxelkloud/loaderpublic

URL-driven loading and driver selection

Pick the right driver, load the source, and return the neutral tree contract.

npm install @voxelkloud/loader

The loader resolves a URL, chooses the matching format driver, and hands back source, tree, and reader factory objects.

@voxelkloud/viewpublic

WebGPU renderer and scene controller

Own the renderer, keep the camera and scene exposed, and feed it the loaded tree.

npm install @voxelkloud/view three

This is the layer that turns source data into pixels and keeps the scene and camera under your control.

@voxelkloud/view/lodpublic

LOD selection and culling helpers

Dependency-free selection math for workers, SSR, tests, and the renderer.

import from @voxelkloud/view/lod

This subpath stays dependency-free so it can run in workers, SSR, tests, or any place that only needs the selector.

@voxelkloud/reactpublic

Thin React wrapper

A small component over the shared renderer, with lifecycle handled for you.

npm install @voxelkloud/react three

Use the wrapper when React should own the canvas lifecycle and you do not want to write that wiring yourself.

@voxelkloud/vuepublic

Thin Vue 3 wrapper

The same renderer, exposed through a Vue component instead of a React one.

npm install @voxelkloud/vue three

The Vue binding mirrors the React API so the two adapters stay aligned while the renderer stays shared.

Format drivers

Each input format gets its own guide and its own responsibility. The renderer only sees the neutral tree contract.

@voxelkloud/format-potreesource

Potree v2 driver

Read metadata.json, hierarchy.bin, and octree.bin, then hand back the neutral tree contract.

npm install @voxelkloud/format-potree

This driver reads the Potree v2 directory layout exactly as it is and produces the source/tree objects the rest of the stack already understands.

@voxelkloud/format-copcsource

COPC driver

One LAZ file, one HTTP host, and an octree embedded inside the file.

npm install @voxelkloud/format-copc

COPC keeps the octree in the file, so the driver reads the page model and fetches only the nodes the view actually needs.

@voxelkloud/format-eptsource

EPT driver

Read a static directory of JSON hierarchy pages and per-node payloads.

npm install @voxelkloud/format-ept

EPT is a good fit for object storage or static hosting because the hierarchy and payloads are already laid out as separate files.

@voxelkloud/format-singlesource

Single-file LAS/LAZ builder

Build an octree in the browser from a file that has no index yet.

npm install @voxelkloud/format-single

For a raw LAS or LAZ file, this package downloads the file, builds the octree in a worker, and hands the renderer the same neutral contracts as the indexed drivers.

@voxelkloud/format-lassource

Shared LAS record decoder

Decode the point-record layer used by COPC, EPT, and the single-file builder.

npm install @voxelkloud/format-las

This package owns the record layout and byte-to-point conversion logic. The higher-level format drivers reuse it instead of each decoding LAS bytes on their own.

@voxelkloud/format-3dtilessource

3D Tiles driver

Load a tileset document, expand the tile tree, and open point content from .pnts tiles.

npm install @voxelkloud/format-3dtiles

This driver is for tileset-driven scenes. It reads the tileset document, expands explicit or implicit trees, and opens point content from point tiles.

Support packages

Lower-level kernels and build-time pieces that show up in workers, converters, and the selection path.

@voxelkloud/wasm-corepublic

Low-level LOD kernels

Raw selector and frustum helpers for workers, SSR, and tests.

npm install @voxelkloud/wasm-core

This module graph is plain arrays and numbers, which keeps it importable where the renderer itself is too heavy.

Support packages,
kept separate on purpose.

Why the low-level bits are split out

The lower-level packages stay independent so workers, converters, and non-DOM code can import only the part they need.

  • @voxelkloud/wasm-core holds the selector kernels used by workers and SSR paths.
  • @voxelkloud/format-las keeps the LAS record decoder shared across format drivers.
  • @voxelkloud/format-single and the converter both depend on that worker model.