Last active
July 25, 2022 16:53
-
-
Save yongjun21/2429c60bd4b608734c85c676702df2ab to your computer and use it in GitHub Desktop.
Fast Octree decoder in JS
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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