summaryrefslogtreecommitdiff
path: root/viewer/resources.ts
diff options
context:
space:
mode:
Diffstat (limited to 'viewer/resources.ts')
-rw-r--r--viewer/resources.ts154
1 files changed, 154 insertions, 0 deletions
diff --git a/viewer/resources.ts b/viewer/resources.ts
new file mode 100644
index 0000000..0340e31
--- /dev/null
+++ b/viewer/resources.ts
@@ -0,0 +1,154 @@
+
+export class Resource<T> {
+ constructor(public hash: Uint8Array) { }
+ toString() {
+ return Array.from(this.hash)
+ .map(e => e.toString(16).padStart(2, "0"))
+ .join("")
+ }
+ async download_raw() {
+ const res = await fetch(`http://127.0.0.1:28556/${this.toString()}`)
+ if (!res.ok) throw new Error("aaaa");
+ return await res.bytes()
+ }
+}
+
+export function read_res_table(buffer: Uint8Array, cb: (key: string, value: Uint8Array) => void) {
+ const view = new DataView(buffer.buffer)
+ let p = 0
+ while (p < view.byteLength) {
+ const key_len = view.getInt16(p, true)
+ p += 2
+ const value_len = view.getInt16(p, true)
+ p += 2
+ const key = String.fromCharCode(...buffer.slice(p, p + key_len))
+ p += key_len
+ const value = buffer.slice(p, p + value_len)
+ p += value_len
+ cb(key, value)
+ }
+}
+
+function get_vec3(b: Uint8Array): Vec3 {
+ const k = new DataView(b.buffer)
+ return {
+ x: k.getFloat32(0, true),
+ y: k.getFloat32(4, true),
+ z: k.getFloat32(8, true),
+ }
+}
+function get_aabb(b: Uint8Array): AABB {
+ return {
+ min: get_vec3(b.slice(0, 12)),
+ max: get_vec3(b.slice(12, 24))
+ }
+}
+
+export async function get_respackentry(r: Resource<RespackEntry>): Promise<RespackEntry> {
+ console.log(`load respackentry ${r}`);
+ const buf = await r.download_raw();
+ const o: RespackEntry = {}
+ read_res_table(buf, (key, value) => {
+ switch (key) {
+ case "c_spatial_index":
+ o.c_spatial_index = new Resource(value)
+ break
+ default:
+ }
+ });
+ return o
+}
+export async function get_spatialindex(r: Resource<SpatialIndex>): Promise<SpatialIndex> {
+ // console.log(`load spatialindex ${r}`);
+ const buf = await r.download_raw();
+ const o: SpatialIndex = { child: [] }
+ read_res_table(buf, (key, value) => {
+ switch (key) {
+ case "prefab":
+ o.prefab = new Resource(value)
+ break
+ case "child":
+ o.child.push([
+ get_aabb(value.slice(0, 24)),
+ new Resource(value.slice(24, 56))
+ ])
+ break
+ default:
+ }
+ });
+ return o
+}
+export async function get_prefab(r: Resource<Prefab>): Promise<Prefab> {
+ console.log(`load prefab ${r}`);
+ const buf = await r.download_raw();
+ const o: Prefab = { graphics: [] }
+ read_res_table(buf, (key, value) => {
+ switch (key) {
+ case "graphics":
+ o.graphics.push([undefined as unknown as Affine3, new Resource(value.slice(48, 80))])
+ break
+ default:
+ }
+ });
+ return o
+}
+export async function get_graphics_part(r: Resource<GraphicsPart>): Promise<GraphicsPart> {
+ console.log(`load graphics ${r}`);
+ return new GraphicsPart(await r.download_raw())
+}
+
+export interface Vec3 { x: number, y: number, z: number }
+export interface AABB { min: Vec3, max: Vec3 }
+export interface Mat3 { x: Vec3, y: Vec3, z: Vec3 }
+export interface Affine3 { basis: Mat3, origin: Vec3 }
+
+export interface SpatialIndex {
+ level?: number
+ prefab?: Resource<undefined>
+ child: [AABB, Resource<undefined>][]
+}
+export interface RespackEntry {
+ c_spatial_index?: Resource<SpatialIndex>
+}
+export interface Prefab {
+ graphics: [Affine3, Resource<GraphicsPart>][]
+}
+export class GraphicsPart {
+ commands: GraphicsCommand[] | undefined
+ constructor(public buffer: Uint8Array) { }
+
+ read(): GraphicsCommand[] {
+ if (this.commands) return this.commands
+
+ const out: GraphicsCommand[] = []
+ let p = 0
+ while (p < this.buffer.length) {
+ const step = this.buffer[p + 0]
+ const kind = this.buffer[p + 1]
+ p += 2
+ if (kind == 0) {
+ if (step == 0) out.push({ no_fill: true })
+ else if (step == 1) out.push({ fill: this.buffer[p + 0] })
+ else throw new Error("bbb");
+ } else if (kind == 1) {
+ if (step == 0) out.push({ no_stroke: true })
+ else if (step == 1) out.push({ stroke: this.buffer[p + 0] })
+ else throw new Error("ccc");
+ }
+ else throw new Error("aaa");
+
+ p += step
+ }
+
+ this.commands = out
+ return out
+ }
+}
+
+export interface GraphicsCommand {
+ no_fill?: true,
+ fill?: number,
+ no_stroke?: true
+ stroke?: number
+ point?: Vec3
+} \ No newline at end of file