diff --git a/src/pcsogs.ts b/src/pcsogs.ts index d86b924..7eb090d 100644 --- a/src/pcsogs.ts +++ b/src/pcsogs.ts @@ -28,74 +28,100 @@ export async function unpackPcSogs( const packedArray = new Uint32Array(maxSplats * 4); const extra: Record = {}; - const means = await Promise.all([ + const meansPromise = Promise.all([ decodeImageRgba(extraFiles[json.means.files[0]]), decodeImageRgba(extraFiles[json.means.files[1]]), - ]); - for (let i = 0; i < numSplats; ++i) { - const i4 = i * 4; - const fx = (means[0][i4 + 0] + (means[1][i4 + 0] << 8)) / 65535; - const fy = (means[0][i4 + 1] + (means[1][i4 + 1] << 8)) / 65535; - const fz = (means[0][i4 + 2] + (means[1][i4 + 2] << 8)) / 65535; - let x = json.means.mins[0] + (json.means.maxs[0] - json.means.mins[0]) * fx; - let y = json.means.mins[1] + (json.means.maxs[1] - json.means.mins[1]) * fy; - let z = json.means.mins[2] + (json.means.maxs[2] - json.means.mins[2]) * fz; - x = Math.sign(x) * (Math.exp(Math.abs(x)) - 1); - y = Math.sign(y) * (Math.exp(Math.abs(y)) - 1); - z = Math.sign(z) * (Math.exp(Math.abs(z)) - 1); - setPackedSplatCenter(packedArray, i, x, y, z); - } - - const scales = await decodeImageRgba(extraFiles[json.scales.files[0]]); - for (let i = 0; i < numSplats; ++i) { - const i4 = i * 4; - const fx = scales[i4 + 0] / 255; - const fy = scales[i4 + 1] / 255; - const fz = scales[i4 + 2] / 255; - const x = - json.scales.mins[0] + (json.scales.maxs[0] - json.scales.mins[0]) * fx; - const y = - json.scales.mins[1] + (json.scales.maxs[1] - json.scales.mins[1]) * fy; - const z = - json.scales.mins[2] + (json.scales.maxs[2] - json.scales.mins[2]) * fz; - setPackedSplatScales(packedArray, i, Math.exp(x), Math.exp(y), Math.exp(z)); - } + ]).then((means) => { + for (let i = 0; i < numSplats; ++i) { + const i4 = i * 4; + const fx = (means[0][i4 + 0] + (means[1][i4 + 0] << 8)) / 65535; + const fy = (means[0][i4 + 1] + (means[1][i4 + 1] << 8)) / 65535; + const fz = (means[0][i4 + 2] + (means[1][i4 + 2] << 8)) / 65535; + let x = + json.means.mins[0] + (json.means.maxs[0] - json.means.mins[0]) * fx; + let y = + json.means.mins[1] + (json.means.maxs[1] - json.means.mins[1]) * fy; + let z = + json.means.mins[2] + (json.means.maxs[2] - json.means.mins[2]) * fz; + x = Math.sign(x) * (Math.exp(Math.abs(x)) - 1); + y = Math.sign(y) * (Math.exp(Math.abs(y)) - 1); + z = Math.sign(z) * (Math.exp(Math.abs(z)) - 1); + setPackedSplatCenter(packedArray, i, x, y, z); + } + }); - const quats = await decodeImageRgba(extraFiles[json.quats.files[0]]); - const SQRT2 = Math.sqrt(2); - for (let i = 0; i < numSplats; ++i) { - const i4 = i * 4; - const r0 = (quats[i4 + 0] / 255 - 0.5) * SQRT2; - const r1 = (quats[i4 + 1] / 255 - 0.5) * SQRT2; - const r2 = (quats[i4 + 2] / 255 - 0.5) * SQRT2; - const rr = Math.sqrt(Math.max(0, 1.0 - r0 * r0 - r1 * r1 - r2 * r2)); - const rOrder = quats[i4 + 3] - 252; - const quatX = rOrder === 0 ? r0 : rOrder === 1 ? rr : r1; - const quatY = rOrder <= 1 ? r1 : rOrder === 2 ? rr : r2; - const quatZ = rOrder <= 2 ? r2 : rr; - const quatW = rOrder === 0 ? rr : r0; - setPackedSplatQuat(packedArray, i, quatX, quatY, quatZ, quatW); - } + const scalesPromise = decodeImageRgba(extraFiles[json.scales.files[0]]).then( + (scales) => { + for (let i = 0; i < numSplats; ++i) { + const i4 = i * 4; + const fx = scales[i4 + 0] / 255; + const fy = scales[i4 + 1] / 255; + const fz = scales[i4 + 2] / 255; + const x = + json.scales.mins[0] + + (json.scales.maxs[0] - json.scales.mins[0]) * fx; + const y = + json.scales.mins[1] + + (json.scales.maxs[1] - json.scales.mins[1]) * fy; + const z = + json.scales.mins[2] + + (json.scales.maxs[2] - json.scales.mins[2]) * fz; + setPackedSplatScales( + packedArray, + i, + Math.exp(x), + Math.exp(y), + Math.exp(z), + ); + } + }, + ); - const sh0 = await decodeImageRgba(extraFiles[json.sh0.files[0]]); - const SH_C0 = 0.28209479177387814; - for (let i = 0; i < numSplats; ++i) { - const i4 = i * 4; - const f0 = sh0[i4 + 0] / 255; - const f1 = sh0[i4 + 1] / 255; - const f2 = sh0[i4 + 2] / 255; - const f3 = sh0[i4 + 3] / 255; - const dc0 = json.sh0.mins[0] + (json.sh0.maxs[0] - json.sh0.mins[0]) * f0; - const dc1 = json.sh0.mins[1] + (json.sh0.maxs[1] - json.sh0.mins[1]) * f1; - const dc2 = json.sh0.mins[2] + (json.sh0.maxs[2] - json.sh0.mins[2]) * f2; - const opa = json.sh0.mins[3] + (json.sh0.maxs[3] - json.sh0.mins[3]) * f3; - const r = SH_C0 * dc0 + 0.5; - const g = SH_C0 * dc1 + 0.5; - const b = SH_C0 * dc2 + 0.5; - const a = 1.0 / (1.0 + Math.exp(-opa)); - setPackedSplatRgba(packedArray, i, r, g, b, a); - } + const quatsPromise = decodeImageRgba(extraFiles[json.quats.files[0]]).then( + (quats) => { + const SQRT2 = Math.sqrt(2); + for (let i = 0; i < numSplats; ++i) { + const i4 = i * 4; + const r0 = (quats[i4 + 0] / 255 - 0.5) * SQRT2; + const r1 = (quats[i4 + 1] / 255 - 0.5) * SQRT2; + const r2 = (quats[i4 + 2] / 255 - 0.5) * SQRT2; + const rr = Math.sqrt(Math.max(0, 1.0 - r0 * r0 - r1 * r1 - r2 * r2)); + const rOrder = quats[i4 + 3] - 252; + const quatX = rOrder === 0 ? r0 : rOrder === 1 ? rr : r1; + const quatY = rOrder <= 1 ? r1 : rOrder === 2 ? rr : r2; + const quatZ = rOrder <= 2 ? r2 : rr; + const quatW = rOrder === 0 ? rr : r0; + setPackedSplatQuat(packedArray, i, quatX, quatY, quatZ, quatW); + } + }, + ); + const sh0Promise = decodeImageRgba(extraFiles[json.sh0.files[0]]).then( + (sh0) => { + const SH_C0 = 0.28209479177387814; + for (let i = 0; i < numSplats; ++i) { + const i4 = i * 4; + const f0 = sh0[i4 + 0] / 255; + const f1 = sh0[i4 + 1] / 255; + const f2 = sh0[i4 + 2] / 255; + const f3 = sh0[i4 + 3] / 255; + const dc0 = + json.sh0.mins[0] + (json.sh0.maxs[0] - json.sh0.mins[0]) * f0; + const dc1 = + json.sh0.mins[1] + (json.sh0.maxs[1] - json.sh0.mins[1]) * f1; + const dc2 = + json.sh0.mins[2] + (json.sh0.maxs[2] - json.sh0.mins[2]) * f2; + const opa = + json.sh0.mins[3] + (json.sh0.maxs[3] - json.sh0.mins[3]) * f3; + const r = SH_C0 * dc0 + 0.5; + const g = SH_C0 * dc1 + 0.5; + const b = SH_C0 * dc2 + 0.5; + const a = 1.0 / (1.0 + Math.exp(-opa)); + setPackedSplatRgba(packedArray, i, r, g, b, a); + } + }, + ); + const promises = [meansPromise, scalesPromise, quatsPromise, sh0Promise]; if (json.shN) { const useSH3 = json.shN.shape[1] >= 48 - 3; const useSH2 = json.shN.shape[1] >= 27 - 3; @@ -109,55 +135,59 @@ export async function unpackPcSogs( const sh2 = new Float32Array(15); const sh3 = new Float32Array(21); - const [centroids, labels] = await Promise.all([ + const shN = json.shN; + const shNPromise = Promise.all([ decodeImage(extraFiles[json.shN.files[0]]), decodeImage(extraFiles[json.shN.files[1]]), - ]); - for (let i = 0; i < numSplats; ++i) { - const i4 = i * 4; - const label = labels.rgba[i4 + 0] + (labels.rgba[i4 + 1] << 8); - const col = (label & 63) * 15; - const row = label >>> 6; - const offset = row * centroids.width + col; + ]).then(([centroids, labels]) => { + for (let i = 0; i < numSplats; ++i) { + const i4 = i * 4; + const label = labels.rgba[i4 + 0] + (labels.rgba[i4 + 1] << 8); + const col = (label & 63) * 15; + const row = label >>> 6; + const offset = row * centroids.width + col; - for (let d = 0; d < 3; ++d) { - if (useSH1) { - for (let k = 0; k < 3; ++k) { - sh1[k * 3 + d] = - json.shN.mins + - ((json.shN.maxs - json.shN.mins) * - centroids.rgba[(offset + k) * 4 + d]) / - 255; + for (let d = 0; d < 3; ++d) { + if (useSH1) { + for (let k = 0; k < 3; ++k) { + sh1[k * 3 + d] = + shN.mins + + ((shN.maxs - shN.mins) * centroids.rgba[(offset + k) * 4 + d]) / + 255; + } } - } - if (useSH2) { - for (let k = 0; k < 5; ++k) { - sh2[k * 3 + d] = - json.shN.mins + - ((json.shN.maxs - json.shN.mins) * - centroids.rgba[(offset + 3 + k) * 4 + d]) / - 255; + if (useSH2) { + for (let k = 0; k < 5; ++k) { + sh2[k * 3 + d] = + shN.mins + + ((shN.maxs - shN.mins) * + centroids.rgba[(offset + 3 + k) * 4 + d]) / + 255; + } } - } - if (useSH3) { - for (let k = 0; k < 7; ++k) { - sh3[k * 3 + d] = - json.shN.mins + - ((json.shN.maxs - json.shN.mins) * - centroids.rgba[(offset + 8 + k) * 4 + d]) / - 255; + if (useSH3) { + for (let k = 0; k < 7; ++k) { + sh3[k * 3 + d] = + shN.mins + + ((shN.maxs - shN.mins) * + centroids.rgba[(offset + 8 + k) * 4 + d]) / + 255; + } } } - } - if (useSH1) encodeSh1Rgb(extra.sh1 as Uint32Array, i, sh1); - if (useSH2) encodeSh2Rgb(extra.sh2 as Uint32Array, i, sh2); - if (useSH3) encodeSh3Rgb(extra.sh3 as Uint32Array, i, sh3); - } + if (useSH1) encodeSh1Rgb(extra.sh1 as Uint32Array, i, sh1); + if (useSH2) encodeSh2Rgb(extra.sh2 as Uint32Array, i, sh2); + if (useSH3) encodeSh3Rgb(extra.sh3 as Uint32Array, i, sh3); + } + }); + promises.push(shNPromise); } + await Promise.all(promises); + return { packedArray, numSplats, extra }; }