Skip to content

Instantly share code, notes, and snippets.

@yongjun21
Last active July 25, 2022 16:53
Show Gist options
  • Save yongjun21/2429c60bd4b608734c85c676702df2ab to your computer and use it in GitHub Desktop.
Save yongjun21/2429c60bd4b608734c85c676702df2ab to your computer and use it in GitHub Desktop.
Fast Octree decoder in JS
const MAX_LEVEL = 30;
const STACK = new Float32Array((7 * MAX_LEVEL + 1) * 4);
interface OctreeHeader {
version: number;
precision: number;
maxLevel: number;
nodeCounts: number[];
leafCount: number;
dataStartOffset: number;
dataEndOffset: number;
}
export function decodeOctree(encoded: ArrayBuffer) {
const meta: OctreeHeader = decodeOctreeHeader(encoded);
const data = new Uint8Array(
encoded,
meta.dataStartOffset,
meta.dataEndOffset - meta.dataStartOffset
);
const startIndexes = new Uint32Array(meta.nodeCounts.length);
for (let i = 1; i < meta.nodeCounts.length; i++) {
startIndexes[i] = startIndexes[i - 1] + meta.nodeCounts[i - 1];
}
const halfPrecision = meta.precision / 2;
const decoded = new Float32Array(meta.leafCount * 3);
const readIndexes = new Uint32Array(startIndexes);
const gridSize = new Float32Array(startIndexes.length);
for (let i = meta.maxLevel, size = meta.precision; i >= 0; i--, size *= 2) {
gridSize[i] = size;
}
let writeIndex = 0;
let pointer = 0;
STACK[0] = 0;
STACK[1] = halfPrecision;
STACK[2] = halfPrecision;
STACK[3] = halfPrecision;
while (pointer >= 0) {
const level = STACK[pointer];
const x0 = STACK[pointer + 1];
const y0 = STACK[pointer + 2];
const z0 = STACK[pointer + 3];
pointer -= 4;
const value = data[readIndexes[level]++];
const delta = gridSize[level] / 2;
for (let i = 7, bitValue = 128; i >= 0; i--, bitValue >>= 1) {
if (value & bitValue) {
const x = x0 + (i & 1 ? 1 : -1) * delta;
const y = y0 + (i & 2 ? 1 : -1) * delta;
const z = z0 + (i & 4 ? 1 : -1) * delta;
if (level < meta.maxLevel) {
pointer += 4;
STACK[pointer] = level + 1;
STACK[pointer + 1] = x;
STACK[pointer + 2] = y;
STACK[pointer + 3] = z;
} else {
decoded[writeIndex++] = x;
decoded[writeIndex++] = y;
decoded[writeIndex++] = z;
}
}
}
}
return decoded;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment