LOD selection
The selector spends from pointBudget until projected screen error falls under targetScreenError. When there is room left, minScreenError keeps refinement bounded.
DOCS / TECHNICAL REFERENCE
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.
The selector spends from pointBudget until projected screen error falls under targetScreenError. When there is room left, minScreenError keeps refinement bounded.
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.
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.
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.
`@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.
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.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)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.
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) returnWebGPU 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)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.
Core types, loading, rendering, and thin framework adapters. This is the surface most apps touch first.
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.
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.
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.
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.
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.
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.
Each input format gets its own guide and its own responsibility. The renderer only sees the neutral tree contract.
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.
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.
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.
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.
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.
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.
Lower-level kernels and build-time pieces that show up in workers, converters, and the selection path.
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.
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.