mirror of
https://github.com/storytold/spark.git
synced 2026-10-17 00:12:59 +00:00
PC SOGS decoding from .Zip archive (#100)
* Implement PC SOGS decoding from .zip file archive. Update viewer and editor to accept .zip files. * Restore GL WEBP decoding.
This commit is contained in:
committed by
GitHub
parent
cd40e139d1
commit
4266db3259
+58
-3
@@ -1,4 +1,5 @@
|
||||
import type { PcSogsJson } from "./SplatLoader";
|
||||
import { unzip } from "fflate";
|
||||
import { type PcSogsJson, tryPcSogsZip } from "./SplatLoader";
|
||||
import {
|
||||
computeMaxSplats,
|
||||
encodeSh1Rgb,
|
||||
@@ -11,14 +12,13 @@ import {
|
||||
} from "./utils";
|
||||
|
||||
export async function unpackPcSogs(
|
||||
fileBytes: Uint8Array,
|
||||
json: PcSogsJson,
|
||||
extraFiles: Record<string, ArrayBuffer>,
|
||||
): Promise<{
|
||||
packedArray: Uint32Array;
|
||||
numSplats: number;
|
||||
extra: Record<string, unknown>;
|
||||
}> {
|
||||
const json = JSON.parse(new TextDecoder().decode(fileBytes)) as PcSogsJson;
|
||||
if (json.quats.encoding !== "quaternion_packed") {
|
||||
throw new Error("Unsupported quaternion encoding");
|
||||
}
|
||||
@@ -204,3 +204,58 @@ async function decodeImageRgba(fileBytes: ArrayBuffer) {
|
||||
const { rgba } = await decodeImage(fileBytes);
|
||||
return rgba;
|
||||
}
|
||||
|
||||
export async function unpackPcSogsZip(fileBytes: Uint8Array): Promise<{
|
||||
packedArray: Uint32Array;
|
||||
numSplats: number;
|
||||
extra: Record<string, unknown>;
|
||||
}> {
|
||||
const nameJson = tryPcSogsZip(fileBytes);
|
||||
if (!nameJson) {
|
||||
throw new Error("Invalid PC SOGS zip file");
|
||||
}
|
||||
const { name, json } = nameJson;
|
||||
// Find path prefix, will be -1 if no / or \
|
||||
const lastSlash = name.lastIndexOf("/");
|
||||
const lastBackslash = name.lastIndexOf("\\");
|
||||
const prefix = name.slice(0, Math.max(lastSlash, lastBackslash) + 1);
|
||||
|
||||
const fileMap = new Map<string, string>();
|
||||
const refFiles = [
|
||||
...json.means.files,
|
||||
...json.scales.files,
|
||||
...json.quats.files,
|
||||
...json.sh0.files,
|
||||
...(json.shN?.files ?? []),
|
||||
];
|
||||
for (const file of refFiles) {
|
||||
fileMap.set(prefix + file, file);
|
||||
}
|
||||
|
||||
const unzipped = await new Promise<Record<string, ArrayBuffer>>(
|
||||
(resolve, reject) => {
|
||||
unzip(
|
||||
fileBytes,
|
||||
{
|
||||
filter: ({ name }) => {
|
||||
return fileMap.has(name);
|
||||
},
|
||||
},
|
||||
(err, files) => {
|
||||
if (err) {
|
||||
reject(err);
|
||||
} else {
|
||||
resolve(files);
|
||||
}
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
const extraFiles: Record<string, ArrayBuffer> = {};
|
||||
for (const [full, name] of fileMap.entries()) {
|
||||
extraFiles[name] = unzipped[full];
|
||||
}
|
||||
|
||||
return await unpackPcSogs(json, extraFiles);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user