@gmvjs/xray-v1 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/README.md +35 -29
  2. package/dist/db.d.ts +2 -2
  3. package/dist/db.js.map +1 -1
  4. package/dist/details.d.ts +4 -4
  5. package/dist/details.js.map +1 -1
  6. package/dist/export.d.ts +13 -13
  7. package/dist/export.js.map +1 -1
  8. package/dist/games/cop.js.map +1 -1
  9. package/dist/games/cs.js.map +1 -1
  10. package/dist/games/sdk.d.ts +1 -1
  11. package/dist/games/sdk.js.map +1 -1
  12. package/dist/games/soc.d.ts +1 -1
  13. package/dist/games/soc.js.map +1 -1
  14. package/dist/i18n.js.map +1 -1
  15. package/dist/index.d.ts +1 -1
  16. package/dist/index.js +8 -8
  17. package/dist/index.js.map +1 -1
  18. package/dist/level.d.ts +5 -5
  19. package/dist/level.js.map +1 -1
  20. package/dist/load.d.ts +1 -1
  21. package/dist/load.js.map +1 -1
  22. package/dist/lzhuf.d.ts +1 -1
  23. package/dist/lzhuf.js.map +1 -1
  24. package/dist/motion.d.ts +6 -6
  25. package/dist/motion.js.map +1 -1
  26. package/dist/object.d.ts +12 -12
  27. package/dist/object.js.map +1 -1
  28. package/dist/ogf.d.ts +6 -6
  29. package/dist/ogf.js.map +1 -1
  30. package/dist/scene.d.ts +6 -6
  31. package/dist/scene.js.map +1 -1
  32. package/dist/skeleton.d.ts +4 -4
  33. package/dist/skeleton.js +4 -4
  34. package/dist/skeleton.js.map +1 -1
  35. package/dist/smotion.d.ts +5 -5
  36. package/dist/smotion.js.map +1 -1
  37. package/dist/soc-key.d.ts +6 -6
  38. package/dist/soc-key.js.map +1 -1
  39. package/dist/thm.d.ts +1 -1
  40. package/dist/thm.js.map +1 -1
  41. package/dist/write-object.d.ts +7 -7
  42. package/dist/write-object.js +1 -1
  43. package/dist/write-object.js.map +1 -1
  44. package/dist/write-omf.d.ts +9 -9
  45. package/dist/write-scene.d.ts +6 -6
  46. package/dist/write-scene.js.map +1 -1
  47. package/package.json +3 -3
@@ -1 +1 @@
1
- {"version":3,"file":"object.js","sources":["../src/object.ts"],"sourcesContent":["// Исходный объект X-Ray SDK (.object, «EOBJ»): меши с вершинами, гранями, UV-картами (vmap) и группами сглаживания,\n// поверхности (шейдер движка, шейдер компилятора, игровой материал, текстура). Координаты X-Ray: левосторонние, Y вверх.\nexport const EOBJ = {\n MAIN: 0x7777, VERSION: 0x0900, FLAGS: 0x0903, SURFACES: 0x0905, SURFACES2: 0x0906, SURFACES3: 0x0907, MESHES: 0x0910,\n USERDATA: 0x0912, SMOTIONS: 0x0916, BONEPARTS: 0x0919, BONES: 0x0921, REVISION: 0x0922, BONEPARTS2: 0x0923, LOD_REF: 0x0925, SMOTION_REFS: 0x0926,\n} as const;\n/** Чанки кости (BONES2): версия, имя/родитель/весовая карта, bind-поза (позиция, углы setXYZi, длина). */\nconst BONE = { DEF: 0x0002, BIND_POSE: 0x0003 } as const;\nexport const EMESH = {\n VERSION: 0x1000, NAME: 0x1001, FLAGS: 0x1002, BBOX: 0x1004, VERTS: 0x1005, FACES: 0x1006, VMREFS: 0x1008, SFACE: 0x1009,\n OPTIONS: 0x1010, VMAPS1: 0x1011, VMAPS2: 0x1012, SG: 0x1013,\n} as const;\n\n/** Флаги объекта (EditObject): динамический, прогрессивный, LOD, HOM, многократное использование, глушитель звука, HQ-экспорт. */\nexport const EOBJ_FLAG = { DYNAMIC: 1, PROGRESSIVE: 2, USING_LOD: 4, HOM: 8, MULTIPLE_USAGE: 16, SOUND_OCCLUDER: 32, HQ_EXPORT: 64 } as const;\n\nexport interface XrSurface {\n name: string; eshader: string; cshader: string; gamemtl: string; texture: string; vmap: string; flags: number; fvf: number;\n}\nexport interface XrVmap {\n name: string; dim: number; poly: boolean; type: number;\n /** size × dim значений. */\n data: Float32Array;\n vertices: Uint32Array;\n /** Для «поли»-карт: номер грани каждой записи. */\n faces: Uint32Array | null;\n}\nexport interface XrEditMesh {\n name: string; flags: number; options: [number, number];\n points: Float32Array;\n /** По 3 угла на грань: [точка, vmref]. */\n faces: Uint32Array;\n sg: Uint32Array | null;\n /** vmref -> список [номер vmap, индекс в vmap]. */\n vmrefs: Array<Array<[number, number]>>;\n /** Поверхность -> номера граней. */\n sfaces: Array<{ surface: string; faces: Uint32Array }>;\n vmaps: XrVmap[];\n}\nexport interface XrObject {\n version: number; flags: number; userdata: string; lodRef: string;\n surfaces: XrSurface[]; meshes: XrEditMesh[];\n revision: { owner: string; created: number; modifier: string; modified: number } | null;\n /** Чанки верхнего уровня, которые читатель не разбирает (кости, анимации…): сохраняются как есть. */\n extra: Array<{ id: number; data: Uint8Array }>;\n}\n\n/** Символ Windows-1251 (строки SDK: имена текстур и материалов бывают русскими). */\nconst cp1251 = (c: number) => String.fromCharCode(c < 128 ? c : c >= 0xc0 ? c + 0x350 : c === 0xa8 ? 0x401 : c === 0xb8 ? 0x451 : c);\n\nclass R {\n readonly dv: DataView; readonly u8: Uint8Array;\n constructor(readonly buf: ArrayBuffer, public pos: number, public end: number) { this.dv = new DataView(buf); this.u8 = new Uint8Array(buf); }\n b() { return this.dv.getUint8(this.pos++); }\n w() { const v = this.dv.getUint16(this.pos, true); this.pos += 2; return v; }\n d() { const v = this.dv.getUint32(this.pos, true); this.pos += 4; return v; }\n f() { const v = this.dv.getFloat32(this.pos, true); this.pos += 4; return v; }\n sz() { let s = ''; while (this.pos < this.end) { const c = this.u8[this.pos++]!; if (!c) break; s += cp1251(c); } return s; }\n}\n\n/** Чанки [id u32, размер u32] в диапазоне. */\nexport function chunksOf(buf: ArrayBuffer, start: number, end: number): Array<{ id: number; start: number; end: number }> {\n const dv = new DataView(buf), out: Array<{ id: number; start: number; end: number }> = [];\n let p = start;\n while (p + 8 <= end) {\n const id = dv.getUint32(p, true), size = dv.getUint32(p + 4, true);\n if (p + 8 + size > end) throw new Error(`.object: чанк 0x${id.toString(16)} выходит за границы`);\n out.push({ id, start: p + 8, end: p + 8 + size });\n p += 8 + size;\n }\n return out;\n}\n\nfunction parseMesh(buf: ArrayBuffer, start: number, end: number): XrEditMesh {\n const m: XrEditMesh = { name: '', flags: 0, options: [0, 0], points: new Float32Array(0), faces: new Uint32Array(0), sg: null, vmrefs: [], sfaces: [], vmaps: [] };\n for (const c of chunksOf(buf, start, end)) {\n const r = new R(buf, c.start, c.end);\n switch (c.id) {\n case EMESH.NAME: m.name = r.sz(); break;\n case EMESH.FLAGS: m.flags = r.b(); break;\n case EMESH.OPTIONS: m.options = [r.d(), r.d()]; break;\n case EMESH.VERTS: { const n = r.d(); m.points = new Float32Array(n * 3); for (let k = 0; k < n * 3; k++) m.points[k] = r.f(); break; }\n case EMESH.FACES: { const n = r.d(); m.faces = new Uint32Array(n * 6); for (let k = 0; k < n * 6; k++) m.faces[k] = r.d(); break; }\n case EMESH.SG: { const n = (c.end - c.start) >> 2; m.sg = new Uint32Array(n); for (let k = 0; k < n; k++) m.sg[k] = r.d(); break; }\n case EMESH.VMREFS: {\n const n = r.d();\n for (let k = 0; k < n; k++) { const cnt = r.b(), ref: Array<[number, number]> = []; for (let i = 0; i < cnt; i++) ref.push([r.d(), r.d()]); m.vmrefs.push(ref); }\n break;\n }\n case EMESH.SFACE: {\n const n = r.w();\n for (let k = 0; k < n; k++) { const surface = r.sz(), cnt = r.d(), faces = new Uint32Array(cnt); for (let i = 0; i < cnt; i++) faces[i] = r.d(); m.sfaces.push({ surface, faces }); }\n break;\n }\n case EMESH.VMAPS2: case EMESH.VMAPS1: {\n // старые объекты (SDK ТЧ ранних версий): в VMAPS1 нет списка вершин — карта индексируется только через vmref\n const read = (withVerts: boolean) => {\n const q = new R(buf, c.start, c.end), n = q.d(), list: XrVmap[] = [];\n for (let k = 0; k < n; k++) {\n const name = q.sz(), dim = q.b(), poly = c.id === EMESH.VMAPS2 ? q.b() !== 0 : false, type = q.b(), size = q.d();\n if (q.pos + size * dim * 4 > c.end) return null;\n const data = new Float32Array(size * dim);\n for (let i = 0; i < size * dim; i++) data[i] = q.f();\n const vertices = new Uint32Array(withVerts ? size : 0);\n if (withVerts) { if (q.pos + size * 4 > c.end) return null; for (let i = 0; i < size; i++) vertices[i] = q.d(); }\n let faces: Uint32Array | null = null;\n if (poly) { if (q.pos + size * 4 > c.end) return null; faces = new Uint32Array(size); for (let i = 0; i < size; i++) faces[i] = q.d(); }\n list.push({ name, dim, poly, type, data, vertices, faces });\n }\n return q.pos === c.end ? list : null;\n };\n const list = read(true) ?? (c.id === EMESH.VMAPS1 ? read(false) : null);\n if (!list) throw new Error(`.object: чанк меша 0x${c.id.toString(16)} разобран неверно`);\n m.vmaps.push(...list);\n r.pos = c.end;\n break;\n }\n }\n if (r.pos > c.end) throw new Error(`.object: чанк меша 0x${c.id.toString(16)} разобран неверно`);\n }\n return m;\n}\n\nexport function parseObject(buf: ArrayBuffer): XrObject {\n const top = chunksOf(buf, 0, buf.byteLength).find((c) => c.id === EOBJ.MAIN);\n if (!top) throw new Error('Не объект X-Ray SDK (.object): нет чанка 0x7777');\n const o: XrObject = { version: 0, flags: 0, userdata: '', lodRef: '', surfaces: [], meshes: [], revision: null, extra: [] };\n for (const c of chunksOf(buf, top.start, top.end)) {\n const r = new R(buf, c.start, c.end);\n switch (c.id) {\n case EOBJ.VERSION: o.version = r.w(); break;\n case EOBJ.FLAGS: o.flags = r.d(); break;\n case EOBJ.USERDATA: o.userdata = r.sz(); break;\n case EOBJ.LOD_REF: o.lodRef = r.sz(); break;\n case EOBJ.MESHES: for (const mc of chunksOf(buf, c.start, c.end)) o.meshes.push(parseMesh(buf, mc.start, mc.end)); break;\n case EOBJ.SURFACES3: case EOBJ.SURFACES2: {\n const n = r.d();\n for (let k = 0; k < n; k++) {\n const s: XrSurface = { name: r.sz(), eshader: r.sz(), cshader: r.sz(), gamemtl: c.id === EOBJ.SURFACES3 ? r.sz() : 'default', texture: r.sz(), vmap: r.sz(), flags: r.d(), fvf: r.d(), };\n r.d(); // число наборов UV\n o.surfaces.push(s);\n }\n break;\n }\n case EOBJ.REVISION: o.revision = { owner: r.sz(), created: r.d(), modifier: r.sz(), modified: r.d() }; break;\n default: o.extra.push({ id: c.id, data: new Uint8Array(buf.slice(c.start, c.end)) });\n }\n }\n if (o.version !== 0x10) throw new Error(`.object версии 0x${o.version.toString(16)} не поддерживается (нужна 0x10, SDK ТЧ/ЧН/ЗП)`);\n return o;\n}\n\n/** Меш для показа: по грани на угол — точка + UV из vmref; нормали по группам сглаживания. */\nexport interface XrObjectMesh { name: string; surface: XrSurface | undefined; pos: Float32Array; nor: Float32Array; uv: Float32Array; indices: Uint32Array; bone?: Float32Array; weight?: Float32Array }\n\nexport function objectMeshes(o: XrObject, smoothing: 'auto' | 'cop' | 'soc' = 'auto', boneOfMap?: Map<string, number>): XrObjectMesh[] {\n const out: XrObjectMesh[] = [];\n for (const m of o.meshes) {\n const nf = m.faces.length / 6, P = m.points;\n // нормали граней\n const fn = new Float32Array(nf * 3);\n for (let f = 0; f < nf; f++) {\n const a = m.faces[f * 6]! * 3, b = m.faces[f * 6 + 2]! * 3, c = m.faces[f * 6 + 4]! * 3;\n const ux = P[b]! - P[a]!, uy = P[b + 1]! - P[a + 1]!, uz = P[b + 2]! - P[a + 2]!, vx = P[c]! - P[a]!, vy = P[c + 1]! - P[a + 1]!, vz = P[c + 2]! - P[a + 2]!;\n // нормаль = (b − a) × (c − a): так же, как у скомпилированного уровня (сверено на labx8: обход граней сохраняется)\n let nx = uy * vz - uz * vy, ny = uz * vx - ux * vz, nz = ux * vy - uy * vx;\n const l = Math.hypot(nx, ny, nz) || 1; nx /= l; ny /= l; nz /= l;\n fn[f * 3] = nx; fn[f * 3 + 1] = ny; fn[f * 3 + 2] = nz;\n }\n // грани вокруг точки\n const around: number[][] = Array.from({ length: P.length / 3 }, () => []);\n for (let f = 0; f < nf; f++) for (let k = 0; k < 3; k++) around[m.faces[f * 6 + k * 2]!]!.push(f);\n // ЗП (SDK 0.7): в sg по биту на ребро грани (бит k — ребро k→k+1 жёсткое); ТЧ/ЧН: маска групп сглаживания.\n // Флага формата в файле нет: значения меньше 8 у всех граней считаем рёбрами (как выяснено на объектах SDK 0.7).\n const sgv = m.sg, copEdges = smoothing === 'cop' || (smoothing === 'auto' && !!sgv && sgv.every((v) => v < 8));\n const hard = new Set<string>();\n if (copEdges) for (let f = 0; f < nf; f++) for (let k = 0; k < 3; k++) if ((sgv![f]! >> k) & 1) {\n const a = m.faces[f * 6 + k * 2]!, b = m.faces[f * 6 + ((k + 1) % 3) * 2]!;\n hard.add(a < b ? `${a}_${b}` : `${b}_${a}`);\n }\n const others = (f: number, pt: number) => { const r: number[] = []; for (let k = 0; k < 3; k++) { const q = m.faces[f * 6 + k * 2]!; if (q !== pt) r.push(q); } return r; };\n /** Грани, нормали которых сглаживаются с гранью f в точке pt. */\n const smoothFan = (f: number, pt: number): number[] => {\n if (!sgv) return around[pt]!;\n if (!copEdges) { const g0 = sgv[f]!; return g0 ? around[pt]!.filter((g) => g === f || (sgv[g]! & g0) !== 0) : [f]; }\n const seen = new Set([f]), stack = [f];\n while (stack.length) {\n const g = stack.pop()!;\n for (const q of others(g, pt)) {\n if (hard.has(pt < q ? `${pt}_${q}` : `${q}_${pt}`)) continue;\n for (const h of around[pt]!) if (!seen.has(h) && others(h, pt).includes(q)) { seen.add(h); stack.push(h); }\n }\n }\n return [...seen];\n };\n const uvOf = (vmref: number): [number, number] => {\n const ref = m.vmrefs[vmref];\n if (!ref) return [0, 0];\n for (const [vm, idx] of ref) { const map = m.vmaps[vm]; if (map && map.type === 0 && map.dim === 2) return [map.data[idx * 2]!, map.data[idx * 2 + 1]!]; }\n return [0, 0];\n };\n for (const sf of m.sfaces.length ? m.sfaces : [{ surface: o.surfaces[0]?.name ?? '', faces: Uint32Array.from({ length: nf }, (_, i) => i) }]) {\n const pos: number[] = [], nor: number[] = [], uv: number[] = [], idx: number[] = [], key = new Map<string, number>(), bone: number[] = [], weight: number[] = [];\n for (const f of sf.faces) {\n for (let k = 0; k < 3; k++) {\n const pt = m.faces[f * 6 + k * 2]!, vr = m.faces[f * 6 + k * 2 + 1]!;\n let nx = 0, ny = 0, nz = 0;\n for (const g of smoothFan(f, pt)) { nx += fn[g * 3]!; ny += fn[g * 3 + 1]!; nz += fn[g * 3 + 2]!; }\n const l = Math.hypot(nx, ny, nz) || 1;\n nx /= l; ny /= l; nz /= l;\n const [u, v] = uvOf(vr), k2 = `${pt}|${u}|${v}|${nx.toFixed(3)}|${ny.toFixed(3)}|${nz.toFixed(3)}`;\n let vi = key.get(k2);\n if (vi === undefined) {\n vi = pos.length / 3; key.set(k2, vi);\n pos.push(P[pt * 3]!, P[pt * 3 + 1]!, P[pt * 3 + 2]!); nor.push(nx, ny, nz); uv.push(u, v);\n if (boneOfMap) { const [bi, w] = cornerWeights(m, vr, boneOfMap); bone.push(...bi); weight.push(...w); }\n }\n idx.push(vi);\n }\n }\n if (idx.length) out.push({ name: `${m.name}: ${sf.surface}`, surface: o.surfaces.find((s) => s.name === sf.surface), pos: Float32Array.from(pos), nor: Float32Array.from(nor), uv: Float32Array.from(uv), indices: Uint32Array.from(idx), ...(boneOfMap ? { bone: Float32Array.from(bone), weight: Float32Array.from(weight) } : {}) });\n }\n }\n return out;\n}\n\n/** Кость объекта: имя, родитель (номер), имя весовой карты вершин, bind-поза. */\nexport interface XrObjectBone { name: string; parent: number; wmap: string; rot: number[]; pos: number[] }\nexport interface XrObjectSkeleton { bones: XrObjectBone[]; parts: Array<{ name: string; bones: string[] }>; motions: Uint8Array | null; motionRefs: string[] }\n\n/** Кости (0x0921), части тела (0x0923/0x0919), анимации (0x0916, как .skls) и ссылки на .omf (0x0926) из чанков объекта. */\nexport function objectSkeleton(o: XrObject): XrObjectSkeleton | null {\n const get = (id: number) => o.extra.find((c) => c.id === id)?.data;\n const bc = get(EOBJ.BONES);\n if (!bc) return null;\n const buf = bc.buffer.slice(bc.byteOffset, bc.byteOffset + bc.byteLength) as ArrayBuffer;\n const raw: Array<{ name: string; parent: string; wmap: string; rot: number[]; pos: number[] }> = [];\n for (const b of chunksOf(buf, 0, buf.byteLength)) {\n const sub = chunksOf(buf, b.start, b.end), def = sub.find((c) => c.id === BONE.DEF), bp = sub.find((c) => c.id === BONE.BIND_POSE);\n if (!def) continue;\n const r = new R(buf, def.start, def.end), name = r.sz(), parent = r.sz(), wmap = r.sz();\n let pos = [0, 0, 0], rot = [0, 0, 0];\n if (bp && bp.end - bp.start >= 24) { const q = new R(buf, bp.start, bp.end); pos = [q.f(), q.f(), q.f()]; rot = [q.f(), q.f(), q.f()]; }\n raw.push({ name, parent, wmap, rot, pos });\n }\n if (!raw.length) return null;\n const at = new Map(raw.map((b, i) => [b.name.toLowerCase(), i]));\n const bones = raw.map((b) => ({ name: b.name, parent: b.parent ? at.get(b.parent.toLowerCase()) ?? -1 : -1, wmap: b.wmap || b.name, rot: b.rot, pos: b.pos }));\n const parts: XrObjectSkeleton['parts'] = [];\n const pc = get(EOBJ.BONEPARTS2);\n if (pc) {\n try {\n const pb = pc.buffer.slice(pc.byteOffset, pc.byteOffset + pc.byteLength) as ArrayBuffer, r = new R(pb, 0, pb.byteLength), n = r.d();\n for (let i = 0; i < n; i++) { const name = r.sz(), k = r.d(), list: string[] = []; for (let j = 0; j < k; j++) list.push(r.sz()); parts.push({ name, bones: list }); }\n } catch { parts.length = 0; }\n }\n const motionRefs: string[] = [];\n const rc = get(EOBJ.SMOTION_REFS);\n if (rc) {\n const rb = rc.buffer.slice(rc.byteOffset, rc.byteOffset + rc.byteLength) as ArrayBuffer, r = new R(rb, 0, rb.byteLength);\n // ЗП: u32 число + строки; старые SDK — одна строка через запятую\n const n = rb.byteLength >= 4 ? new DataView(rb).getUint32(0, true) : 0;\n if (n > 0 && n < 1000) { r.d(); for (let i = 0; i < n && r.pos < r.end; i++) motionRefs.push(r.sz()); }\n else motionRefs.push(...r.sz().split(',').map((x) => x.trim()).filter(Boolean));\n }\n return { bones, parts, motions: get(EOBJ.SMOTIONS) ?? null, motionRefs };\n}\n\n/** Веса вершин угла грани (vmref): до 4 костей по весовым картам (vmap типа 1), нормированные. */\nexport function cornerWeights(m: XrEditMesh, vmref: number, boneOfMap: Map<string, number>): [number[], number[]] {\n const list: Array<[number, number]> = [];\n for (const [vm, idx] of m.vmrefs[vmref] ?? []) {\n const map = m.vmaps[vm];\n if (!map || map.type !== 1) continue;\n const b = boneOfMap.get(map.name.toLowerCase());\n if (b !== undefined) list.push([b, map.data[idx]!]);\n }\n if (!list.length) return [[0, 0, 0, 0], [1, 0, 0, 0]];\n list.sort((a, b) => b[1] - a[1]);\n const top = list.slice(0, 4), sum = top.reduce((a, x) => a + x[1], 0) || 1;\n const bi = [0, 0, 0, 0], w = [0, 0, 0, 0];\n top.forEach(([b, x], i) => { bi[i] = b; w[i] = x / sum; });\n if (top.length === 1) w[0] = 1;\n return [bi, w];\n}\n"],"names":["list"],"mappings":"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"}
1
+ {"version":3,"file":"object.js","sources":["../src/object.ts"],"sourcesContent":["// X-Ray SDK source object (.object, \"EOBJ\"): meshes with vertices, faces, UV maps (vmap) and smoothing groups,\n// surfaces (engine shader, compiler shader, game material, texture). X-Ray coordinates: left-handed, Y up.\nexport const EOBJ = {\n MAIN: 0x7777, VERSION: 0x0900, FLAGS: 0x0903, SURFACES: 0x0905, SURFACES2: 0x0906, SURFACES3: 0x0907, MESHES: 0x0910,\n USERDATA: 0x0912, SMOTIONS: 0x0916, BONEPARTS: 0x0919, BONES: 0x0921, REVISION: 0x0922, BONEPARTS2: 0x0923, LOD_REF: 0x0925, SMOTION_REFS: 0x0926,\n} as const;\n/** Bone chunks (BONES2): version, name/parent/weight map, bind pose (position, setXYZi angles, length). */\nconst BONE = { DEF: 0x0002, BIND_POSE: 0x0003 } as const;\nexport const EMESH = {\n VERSION: 0x1000, NAME: 0x1001, FLAGS: 0x1002, BBOX: 0x1004, VERTS: 0x1005, FACES: 0x1006, VMREFS: 0x1008, SFACE: 0x1009,\n OPTIONS: 0x1010, VMAPS1: 0x1011, VMAPS2: 0x1012, SG: 0x1013,\n} as const;\n\n/** Object flags (EditObject): dynamic, progressive, LOD, HOM, multiple usage, sound occluder, HQ export. */\nexport const EOBJ_FLAG = { DYNAMIC: 1, PROGRESSIVE: 2, USING_LOD: 4, HOM: 8, MULTIPLE_USAGE: 16, SOUND_OCCLUDER: 32, HQ_EXPORT: 64 } as const;\n\nexport interface XrSurface {\n name: string; eshader: string; cshader: string; gamemtl: string; texture: string; vmap: string; flags: number; fvf: number;\n}\nexport interface XrVmap {\n name: string; dim: number; poly: boolean; type: number;\n /** size × dim values. */\n data: Float32Array;\n vertices: Uint32Array;\n /** For \"poly\" maps: the face number of every record. */\n faces: Uint32Array | null;\n}\nexport interface XrEditMesh {\n name: string; flags: number; options: [number, number];\n points: Float32Array;\n /** 3 corners per face: [point, vmref]. */\n faces: Uint32Array;\n sg: Uint32Array | null;\n /** vmref -> a list of [vmap number, index in the vmap]. */\n vmrefs: Array<Array<[number, number]>>;\n /** Surface -> face numbers. */\n sfaces: Array<{ surface: string; faces: Uint32Array }>;\n vmaps: XrVmap[];\n}\nexport interface XrObject {\n version: number; flags: number; userdata: string; lodRef: string;\n surfaces: XrSurface[]; meshes: XrEditMesh[];\n revision: { owner: string; created: number; modifier: string; modified: number } | null;\n /** Top-level chunks the reader does not parse (bones, animations…): kept as is. */\n extra: Array<{ id: number; data: Uint8Array }>;\n}\n\n/** A Windows-1251 character (SDK strings: texture and material names may be in Russian). */\nconst cp1251 = (c: number) => String.fromCharCode(c < 128 ? c : c >= 0xc0 ? c + 0x350 : c === 0xa8 ? 0x401 : c === 0xb8 ? 0x451 : c);\n\nclass R {\n readonly dv: DataView; readonly u8: Uint8Array;\n constructor(readonly buf: ArrayBuffer, public pos: number, public end: number) { this.dv = new DataView(buf); this.u8 = new Uint8Array(buf); }\n b() { return this.dv.getUint8(this.pos++); }\n w() { const v = this.dv.getUint16(this.pos, true); this.pos += 2; return v; }\n d() { const v = this.dv.getUint32(this.pos, true); this.pos += 4; return v; }\n f() { const v = this.dv.getFloat32(this.pos, true); this.pos += 4; return v; }\n sz() { let s = ''; while (this.pos < this.end) { const c = this.u8[this.pos++]!; if (!c) break; s += cp1251(c); } return s; }\n}\n\n/** Chunks [id u32, size u32] within a range. */\nexport function chunksOf(buf: ArrayBuffer, start: number, end: number): Array<{ id: number; start: number; end: number }> {\n const dv = new DataView(buf), out: Array<{ id: number; start: number; end: number }> = [];\n let p = start;\n while (p + 8 <= end) {\n const id = dv.getUint32(p, true), size = dv.getUint32(p + 4, true);\n if (p + 8 + size > end) throw new Error(`.object: чанк 0x${id.toString(16)} выходит за границы`);\n out.push({ id, start: p + 8, end: p + 8 + size });\n p += 8 + size;\n }\n return out;\n}\n\nfunction parseMesh(buf: ArrayBuffer, start: number, end: number): XrEditMesh {\n const m: XrEditMesh = { name: '', flags: 0, options: [0, 0], points: new Float32Array(0), faces: new Uint32Array(0), sg: null, vmrefs: [], sfaces: [], vmaps: [] };\n for (const c of chunksOf(buf, start, end)) {\n const r = new R(buf, c.start, c.end);\n switch (c.id) {\n case EMESH.NAME: m.name = r.sz(); break;\n case EMESH.FLAGS: m.flags = r.b(); break;\n case EMESH.OPTIONS: m.options = [r.d(), r.d()]; break;\n case EMESH.VERTS: { const n = r.d(); m.points = new Float32Array(n * 3); for (let k = 0; k < n * 3; k++) m.points[k] = r.f(); break; }\n case EMESH.FACES: { const n = r.d(); m.faces = new Uint32Array(n * 6); for (let k = 0; k < n * 6; k++) m.faces[k] = r.d(); break; }\n case EMESH.SG: { const n = (c.end - c.start) >> 2; m.sg = new Uint32Array(n); for (let k = 0; k < n; k++) m.sg[k] = r.d(); break; }\n case EMESH.VMREFS: {\n const n = r.d();\n for (let k = 0; k < n; k++) { const cnt = r.b(), ref: Array<[number, number]> = []; for (let i = 0; i < cnt; i++) ref.push([r.d(), r.d()]); m.vmrefs.push(ref); }\n break;\n }\n case EMESH.SFACE: {\n const n = r.w();\n for (let k = 0; k < n; k++) { const surface = r.sz(), cnt = r.d(), faces = new Uint32Array(cnt); for (let i = 0; i < cnt; i++) faces[i] = r.d(); m.sfaces.push({ surface, faces }); }\n break;\n }\n case EMESH.VMAPS2: case EMESH.VMAPS1: {\n // old objects (early SoC SDK): VMAPS1 has no vertex list, the map is indexed only through vmref\n const read = (withVerts: boolean) => {\n const q = new R(buf, c.start, c.end), n = q.d(), list: XrVmap[] = [];\n for (let k = 0; k < n; k++) {\n const name = q.sz(), dim = q.b(), poly = c.id === EMESH.VMAPS2 ? q.b() !== 0 : false, type = q.b(), size = q.d();\n if (q.pos + size * dim * 4 > c.end) return null;\n const data = new Float32Array(size * dim);\n for (let i = 0; i < size * dim; i++) data[i] = q.f();\n const vertices = new Uint32Array(withVerts ? size : 0);\n if (withVerts) { if (q.pos + size * 4 > c.end) return null; for (let i = 0; i < size; i++) vertices[i] = q.d(); }\n let faces: Uint32Array | null = null;\n if (poly) { if (q.pos + size * 4 > c.end) return null; faces = new Uint32Array(size); for (let i = 0; i < size; i++) faces[i] = q.d(); }\n list.push({ name, dim, poly, type, data, vertices, faces });\n }\n return q.pos === c.end ? list : null;\n };\n const list = read(true) ?? (c.id === EMESH.VMAPS1 ? read(false) : null);\n if (!list) throw new Error(`.object: чанк меша 0x${c.id.toString(16)} разобран неверно`);\n m.vmaps.push(...list);\n r.pos = c.end;\n break;\n }\n }\n if (r.pos > c.end) throw new Error(`.object: чанк меша 0x${c.id.toString(16)} разобран неверно`);\n }\n return m;\n}\n\nexport function parseObject(buf: ArrayBuffer): XrObject {\n const top = chunksOf(buf, 0, buf.byteLength).find((c) => c.id === EOBJ.MAIN);\n if (!top) throw new Error('Не объект X-Ray SDK (.object): нет чанка 0x7777');\n const o: XrObject = { version: 0, flags: 0, userdata: '', lodRef: '', surfaces: [], meshes: [], revision: null, extra: [] };\n for (const c of chunksOf(buf, top.start, top.end)) {\n const r = new R(buf, c.start, c.end);\n switch (c.id) {\n case EOBJ.VERSION: o.version = r.w(); break;\n case EOBJ.FLAGS: o.flags = r.d(); break;\n case EOBJ.USERDATA: o.userdata = r.sz(); break;\n case EOBJ.LOD_REF: o.lodRef = r.sz(); break;\n case EOBJ.MESHES: for (const mc of chunksOf(buf, c.start, c.end)) o.meshes.push(parseMesh(buf, mc.start, mc.end)); break;\n case EOBJ.SURFACES3: case EOBJ.SURFACES2: {\n const n = r.d();\n for (let k = 0; k < n; k++) {\n const s: XrSurface = { name: r.sz(), eshader: r.sz(), cshader: r.sz(), gamemtl: c.id === EOBJ.SURFACES3 ? r.sz() : 'default', texture: r.sz(), vmap: r.sz(), flags: r.d(), fvf: r.d(), };\n r.d(); // number of UV sets\n o.surfaces.push(s);\n }\n break;\n }\n case EOBJ.REVISION: o.revision = { owner: r.sz(), created: r.d(), modifier: r.sz(), modified: r.d() }; break;\n default: o.extra.push({ id: c.id, data: new Uint8Array(buf.slice(c.start, c.end)) });\n }\n }\n if (o.version !== 0x10) throw new Error(`.object версии 0x${o.version.toString(16)} не поддерживается (нужна 0x10, SDK ТЧ/ЧН/ЗП)`);\n return o;\n}\n\n/** Display mesh: per face corner, a point + UV from vmref; normals by smoothing groups. */\nexport interface XrObjectMesh { name: string; surface: XrSurface | undefined; pos: Float32Array; nor: Float32Array; uv: Float32Array; indices: Uint32Array; bone?: Float32Array; weight?: Float32Array }\n\nexport function objectMeshes(o: XrObject, smoothing: 'auto' | 'cop' | 'soc' = 'auto', boneOfMap?: Map<string, number>): XrObjectMesh[] {\n const out: XrObjectMesh[] = [];\n for (const m of o.meshes) {\n const nf = m.faces.length / 6, P = m.points;\n // face normals\n const fn = new Float32Array(nf * 3);\n for (let f = 0; f < nf; f++) {\n const a = m.faces[f * 6]! * 3, b = m.faces[f * 6 + 2]! * 3, c = m.faces[f * 6 + 4]! * 3;\n const ux = P[b]! - P[a]!, uy = P[b + 1]! - P[a + 1]!, uz = P[b + 2]! - P[a + 2]!, vx = P[c]! - P[a]!, vy = P[c + 1]! - P[a + 1]!, vz = P[c + 2]! - P[a + 2]!;\n // normal = (b − a) × (c − a): the same as for a compiled level (checked on labx8: face winding is preserved)\n let nx = uy * vz - uz * vy, ny = uz * vx - ux * vz, nz = ux * vy - uy * vx;\n const l = Math.hypot(nx, ny, nz) || 1; nx /= l; ny /= l; nz /= l;\n fn[f * 3] = nx; fn[f * 3 + 1] = ny; fn[f * 3 + 2] = nz;\n }\n // faces around a point\n const around: number[][] = Array.from({ length: P.length / 3 }, () => []);\n for (let f = 0; f < nf; f++) for (let k = 0; k < 3; k++) around[m.faces[f * 6 + k * 2]!]!.push(f);\n // CoP (SDK 0.7): sg has one bit per face edge (bit k = edge k→k+1 is hard); SoC/CS: a smoothing group mask.\n // The file has no format flag: values below 8 on all faces are treated as edges (as found on SDK 0.7 objects).\n const sgv = m.sg, copEdges = smoothing === 'cop' || (smoothing === 'auto' && !!sgv && sgv.every((v) => v < 8));\n const hard = new Set<string>();\n if (copEdges) for (let f = 0; f < nf; f++) for (let k = 0; k < 3; k++) if ((sgv![f]! >> k) & 1) {\n const a = m.faces[f * 6 + k * 2]!, b = m.faces[f * 6 + ((k + 1) % 3) * 2]!;\n hard.add(a < b ? `${a}_${b}` : `${b}_${a}`);\n }\n const others = (f: number, pt: number) => { const r: number[] = []; for (let k = 0; k < 3; k++) { const q = m.faces[f * 6 + k * 2]!; if (q !== pt) r.push(q); } return r; };\n /** Faces whose normals are smoothed with face f at point pt. */\n const smoothFan = (f: number, pt: number): number[] => {\n if (!sgv) return around[pt]!;\n if (!copEdges) { const g0 = sgv[f]!; return g0 ? around[pt]!.filter((g) => g === f || (sgv[g]! & g0) !== 0) : [f]; }\n const seen = new Set([f]), stack = [f];\n while (stack.length) {\n const g = stack.pop()!;\n for (const q of others(g, pt)) {\n if (hard.has(pt < q ? `${pt}_${q}` : `${q}_${pt}`)) continue;\n for (const h of around[pt]!) if (!seen.has(h) && others(h, pt).includes(q)) { seen.add(h); stack.push(h); }\n }\n }\n return [...seen];\n };\n const uvOf = (vmref: number): [number, number] => {\n const ref = m.vmrefs[vmref];\n if (!ref) return [0, 0];\n for (const [vm, idx] of ref) { const map = m.vmaps[vm]; if (map && map.type === 0 && map.dim === 2) return [map.data[idx * 2]!, map.data[idx * 2 + 1]!]; }\n return [0, 0];\n };\n for (const sf of m.sfaces.length ? m.sfaces : [{ surface: o.surfaces[0]?.name ?? '', faces: Uint32Array.from({ length: nf }, (_, i) => i) }]) {\n const pos: number[] = [], nor: number[] = [], uv: number[] = [], idx: number[] = [], key = new Map<string, number>(), bone: number[] = [], weight: number[] = [];\n for (const f of sf.faces) {\n for (let k = 0; k < 3; k++) {\n const pt = m.faces[f * 6 + k * 2]!, vr = m.faces[f * 6 + k * 2 + 1]!;\n let nx = 0, ny = 0, nz = 0;\n for (const g of smoothFan(f, pt)) { nx += fn[g * 3]!; ny += fn[g * 3 + 1]!; nz += fn[g * 3 + 2]!; }\n const l = Math.hypot(nx, ny, nz) || 1;\n nx /= l; ny /= l; nz /= l;\n const [u, v] = uvOf(vr), k2 = `${pt}|${u}|${v}|${nx.toFixed(3)}|${ny.toFixed(3)}|${nz.toFixed(3)}`;\n let vi = key.get(k2);\n if (vi === undefined) {\n vi = pos.length / 3; key.set(k2, vi);\n pos.push(P[pt * 3]!, P[pt * 3 + 1]!, P[pt * 3 + 2]!); nor.push(nx, ny, nz); uv.push(u, v);\n if (boneOfMap) { const [bi, w] = cornerWeights(m, vr, boneOfMap); bone.push(...bi); weight.push(...w); }\n }\n idx.push(vi);\n }\n }\n if (idx.length) out.push({ name: `${m.name}: ${sf.surface}`, surface: o.surfaces.find((s) => s.name === sf.surface), pos: Float32Array.from(pos), nor: Float32Array.from(nor), uv: Float32Array.from(uv), indices: Uint32Array.from(idx), ...(boneOfMap ? { bone: Float32Array.from(bone), weight: Float32Array.from(weight) } : {}) });\n }\n }\n return out;\n}\n\n/** Object bone: name, parent (number), vertex weight map name, bind pose. */\nexport interface XrObjectBone { name: string; parent: number; wmap: string; rot: number[]; pos: number[] }\nexport interface XrObjectSkeleton { bones: XrObjectBone[]; parts: Array<{ name: string; bones: string[] }>; motions: Uint8Array | null; motionRefs: string[] }\n\n/** Bones (0x0921), body parts (0x0923/0x0919), animations (0x0916, like .skls) and .omf references (0x0926) from the object chunks. */\nexport function objectSkeleton(o: XrObject): XrObjectSkeleton | null {\n const get = (id: number) => o.extra.find((c) => c.id === id)?.data;\n const bc = get(EOBJ.BONES);\n if (!bc) return null;\n const buf = bc.buffer.slice(bc.byteOffset, bc.byteOffset + bc.byteLength) as ArrayBuffer;\n const raw: Array<{ name: string; parent: string; wmap: string; rot: number[]; pos: number[] }> = [];\n for (const b of chunksOf(buf, 0, buf.byteLength)) {\n const sub = chunksOf(buf, b.start, b.end), def = sub.find((c) => c.id === BONE.DEF), bp = sub.find((c) => c.id === BONE.BIND_POSE);\n if (!def) continue;\n const r = new R(buf, def.start, def.end), name = r.sz(), parent = r.sz(), wmap = r.sz();\n let pos = [0, 0, 0], rot = [0, 0, 0];\n if (bp && bp.end - bp.start >= 24) { const q = new R(buf, bp.start, bp.end); pos = [q.f(), q.f(), q.f()]; rot = [q.f(), q.f(), q.f()]; }\n raw.push({ name, parent, wmap, rot, pos });\n }\n if (!raw.length) return null;\n const at = new Map(raw.map((b, i) => [b.name.toLowerCase(), i]));\n const bones = raw.map((b) => ({ name: b.name, parent: b.parent ? at.get(b.parent.toLowerCase()) ?? -1 : -1, wmap: b.wmap || b.name, rot: b.rot, pos: b.pos }));\n const parts: XrObjectSkeleton['parts'] = [];\n const pc = get(EOBJ.BONEPARTS2);\n if (pc) {\n try {\n const pb = pc.buffer.slice(pc.byteOffset, pc.byteOffset + pc.byteLength) as ArrayBuffer, r = new R(pb, 0, pb.byteLength), n = r.d();\n for (let i = 0; i < n; i++) { const name = r.sz(), k = r.d(), list: string[] = []; for (let j = 0; j < k; j++) list.push(r.sz()); parts.push({ name, bones: list }); }\n } catch { parts.length = 0; }\n }\n const motionRefs: string[] = [];\n const rc = get(EOBJ.SMOTION_REFS);\n if (rc) {\n const rb = rc.buffer.slice(rc.byteOffset, rc.byteOffset + rc.byteLength) as ArrayBuffer, r = new R(rb, 0, rb.byteLength);\n // CoP: u32 count + strings; older SDKs: one comma-separated string\n const n = rb.byteLength >= 4 ? new DataView(rb).getUint32(0, true) : 0;\n if (n > 0 && n < 1000) { r.d(); for (let i = 0; i < n && r.pos < r.end; i++) motionRefs.push(r.sz()); }\n else motionRefs.push(...r.sz().split(',').map((x) => x.trim()).filter(Boolean));\n }\n return { bones, parts, motions: get(EOBJ.SMOTIONS) ?? null, motionRefs };\n}\n\n/** Vertex weights of a face corner (vmref): up to 4 bones from weight maps (type-1 vmaps), normalized. */\nexport function cornerWeights(m: XrEditMesh, vmref: number, boneOfMap: Map<string, number>): [number[], number[]] {\n const list: Array<[number, number]> = [];\n for (const [vm, idx] of m.vmrefs[vmref] ?? []) {\n const map = m.vmaps[vm];\n if (!map || map.type !== 1) continue;\n const b = boneOfMap.get(map.name.toLowerCase());\n if (b !== undefined) list.push([b, map.data[idx]!]);\n }\n if (!list.length) return [[0, 0, 0, 0], [1, 0, 0, 0]];\n list.sort((a, b) => b[1] - a[1]);\n const top = list.slice(0, 4), sum = top.reduce((a, x) => a + x[1], 0) || 1;\n const bi = [0, 0, 0, 0], w = [0, 0, 0, 0];\n top.forEach(([b, x], i) => { bi[i] = b; w[i] = x / sum; });\n if (top.length === 1) w[0] = 1;\n return [bi, w];\n}\n"],"names":["list"],"mappings":"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"}
package/dist/ogf.d.ts CHANGED
@@ -60,12 +60,12 @@ export interface OgfModel {
60
60
  bounds: Bounds;
61
61
  }
62
62
  export declare function readChunks(buf: ArrayBuffer, start: number, end: number): OgfChunk[];
63
- /** Сжатые (LZHUF, старший бит id) чанки — распаковываются в отдельный буфер; остальные остаются как есть. */
63
+ /** Compressed chunks (LZHUF, the top bit of the id) are unpacked into a separate buffer; the rest stay as is. */
64
64
  export declare function unpackChunks(buf: ArrayBuffer, chunks: OgfChunk[]): {
65
65
  buf: ArrayBuffer;
66
66
  chunks: OgfChunk[];
67
67
  };
68
- /** Описание анимации из S_SMPARAMS: флаги (esmFX = 1 — «эффект» на одну кость), часть тела или кость, номер анимации. */
68
+ /** Animation description from S_SMPARAMS: flags (esmFX = 1 = an "effect" on one bone), body part or bone, animation number. */
69
69
  export interface XrayMotionDef {
70
70
  name: string;
71
71
  flags: number;
@@ -83,11 +83,11 @@ export interface XraySMParams {
83
83
  defs: XrayMotionDef[];
84
84
  }
85
85
  /**
86
- * S_SMPARAMS: части тела, порядок треков и описания анимаций. Треки в S_MOTIONS идут по номеру m_idx,
87
- * а кость определяется по имени (как в motions_value::load движка), поэтому порядок костей модели и анимации может различаться.
88
- * Анимация части (ноги, торс, голова) управляет только костями своей части — остальные треки в файле не значимы.
86
+ * S_SMPARAMS: body parts, track order and animation descriptions. Tracks in S_MOTIONS go by m_idx,
87
+ * and the bone is determined by name (as in the engine's motions_value::load), so the bone order of the model and the animation may differ.
88
+ * A part animation (legs, torso, head) drives only its part's bones; the other tracks in the file are not significant.
89
89
  */
90
90
  export declare function parseSMParams(buf: ArrayBuffer, c: OgfChunk): XraySMParams | null;
91
- /** Внешние анимации .omf для модели с костями bones (сопоставление треков по именам костей). */
91
+ /** External .omf animations for a model with bones `bones` (tracks matched by bone name). */
92
92
  export declare function parseOMF(buf: ArrayBuffer, bones: readonly OgfBone[]): XrayMotion[];
93
93
  export declare function parseOGF(buf0: ArrayBuffer): OgfModel;
package/dist/ogf.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"ogf.js","sources":["../src/ogf.ts"],"sourcesContent":["// Парсер X-Ray OGF (v4) и OMF. Без внешних зависимостей.\nimport { XRAY_FX_PART } from './motion';\nimport { lzhufDecompress } from './lzhuf';\nimport type { Bounds } from '@gmvjs/core/types';\nimport type { XrayMotion, XrayTrack } from './motion';\n\nexport const OGF = {\n HEADER: 1, TEXTURE: 2, VERTICES: 3, INDICES: 4, CHILDREN: 9, S_BONE_NAMES: 13, S_MOTIONS: 14,\n S_SMPARAMS: 15, S_IKDATA: 16, S_USERDATA: 17, S_DESC: 18, S_MOTION_REFS0: 19, S_MOTION_REFS1: 24,\n} as const;\nconst TYPE_NAMES = ['NORMAL', 'HIERRARHY', 'PROGRESSIVE', 'SKELETON_ANIM', 'SKELETON_GEOMDEF_PM', 'SKELETON_GEOMDEF_ST',\n 'LOD', 'TREE_ST', 'PARTICLE_EFFECT', 'PARTICLE_GROUP', 'SKELETON_RIGID', 'TREE_PM'];\nexport const FPS = 30;\n\nexport interface OgfChunk { id: number; comp: boolean; offset: number; size: number }\nexport interface OgfBone { name: string; parent: number; rot: number[]; pos: number[] }\nexport interface OgfMesh {\n texture: string; shader: string; vertexCount: number;\n pos: Float32Array; nor: Float32Array; uv: Float32Array; bone: Float32Array; weight: Float32Array;\n indices: Uint16Array; skinned: boolean; stride: number; name?: string;\n}\nexport interface OgfModel {\n info: { type: string; tris: number; ikOk: boolean; motionRefs: string[]; desc: { source: string; tool: string; owner?: string } | null };\n meshes: OgfMesh[]; bones: OgfBone[]; motions: XrayMotion[]; bounds: Bounds;\n}\n\nclass Reader {\n readonly dv: DataView;\n readonly u8: Uint8Array;\n constructor(buf: ArrayBuffer, public pos: number, public end: number) { this.dv = new DataView(buf); this.u8 = new Uint8Array(buf); }\n byte() { return this.dv.getUint8(this.pos++); }\n u16() { const v = this.dv.getUint16(this.pos, true); this.pos += 2; return v; }\n u32() { const v = this.dv.getUint32(this.pos, true); this.pos += 4; return v; }\n f32() { const v = this.dv.getFloat32(this.pos, true); this.pos += 4; return v; }\n skip(n: number) { this.pos += n; }\n get eof() { return this.pos >= this.end; }\n stringz() { let s = ''; while (this.pos < this.end) { const c = this.u8[this.pos++]!; if (!c) break; s += String.fromCharCode(c); } return s; }\n}\n\nexport function readChunks(buf: ArrayBuffer, start: number, end: number): OgfChunk[] {\n const dv = new DataView(buf), list: OgfChunk[] = [];\n let p = start;\n while (p + 8 <= end) {\n const raw = dv.getUint32(p, true), size = dv.getUint32(p + 4, true);\n if (p + 8 + size > end) break;\n list.push({ id: raw & 0x7fffffff, comp: (raw & 0x80000000) !== 0, offset: p + 8, size });\n p += 8 + size;\n }\n return list;\n}\n\nfunction readHeader(buf: ArrayBuffer, c: OgfChunk) {\n const r = new Reader(buf, c.offset, c.offset + c.size);\n const version = r.byte(), type = r.byte(), shader = r.u16();\n const bmin = [r.f32(), r.f32(), r.f32()], bmax = [r.f32(), r.f32(), r.f32()];\n return { version, type, shader, bmin, bmax };\n}\n\nfunction parseGeometry(buf: ArrayBuffer, vtx: OgfChunk, idx: OgfChunk, tex: OgfChunk | undefined, nBones: number): OgfMesh {\n const dv = new DataView(buf);\n const fmt = dv.getUint32(vtx.offset, true), n = dv.getUint32(vtx.offset + 4, true), base = vtx.offset + 8;\n const stride = n ? Math.floor((vtx.size - 8) / n) : 0;\n if (![32, 60, 64, 70, 72, 76].includes(stride)) throw new Error(`Неподдерживаемый формат вершин 0x${fmt.toString(16)} (stride ${stride})`);\n const pos = new Float32Array(n * 3), nor = new Float32Array(n * 3), uv = new Float32Array(n * 2);\n const bone = new Float32Array(n * 4), wt = new Float32Array(n * 4);\n const f = (o: number) => dv.getFloat32(o, true), h = (o: number) => dv.getUint16(o, true);\n const cl = (b: number) => Math.min(b, Math.max(0, nBones - 1));\n for (let i = 0; i < n; i++) {\n const o = base + i * stride;\n let P: number, N: number, UV: number, bi = [0, 0, 0, 0], w = [1, 0, 0, 0];\n if (stride === 32) { P = o; N = o + 12; UV = o + 24; }\n else if (stride === 60) { P = o; N = o + 12; UV = o + 48; bi[0] = dv.getUint32(o + 56, true); }\n else if (stride === 64) { bi[0] = h(o); bi[1] = h(o + 2); P = o + 4; N = o + 16; UV = o + 56; const w1 = f(o + 52); w = [1 - w1, w1, 0, 0]; }\n // 3L/4L (ЧН/ЗП): в файле веса первых костей, вес последней — остаток (как в Vertices3W/4W движка)\n else if (stride === 70 || stride === 72) { bi = [h(o), h(o + 2), h(o + 4), 0]; P = o + 6; N = o + 18; UV = o + 62; const a = f(o + 54), b = f(o + 58); w = [a, b, 1 - a - b, 0]; }\n else { bi = [h(o), h(o + 2), h(o + 4), h(o + 6)]; P = o + 8; N = o + 20; UV = o + 68; const a = f(o + 56), b = f(o + 60), c = f(o + 64); w = [a, b, c, 1 - a - b - c]; }\n for (let k = 0; k < 3; k++) { pos[i * 3 + k] = f(P + 4 * k); nor[i * 3 + k] = f(N + 4 * k); }\n uv[i * 2] = f(UV); uv[i * 2 + 1] = f(UV + 4);\n for (let k = 0; k < 4; k++) { bone[i * 4 + k] = cl(bi[k]!); wt[i * 4 + k] = w[k]!; }\n }\n const ic = dv.getUint32(idx.offset, true), indices = new Uint16Array(ic);\n for (let i = 0; i < ic; i++) indices[i] = dv.getUint16(idx.offset + 4 + i * 2, true);\n let texture = '', shader = '';\n if (tex) { const r = new Reader(buf, tex.offset, tex.offset + tex.size); texture = r.stringz(); shader = r.stringz(); }\n return { texture, shader, vertexCount: n, pos, nor, uv, bone, weight: wt, indices, skinned: stride !== 32, stride };\n}\n\n/** Сжатые (LZHUF, старший бит id) чанки — распаковываются в отдельный буфер; остальные остаются как есть. */\nexport function unpackChunks(buf: ArrayBuffer, chunks: OgfChunk[]): { buf: ArrayBuffer; chunks: OgfChunk[] } {\n if (!chunks.some((c) => c.comp)) return { buf, chunks };\n const parts = chunks.map((c) => { const raw = new Uint8Array(buf, c.offset, c.size); return c.comp ? lzhufDecompress(raw) : raw; });\n const out = new Uint8Array(parts.reduce((a, p) => a + p.length, 0)), list: OgfChunk[] = [];\n let o = 0;\n parts.forEach((p, i) => { out.set(p, o); list.push({ id: chunks[i]!.id, comp: false, offset: o, size: p.length }); o += p.length; });\n return { buf: out.buffer, chunks: list };\n}\n\nfunction collectMeshes(buf0: ArrayBuffer, chunks0: OgfChunk[], out: OgfMesh[], nBones: number): void {\n const { buf, chunks } = unpackChunks(buf0, chunks0);\n const find = (id: number) => chunks.find((c) => c.id === id);\n const vtx = find(OGF.VERTICES), idx = find(OGF.INDICES);\n if (vtx && idx) out.push(parseGeometry(buf, vtx, idx, find(OGF.TEXTURE), nBones));\n const ch = find(OGF.CHILDREN);\n if (ch) for (const s of readChunks(buf, ch.offset, ch.offset + ch.size)) collectMeshes(buf, readChunks(buf, s.offset, s.offset + s.size), out, nBones);\n}\n\nfunction parseBoneNames(buf: ArrayBuffer, c: OgfChunk): OgfBone[] {\n const attempt = (withCount: boolean) => {\n const r = new Reader(buf, c.offset, c.offset + c.size);\n const count = withCount ? r.u32() : Infinity, out: Array<{ name: string; parentName: string }> = [];\n while (!r.eof && out.length < count) { const name = r.stringz(), parentName = r.stringz(); r.skip(60); out.push({ name, parentName }); }\n if (r.pos !== r.end || (withCount && out.length !== count)) return null;\n return out;\n };\n const list = attempt(true) ?? attempt(false);\n if (!list) throw new Error('Не удалось разобрать S_BONE_NAMES');\n const map = new Map(list.map((b, i) => [b.name.toLowerCase(), i]));\n return list.map((b) => ({ name: b.name, parent: b.parentName ? map.get(b.parentName.toLowerCase()) ?? -1 : -1, rot: [0, 0, 0], pos: [0, 0, 0] }));\n}\n\nfunction parseIK(buf: ArrayBuffer, c: OgfChunk, bones: OgfBone[]): boolean {\n const attempt = (friction: boolean) => {\n const r = new Reader(buf, c.offset, c.offset + c.size), out: Array<{ rot: number[]; pos: number[] }> = [];\n for (let i = 0; i < bones.length; i++) {\n if (r.pos + 4 > r.end) return null;\n r.u32(); r.stringz(); r.skip(112 + 4 + 48 + 8 + 12 + (friction ? 4 : 0));\n if (r.pos + 24 > r.end) return null;\n const rot = [r.f32(), r.f32(), r.f32()], pos = [r.f32(), r.f32(), r.f32()];\n r.skip(16);\n out.push({ rot, pos });\n }\n return r.pos === r.end ? out : null;\n };\n const res = attempt(true) ?? attempt(false);\n if (res) res.forEach((d, i) => { bones[i]!.rot = d.rot; bones[i]!.pos = d.pos; });\n return !!res;\n}\n\n// ---- Анимации ----\nfunction readTracks(buf: ArrayBuffer, start: number, end: number, frames: number, n: number): { tracks: XrayTrack[]; p: number } | null {\n const dv = new DataView(buf), tracks: XrayTrack[] = [];\n let p = start;\n for (let i = 0; i < n; i++) {\n if (p + 1 > end) return null;\n const flags = dv.getUint8(p++);\n let rot: Int16Array, trans: Float32Array, constT = false;\n if (flags & 2) {\n if (p + 8 > end) return null;\n rot = new Int16Array(4);\n for (let k = 0; k < 4; k++) rot[k] = dv.getInt16(p + 2 * k, true);\n p += 8;\n } else {\n if (p + 4 + frames * 8 > end) return null;\n p += 4;\n rot = new Int16Array(frames * 4);\n for (let k = 0; k < frames * 4; k++) rot[k] = dv.getInt16(p + 2 * k, true);\n p += frames * 8;\n }\n if (flags & 1) {\n const wide = (flags & 4) !== 0, bytes = frames * 3 * (wide ? 2 : 1);\n if (p + 4 + bytes + 24 > end) return null;\n p += 4;\n const raw = new Float32Array(frames * 3), kp = p;\n for (let k = 0; k < frames * 3; k++) raw[k] = wide ? dv.getInt16(kp + 2 * k, true) : dv.getInt8(kp + k);\n p += bytes;\n const sz = [dv.getFloat32(p, true), dv.getFloat32(p + 4, true), dv.getFloat32(p + 8, true)];\n const ini = [dv.getFloat32(p + 12, true), dv.getFloat32(p + 16, true), dv.getFloat32(p + 20, true)];\n p += 24;\n for (let k = 0; k < frames * 3; k++) raw[k] = raw[k]! * sz[k % 3]! + ini[k % 3]!;\n trans = raw;\n } else {\n if (p + 12 > end) return null;\n trans = new Float32Array([dv.getFloat32(p, true), dv.getFloat32(p + 4, true), dv.getFloat32(p + 8, true)]);\n p += 12;\n constT = true;\n }\n tracks.push({ rot, trans, constT });\n }\n return { tracks, p };\n}\n\n/** Описание анимации из S_SMPARAMS: флаги (esmFX = 1 — «эффект» на одну кость), часть тела или кость, номер анимации. */\nexport interface XrayMotionDef { name: string; flags: number; boneOrPart: number; motion: number; speed: number }\nexport interface XraySMParams { version: number; trackBones: string[]; parts: Array<{ name: string; bones: string[] }>; defs: XrayMotionDef[] }\n\n/**\n * S_SMPARAMS: части тела, порядок треков и описания анимаций. Треки в S_MOTIONS идут по номеру m_idx,\n * а кость определяется по имени (как в motions_value::load движка), поэтому порядок костей модели и анимации может различаться.\n * Анимация части (ноги, торс, голова) управляет только костями своей части — остальные треки в файле не значимы.\n */\nexport function parseSMParams(buf: ArrayBuffer, c: OgfChunk): XraySMParams | null {\n try {\n const r = new Reader(buf, c.offset, c.offset + c.size), version = r.u16(), nParts = r.u16(), trackBones: string[] = [], parts: XraySMParams['parts'] = [];\n for (let p = 0; p < nParts; p++) {\n const part = { name: r.stringz(), bones: [] as string[] }, nb = r.u16();\n for (let b = 0; b < nb; b++) { const name = r.stringz(), idx = version === 1 ? trackBones.length : r.u32(); trackBones[idx] = name; part.bones.push(name); }\n parts.push(part);\n }\n if (r.pos > r.end) return null;\n const defs: XrayMotionDef[] = [];\n try {\n const n = r.u16();\n for (let k = 0; k < n && r.pos < r.end; k++) {\n const name = r.stringz(), flags = r.u32(), boneOrPart = r.u16(), motion = r.u16(), speed = r.f32();\n r.skip(12); // power, accrue, falloff\n if (version >= 4) { const nm = r.u32(); for (let i = 0; i < nm; i++) { while (r.pos < r.end && r.byte() !== 10); r.skip(8 * r.u32()); } } // метки: имя до «\\r\\n», интервалы\n defs.push({ name, flags, boneOrPart, motion, speed });\n }\n if (r.pos > r.end) defs.length = 0;\n } catch { defs.length = 0; /* описания анимаций необязательны */ }\n return { version, trackBones, parts, defs };\n } catch { return null; }\n}\n\nfunction parseMotion(buf: ArrayBuffer, s: OgfChunk, nTracks: number): XrayMotion | null {\n const r = new Reader(buf, s.offset, s.offset + s.size);\n const name = r.stringz(), frames = r.u32(), start = r.pos, end = s.offset + s.size;\n if (!frames || frames > 100000) return null;\n let res = readTracks(buf, start, end, frames, nTracks);\n if (!res || res.p !== end) {\n res = null;\n for (let n = 1; n <= 1024 && !res; n++) { const t = readTracks(buf, start, end, frames, n); if (t && t.p === end) res = t; }\n if (!res) res = readTracks(buf, start, end, frames, nTracks);\n }\n if (!res) return null;\n return { kind: 'xray', name, frames, tracks: res.tracks, duration: frames / FPS };\n}\n\n/** Анимации чанка S_MOTIONS; треки раскладываются по костям модели по именам из S_SMPARAMS (если есть). */\nfunction parseMotionsChunk(buf: ArrayBuffer, c: OgfChunk, bones: readonly OgfBone[], params: XraySMParams | null): XrayMotion[] {\n const out: XrayMotion[] = [];\n const byName = new Map(bones.map((b, i) => [b.name.toLowerCase(), i]));\n const idx = (n: string | undefined) => byName.get((n ?? '').toLowerCase()) ?? -1;\n const map = params?.trackBones.length ? params.trackBones.map(idx) : null;\n const nTracks = map ? map.length : bones.length;\n const partBones = params?.parts.map((p) => new Set(p.bones.map(idx))) ?? [];\n const defOf = new Map(params?.defs.map((d) => [d.motion, d]) ?? []);\n for (const s of readChunks(buf, c.offset, c.offset + c.size)) {\n if (s.id === 0) continue;\n try {\n const m = parseMotion(buf, s, nTracks);\n if (!m) continue;\n if (map) { const t: XrayTrack[] = []; map.forEach((bi, k) => { if (bi >= 0 && m.tracks[k]) t[bi] = m.tracks[k]!; }); m.tracks = t; }\n // анимация одной части тела: остальные кости остаются в bind-позе (в игре их ведёт другая анимация)\n const def = defOf.get(s.id - 1);\n if (def) {\n const fx = (def.flags & 1) !== 0, only = fx ? new Set([def.boneOrPart]) : partBones[def.boneOrPart];\n if (only && only.size && (fx || partBones.length > 1)) {\n const t: XrayTrack[] = [];\n for (const bi of only) if (m.tracks[bi]) t[bi] = m.tracks[bi]!;\n m.tracks = t;\n m.part = fx ? XRAY_FX_PART : params!.parts[def.boneOrPart]!.name;\n }\n }\n out.push(m);\n } catch { /* пропускаем битую анимацию */ }\n }\n return out;\n}\n\n/** Внешние анимации .omf для модели с костями bones (сопоставление треков по именам костей). */\nexport function parseOMF(buf: ArrayBuffer, bones: readonly OgfBone[]): XrayMotion[] {\n const top = readChunks(buf, 0, buf.byteLength), c = top.find((x) => x.id === OGF.S_MOTIONS);\n if (!c) throw new Error('В файле нет чанка анимаций (S_MOTIONS)');\n const pc = top.find((x) => x.id === OGF.S_SMPARAMS);\n return parseMotionsChunk(buf, c, bones, pc ? parseSMParams(buf, pc) : null);\n}\n\nexport function parseOGF(buf0: ArrayBuffer): OgfModel {\n const { buf, chunks: top } = unpackChunks(buf0, readChunks(buf0, 0, buf0.byteLength));\n const hc = top.find((c) => c.id === OGF.HEADER);\n if (!hc) throw new Error('Не OGF файл: нет заголовка');\n const hdr = readHeader(buf, hc);\n if (hdr.version !== 4) throw new Error(`Поддерживается только OGF версии 4 (в файле v${hdr.version})`);\n const find = (id: number) => top.find((c) => c.id === id);\n\n const bnc = find(OGF.S_BONE_NAMES);\n const bones = bnc ? parseBoneNames(buf, bnc) : [];\n const ikc = find(OGF.S_IKDATA);\n const ikOk = ikc && bones.length ? parseIK(buf, ikc, bones) : false;\n\n const meshes: OgfMesh[] = [];\n collectMeshes(buf, top, meshes, bones.length);\n if (!meshes.length) throw new Error(`Геометрия не найдена (тип модели: ${TYPE_NAMES[hdr.type] ?? hdr.type})`);\n\n const min = [Infinity, Infinity, Infinity], max = [-Infinity, -Infinity, -Infinity];\n let tris = 0;\n for (const m of meshes) {\n tris += m.indices.length / 3;\n for (let i = 0; i < m.pos.length; i++) { const k = i % 3; if (m.pos[i]! < min[k]!) min[k] = m.pos[i]!; if (m.pos[i]! > max[k]!) max[k] = m.pos[i]!; }\n }\n\n const mc = find(OGF.S_MOTIONS);\n const pc = find(OGF.S_SMPARAMS);\n const motions = mc ? parseMotionsChunk(buf, mc, bones, pc ? parseSMParams(buf, pc) : null) : [];\n\n let refs: string[] = [];\n try {\n const c19 = find(OGF.S_MOTION_REFS0), c20 = find(OGF.S_MOTION_REFS1);\n if (c19) refs = new Reader(buf, c19.offset, c19.offset + c19.size).stringz().split(',').map((s) => s.trim()).filter(Boolean);\n else if (c20) { const r = new Reader(buf, c20.offset, c20.offset + c20.size); const k = r.u32(); for (let i = 0; i < k; i++) refs.push(r.stringz()); }\n } catch { /* необязательный чанк */ }\n\n let desc: OgfModel['info']['desc'] = null;\n try {\n const d = find(OGF.S_DESC);\n if (d) { const r = new Reader(buf, d.offset, d.offset + d.size); desc = { source: r.stringz(), tool: r.stringz() }; r.u32(); desc.owner = r.stringz(); }\n } catch { /* необязательный чанк */ }\n\n return { info: { type: TYPE_NAMES[hdr.type] ?? String(hdr.type), tris, ikOk, motionRefs: refs, desc }, meshes, bones, motions, bounds: { min, max } };\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ogf.js","sources":["../src/ogf.ts"],"sourcesContent":["// X-Ray OGF (v4) and OMF parser. No external dependencies.\nimport { XRAY_FX_PART } from './motion';\nimport { lzhufDecompress } from './lzhuf';\nimport type { Bounds } from '@gmvjs/core/types';\nimport type { XrayMotion, XrayTrack } from './motion';\n\nexport const OGF = {\n HEADER: 1, TEXTURE: 2, VERTICES: 3, INDICES: 4, CHILDREN: 9, S_BONE_NAMES: 13, S_MOTIONS: 14,\n S_SMPARAMS: 15, S_IKDATA: 16, S_USERDATA: 17, S_DESC: 18, S_MOTION_REFS0: 19, S_MOTION_REFS1: 24,\n} as const;\nconst TYPE_NAMES = ['NORMAL', 'HIERRARHY', 'PROGRESSIVE', 'SKELETON_ANIM', 'SKELETON_GEOMDEF_PM', 'SKELETON_GEOMDEF_ST',\n 'LOD', 'TREE_ST', 'PARTICLE_EFFECT', 'PARTICLE_GROUP', 'SKELETON_RIGID', 'TREE_PM'];\nexport const FPS = 30;\n\nexport interface OgfChunk { id: number; comp: boolean; offset: number; size: number }\nexport interface OgfBone { name: string; parent: number; rot: number[]; pos: number[] }\nexport interface OgfMesh {\n texture: string; shader: string; vertexCount: number;\n pos: Float32Array; nor: Float32Array; uv: Float32Array; bone: Float32Array; weight: Float32Array;\n indices: Uint16Array; skinned: boolean; stride: number; name?: string;\n}\nexport interface OgfModel {\n info: { type: string; tris: number; ikOk: boolean; motionRefs: string[]; desc: { source: string; tool: string; owner?: string } | null };\n meshes: OgfMesh[]; bones: OgfBone[]; motions: XrayMotion[]; bounds: Bounds;\n}\n\nclass Reader {\n readonly dv: DataView;\n readonly u8: Uint8Array;\n constructor(buf: ArrayBuffer, public pos: number, public end: number) { this.dv = new DataView(buf); this.u8 = new Uint8Array(buf); }\n byte() { return this.dv.getUint8(this.pos++); }\n u16() { const v = this.dv.getUint16(this.pos, true); this.pos += 2; return v; }\n u32() { const v = this.dv.getUint32(this.pos, true); this.pos += 4; return v; }\n f32() { const v = this.dv.getFloat32(this.pos, true); this.pos += 4; return v; }\n skip(n: number) { this.pos += n; }\n get eof() { return this.pos >= this.end; }\n stringz() { let s = ''; while (this.pos < this.end) { const c = this.u8[this.pos++]!; if (!c) break; s += String.fromCharCode(c); } return s; }\n}\n\nexport function readChunks(buf: ArrayBuffer, start: number, end: number): OgfChunk[] {\n const dv = new DataView(buf), list: OgfChunk[] = [];\n let p = start;\n while (p + 8 <= end) {\n const raw = dv.getUint32(p, true), size = dv.getUint32(p + 4, true);\n if (p + 8 + size > end) break;\n list.push({ id: raw & 0x7fffffff, comp: (raw & 0x80000000) !== 0, offset: p + 8, size });\n p += 8 + size;\n }\n return list;\n}\n\nfunction readHeader(buf: ArrayBuffer, c: OgfChunk) {\n const r = new Reader(buf, c.offset, c.offset + c.size);\n const version = r.byte(), type = r.byte(), shader = r.u16();\n const bmin = [r.f32(), r.f32(), r.f32()], bmax = [r.f32(), r.f32(), r.f32()];\n return { version, type, shader, bmin, bmax };\n}\n\nfunction parseGeometry(buf: ArrayBuffer, vtx: OgfChunk, idx: OgfChunk, tex: OgfChunk | undefined, nBones: number): OgfMesh {\n const dv = new DataView(buf);\n const fmt = dv.getUint32(vtx.offset, true), n = dv.getUint32(vtx.offset + 4, true), base = vtx.offset + 8;\n const stride = n ? Math.floor((vtx.size - 8) / n) : 0;\n if (![32, 60, 64, 70, 72, 76].includes(stride)) throw new Error(`Неподдерживаемый формат вершин 0x${fmt.toString(16)} (stride ${stride})`);\n const pos = new Float32Array(n * 3), nor = new Float32Array(n * 3), uv = new Float32Array(n * 2);\n const bone = new Float32Array(n * 4), wt = new Float32Array(n * 4);\n const f = (o: number) => dv.getFloat32(o, true), h = (o: number) => dv.getUint16(o, true);\n const cl = (b: number) => Math.min(b, Math.max(0, nBones - 1));\n for (let i = 0; i < n; i++) {\n const o = base + i * stride;\n let P: number, N: number, UV: number, bi = [0, 0, 0, 0], w = [1, 0, 0, 0];\n if (stride === 32) { P = o; N = o + 12; UV = o + 24; }\n else if (stride === 60) { P = o; N = o + 12; UV = o + 48; bi[0] = dv.getUint32(o + 56, true); }\n else if (stride === 64) { bi[0] = h(o); bi[1] = h(o + 2); P = o + 4; N = o + 16; UV = o + 56; const w1 = f(o + 52); w = [1 - w1, w1, 0, 0]; }\n // 3L/4L (CS/CoP): the file holds the weights of the first bones, the last bone's weight is the remainder (as in the engine's Vertices3W/4W)\n else if (stride === 70 || stride === 72) { bi = [h(o), h(o + 2), h(o + 4), 0]; P = o + 6; N = o + 18; UV = o + 62; const a = f(o + 54), b = f(o + 58); w = [a, b, 1 - a - b, 0]; }\n else { bi = [h(o), h(o + 2), h(o + 4), h(o + 6)]; P = o + 8; N = o + 20; UV = o + 68; const a = f(o + 56), b = f(o + 60), c = f(o + 64); w = [a, b, c, 1 - a - b - c]; }\n for (let k = 0; k < 3; k++) { pos[i * 3 + k] = f(P + 4 * k); nor[i * 3 + k] = f(N + 4 * k); }\n uv[i * 2] = f(UV); uv[i * 2 + 1] = f(UV + 4);\n for (let k = 0; k < 4; k++) { bone[i * 4 + k] = cl(bi[k]!); wt[i * 4 + k] = w[k]!; }\n }\n const ic = dv.getUint32(idx.offset, true), indices = new Uint16Array(ic);\n for (let i = 0; i < ic; i++) indices[i] = dv.getUint16(idx.offset + 4 + i * 2, true);\n let texture = '', shader = '';\n if (tex) { const r = new Reader(buf, tex.offset, tex.offset + tex.size); texture = r.stringz(); shader = r.stringz(); }\n return { texture, shader, vertexCount: n, pos, nor, uv, bone, weight: wt, indices, skinned: stride !== 32, stride };\n}\n\n/** Compressed chunks (LZHUF, the top bit of the id) are unpacked into a separate buffer; the rest stay as is. */\nexport function unpackChunks(buf: ArrayBuffer, chunks: OgfChunk[]): { buf: ArrayBuffer; chunks: OgfChunk[] } {\n if (!chunks.some((c) => c.comp)) return { buf, chunks };\n const parts = chunks.map((c) => { const raw = new Uint8Array(buf, c.offset, c.size); return c.comp ? lzhufDecompress(raw) : raw; });\n const out = new Uint8Array(parts.reduce((a, p) => a + p.length, 0)), list: OgfChunk[] = [];\n let o = 0;\n parts.forEach((p, i) => { out.set(p, o); list.push({ id: chunks[i]!.id, comp: false, offset: o, size: p.length }); o += p.length; });\n return { buf: out.buffer, chunks: list };\n}\n\nfunction collectMeshes(buf0: ArrayBuffer, chunks0: OgfChunk[], out: OgfMesh[], nBones: number): void {\n const { buf, chunks } = unpackChunks(buf0, chunks0);\n const find = (id: number) => chunks.find((c) => c.id === id);\n const vtx = find(OGF.VERTICES), idx = find(OGF.INDICES);\n if (vtx && idx) out.push(parseGeometry(buf, vtx, idx, find(OGF.TEXTURE), nBones));\n const ch = find(OGF.CHILDREN);\n if (ch) for (const s of readChunks(buf, ch.offset, ch.offset + ch.size)) collectMeshes(buf, readChunks(buf, s.offset, s.offset + s.size), out, nBones);\n}\n\nfunction parseBoneNames(buf: ArrayBuffer, c: OgfChunk): OgfBone[] {\n const attempt = (withCount: boolean) => {\n const r = new Reader(buf, c.offset, c.offset + c.size);\n const count = withCount ? r.u32() : Infinity, out: Array<{ name: string; parentName: string }> = [];\n while (!r.eof && out.length < count) { const name = r.stringz(), parentName = r.stringz(); r.skip(60); out.push({ name, parentName }); }\n if (r.pos !== r.end || (withCount && out.length !== count)) return null;\n return out;\n };\n const list = attempt(true) ?? attempt(false);\n if (!list) throw new Error('Не удалось разобрать S_BONE_NAMES');\n const map = new Map(list.map((b, i) => [b.name.toLowerCase(), i]));\n return list.map((b) => ({ name: b.name, parent: b.parentName ? map.get(b.parentName.toLowerCase()) ?? -1 : -1, rot: [0, 0, 0], pos: [0, 0, 0] }));\n}\n\nfunction parseIK(buf: ArrayBuffer, c: OgfChunk, bones: OgfBone[]): boolean {\n const attempt = (friction: boolean) => {\n const r = new Reader(buf, c.offset, c.offset + c.size), out: Array<{ rot: number[]; pos: number[] }> = [];\n for (let i = 0; i < bones.length; i++) {\n if (r.pos + 4 > r.end) return null;\n r.u32(); r.stringz(); r.skip(112 + 4 + 48 + 8 + 12 + (friction ? 4 : 0));\n if (r.pos + 24 > r.end) return null;\n const rot = [r.f32(), r.f32(), r.f32()], pos = [r.f32(), r.f32(), r.f32()];\n r.skip(16);\n out.push({ rot, pos });\n }\n return r.pos === r.end ? out : null;\n };\n const res = attempt(true) ?? attempt(false);\n if (res) res.forEach((d, i) => { bones[i]!.rot = d.rot; bones[i]!.pos = d.pos; });\n return !!res;\n}\n\n// ---- Animations ----\nfunction readTracks(buf: ArrayBuffer, start: number, end: number, frames: number, n: number): { tracks: XrayTrack[]; p: number } | null {\n const dv = new DataView(buf), tracks: XrayTrack[] = [];\n let p = start;\n for (let i = 0; i < n; i++) {\n if (p + 1 > end) return null;\n const flags = dv.getUint8(p++);\n let rot: Int16Array, trans: Float32Array, constT = false;\n if (flags & 2) {\n if (p + 8 > end) return null;\n rot = new Int16Array(4);\n for (let k = 0; k < 4; k++) rot[k] = dv.getInt16(p + 2 * k, true);\n p += 8;\n } else {\n if (p + 4 + frames * 8 > end) return null;\n p += 4;\n rot = new Int16Array(frames * 4);\n for (let k = 0; k < frames * 4; k++) rot[k] = dv.getInt16(p + 2 * k, true);\n p += frames * 8;\n }\n if (flags & 1) {\n const wide = (flags & 4) !== 0, bytes = frames * 3 * (wide ? 2 : 1);\n if (p + 4 + bytes + 24 > end) return null;\n p += 4;\n const raw = new Float32Array(frames * 3), kp = p;\n for (let k = 0; k < frames * 3; k++) raw[k] = wide ? dv.getInt16(kp + 2 * k, true) : dv.getInt8(kp + k);\n p += bytes;\n const sz = [dv.getFloat32(p, true), dv.getFloat32(p + 4, true), dv.getFloat32(p + 8, true)];\n const ini = [dv.getFloat32(p + 12, true), dv.getFloat32(p + 16, true), dv.getFloat32(p + 20, true)];\n p += 24;\n for (let k = 0; k < frames * 3; k++) raw[k] = raw[k]! * sz[k % 3]! + ini[k % 3]!;\n trans = raw;\n } else {\n if (p + 12 > end) return null;\n trans = new Float32Array([dv.getFloat32(p, true), dv.getFloat32(p + 4, true), dv.getFloat32(p + 8, true)]);\n p += 12;\n constT = true;\n }\n tracks.push({ rot, trans, constT });\n }\n return { tracks, p };\n}\n\n/** Animation description from S_SMPARAMS: flags (esmFX = 1 = an \"effect\" on one bone), body part or bone, animation number. */\nexport interface XrayMotionDef { name: string; flags: number; boneOrPart: number; motion: number; speed: number }\nexport interface XraySMParams { version: number; trackBones: string[]; parts: Array<{ name: string; bones: string[] }>; defs: XrayMotionDef[] }\n\n/**\n * S_SMPARAMS: body parts, track order and animation descriptions. Tracks in S_MOTIONS go by m_idx,\n * and the bone is determined by name (as in the engine's motions_value::load), so the bone order of the model and the animation may differ.\n * A part animation (legs, torso, head) drives only its part's bones; the other tracks in the file are not significant.\n */\nexport function parseSMParams(buf: ArrayBuffer, c: OgfChunk): XraySMParams | null {\n try {\n const r = new Reader(buf, c.offset, c.offset + c.size), version = r.u16(), nParts = r.u16(), trackBones: string[] = [], parts: XraySMParams['parts'] = [];\n for (let p = 0; p < nParts; p++) {\n const part = { name: r.stringz(), bones: [] as string[] }, nb = r.u16();\n for (let b = 0; b < nb; b++) { const name = r.stringz(), idx = version === 1 ? trackBones.length : r.u32(); trackBones[idx] = name; part.bones.push(name); }\n parts.push(part);\n }\n if (r.pos > r.end) return null;\n const defs: XrayMotionDef[] = [];\n try {\n const n = r.u16();\n for (let k = 0; k < n && r.pos < r.end; k++) {\n const name = r.stringz(), flags = r.u32(), boneOrPart = r.u16(), motion = r.u16(), speed = r.f32();\n r.skip(12); // power, accrue, falloff\n if (version >= 4) { const nm = r.u32(); for (let i = 0; i < nm; i++) { while (r.pos < r.end && r.byte() !== 10); r.skip(8 * r.u32()); } } // marks: a name up to \"\\r\\n\", intervals\n defs.push({ name, flags, boneOrPart, motion, speed });\n }\n if (r.pos > r.end) defs.length = 0;\n } catch { defs.length = 0; /* animation descriptions are optional */ }\n return { version, trackBones, parts, defs };\n } catch { return null; }\n}\n\nfunction parseMotion(buf: ArrayBuffer, s: OgfChunk, nTracks: number): XrayMotion | null {\n const r = new Reader(buf, s.offset, s.offset + s.size);\n const name = r.stringz(), frames = r.u32(), start = r.pos, end = s.offset + s.size;\n if (!frames || frames > 100000) return null;\n let res = readTracks(buf, start, end, frames, nTracks);\n if (!res || res.p !== end) {\n res = null;\n for (let n = 1; n <= 1024 && !res; n++) { const t = readTracks(buf, start, end, frames, n); if (t && t.p === end) res = t; }\n if (!res) res = readTracks(buf, start, end, frames, nTracks);\n }\n if (!res) return null;\n return { kind: 'xray', name, frames, tracks: res.tracks, duration: frames / FPS };\n}\n\n/** Animations of the S_MOTIONS chunk; tracks are mapped to model bones by the names from S_SMPARAMS (if present). */\nfunction parseMotionsChunk(buf: ArrayBuffer, c: OgfChunk, bones: readonly OgfBone[], params: XraySMParams | null): XrayMotion[] {\n const out: XrayMotion[] = [];\n const byName = new Map(bones.map((b, i) => [b.name.toLowerCase(), i]));\n const idx = (n: string | undefined) => byName.get((n ?? '').toLowerCase()) ?? -1;\n const map = params?.trackBones.length ? params.trackBones.map(idx) : null;\n const nTracks = map ? map.length : bones.length;\n const partBones = params?.parts.map((p) => new Set(p.bones.map(idx))) ?? [];\n const defOf = new Map(params?.defs.map((d) => [d.motion, d]) ?? []);\n for (const s of readChunks(buf, c.offset, c.offset + c.size)) {\n if (s.id === 0) continue;\n try {\n const m = parseMotion(buf, s, nTracks);\n if (!m) continue;\n if (map) { const t: XrayTrack[] = []; map.forEach((bi, k) => { if (bi >= 0 && m.tracks[k]) t[bi] = m.tracks[k]!; }); m.tracks = t; }\n // an animation of one body part: the other bones stay in the bind pose (in game another animation drives them)\n const def = defOf.get(s.id - 1);\n if (def) {\n const fx = (def.flags & 1) !== 0, only = fx ? new Set([def.boneOrPart]) : partBones[def.boneOrPart];\n if (only && only.size && (fx || partBones.length > 1)) {\n const t: XrayTrack[] = [];\n for (const bi of only) if (m.tracks[bi]) t[bi] = m.tracks[bi]!;\n m.tracks = t;\n m.part = fx ? XRAY_FX_PART : params!.parts[def.boneOrPart]!.name;\n }\n }\n out.push(m);\n } catch { /* skip a broken animation */ }\n }\n return out;\n}\n\n/** External .omf animations for a model with bones `bones` (tracks matched by bone name). */\nexport function parseOMF(buf: ArrayBuffer, bones: readonly OgfBone[]): XrayMotion[] {\n const top = readChunks(buf, 0, buf.byteLength), c = top.find((x) => x.id === OGF.S_MOTIONS);\n if (!c) throw new Error('В файле нет чанка анимаций (S_MOTIONS)');\n const pc = top.find((x) => x.id === OGF.S_SMPARAMS);\n return parseMotionsChunk(buf, c, bones, pc ? parseSMParams(buf, pc) : null);\n}\n\nexport function parseOGF(buf0: ArrayBuffer): OgfModel {\n const { buf, chunks: top } = unpackChunks(buf0, readChunks(buf0, 0, buf0.byteLength));\n const hc = top.find((c) => c.id === OGF.HEADER);\n if (!hc) throw new Error('Не OGF файл: нет заголовка');\n const hdr = readHeader(buf, hc);\n if (hdr.version !== 4) throw new Error(`Поддерживается только OGF версии 4 (в файле v${hdr.version})`);\n const find = (id: number) => top.find((c) => c.id === id);\n\n const bnc = find(OGF.S_BONE_NAMES);\n const bones = bnc ? parseBoneNames(buf, bnc) : [];\n const ikc = find(OGF.S_IKDATA);\n const ikOk = ikc && bones.length ? parseIK(buf, ikc, bones) : false;\n\n const meshes: OgfMesh[] = [];\n collectMeshes(buf, top, meshes, bones.length);\n if (!meshes.length) throw new Error(`Геометрия не найдена (тип модели: ${TYPE_NAMES[hdr.type] ?? hdr.type})`);\n\n const min = [Infinity, Infinity, Infinity], max = [-Infinity, -Infinity, -Infinity];\n let tris = 0;\n for (const m of meshes) {\n tris += m.indices.length / 3;\n for (let i = 0; i < m.pos.length; i++) { const k = i % 3; if (m.pos[i]! < min[k]!) min[k] = m.pos[i]!; if (m.pos[i]! > max[k]!) max[k] = m.pos[i]!; }\n }\n\n const mc = find(OGF.S_MOTIONS);\n const pc = find(OGF.S_SMPARAMS);\n const motions = mc ? parseMotionsChunk(buf, mc, bones, pc ? parseSMParams(buf, pc) : null) : [];\n\n let refs: string[] = [];\n try {\n const c19 = find(OGF.S_MOTION_REFS0), c20 = find(OGF.S_MOTION_REFS1);\n if (c19) refs = new Reader(buf, c19.offset, c19.offset + c19.size).stringz().split(',').map((s) => s.trim()).filter(Boolean);\n else if (c20) { const r = new Reader(buf, c20.offset, c20.offset + c20.size); const k = r.u32(); for (let i = 0; i < k; i++) refs.push(r.stringz()); }\n } catch { /* optional chunk */ }\n\n let desc: OgfModel['info']['desc'] = null;\n try {\n const d = find(OGF.S_DESC);\n if (d) { const r = new Reader(buf, d.offset, d.offset + d.size); desc = { source: r.stringz(), tool: r.stringz() }; r.u32(); desc.owner = r.stringz(); }\n } catch { /* optional chunk */ }\n\n return { info: { type: TYPE_NAMES[hdr.type] ?? String(hdr.type), tris, ikOk, motionRefs: refs, desc }, meshes, bones, motions, bounds: { min, max } };\n}\n"],"names":[],"mappings":"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"}
package/dist/scene.d.ts CHANGED
@@ -2,7 +2,7 @@ import type { LoadContext } from '@gmvjs/core/plugin';
2
2
  import type { Model, VFile } from '@gmvjs/core/types';
3
3
  import { type XrObjectMesh } from './object';
4
4
  export type Ini = Map<string, Map<string, string>>;
5
- /** Разбор ini X-Ray (секции, «ключ = значение», комментарии «;»). */
5
+ /** X-Ray ini parsing (sections, "key = value", ";" comments). */
6
6
  export declare function parseIni(text: string): Ini;
7
7
  export interface SceneObjectRef {
8
8
  name: string;
@@ -12,17 +12,17 @@ export interface SceneObjectRef {
12
12
  scale: number[];
13
13
  flags: number;
14
14
  }
15
- /** Объекты из scene_object.part. */
15
+ /** Objects from scene_object.part. */
16
16
  export declare function sceneObjects(ini: Ini): SceneObjectRef[];
17
17
  /**
18
- * Матрица поворота объекта сцены (строки-векторы: v' = v·R). Проверено на labx8 (ЗП): вершины 40 из 40 повёрнутых объектов
19
- * сцены совпали с геометрией скомпилированного уровня точно при R = transpose(setHPB(y, x, z)); другие трактовки углов — нет.
18
+ * Scene object rotation matrix (row vectors: v' = v·R). Verified on labx8 (CoP): the vertices of 40 out of 40 rotated scene objects
19
+ * matched the compiled level geometry exactly with R = transpose(setHPB(y, x, z)); other angle interpretations did not.
20
20
  */
21
21
  export declare function sceneRotation(rot: number[]): number[];
22
- /** Вершины меша объекта в мир сцены: v·S·R + P (строки-векторы). */
22
+ /** Object mesh vertices into the scene world: v·S·R + P (row vectors). */
23
23
  export declare function placeMesh(m: XrObjectMesh, ref: SceneObjectRef): {
24
24
  pos: Float32Array;
25
25
  nor: Float32Array;
26
26
  };
27
- /** Уровень SDK: .level + scene_object.part + объекты. Меши объединяются по текстуре и шейдеру. */
27
+ /** SDK level: .level + scene_object.part + objects. Meshes are merged by texture and shader. */
28
28
  export declare function loadSceneLevel(main: VFile, ctx: LoadContext): Promise<Model>;
package/dist/scene.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"scene.js","sources":["../src/scene.ts"],"sourcesContent":["// Сцена уровня X-Ray SDK 0.7 (ЗП): текстовые .level и части rawdata/levels/<уровень>/*.part (формат ini).\n// scene_object.part: объекты [object_N] с reference_name (путь в rawdata/objects без .object), position, rotation, scale.\nimport { boundsOf } from '@gmvjs/core/geometry';\nimport type { LoadContext } from '@gmvjs/core/plugin';\nimport type { Mesh, Model, VFile } from '@gmvjs/core/types';\nimport { objectMeshes, parseObject, type XrObjectMesh } from './object';\n\nexport type Ini = Map<string, Map<string, string>>;\n\n/** Разбор ini X-Ray (секции, «ключ = значение», комментарии «;»). */\nexport function parseIni(text: string): Ini {\n const out: Ini = new Map();\n let cur: Map<string, string> | null = null;\n for (const raw of text.split(/\\r?\\n/)) {\n const line = raw.replace(/;.*$/, '').trim();\n if (!line) continue;\n const sec = /^\\[([^\\]]+)\\]/.exec(line);\n if (sec) { cur = new Map(); out.set(sec[1]!.trim(), cur); continue; }\n const eq = line.indexOf('=');\n if (cur && eq > 0) cur.set(line.slice(0, eq).trim(), line.slice(eq + 1).trim());\n }\n return out;\n}\n\nexport interface SceneObjectRef { name: string; reference: string; position: number[]; rotation: number[]; scale: number[]; flags: number }\n\nconst vec = (s: string | undefined, d: number[]) => (s ? s.split(',').map((x) => +x.trim()) : d);\n\n/** Объекты из scene_object.part. */\nexport function sceneObjects(ini: Ini): SceneObjectRef[] {\n const out: SceneObjectRef[] = [];\n for (const [name, sec] of ini) {\n if (!/^object_\\d+$/.test(name) || !sec.get('reference_name')) continue;\n out.push({\n name: sec.get('name') ?? name, reference: sec.get('reference_name')!, flags: +(sec.get('flags') ?? 0),\n position: vec(sec.get('position'), [0, 0, 0]), rotation: vec(sec.get('rotation'), [0, 0, 0]), scale: vec(sec.get('scale'), [1, 1, 1]),\n });\n }\n return out;\n}\n\n/**\n * Матрица поворота объекта сцены (строки-векторы: v' = v·R). Проверено на labx8 (ЗП): вершины 40 из 40 повёрнутых объектов\n * сцены совпали с геометрией скомпилированного уровня точно при R = transpose(setHPB(y, x, z)); другие трактовки углов — нет.\n */\nexport function sceneRotation(rot: number[]): number[] {\n const h = rot[1]!, p = rot[0]!, b = rot[2]!;\n const sh = Math.sin(h), ch = Math.cos(h), sp = Math.sin(p), cp = Math.cos(p), sb = Math.sin(b), cb = Math.cos(b);\n const cc = ch * cb, cs = ch * sb, sc = sh * cb, ss = sh * sb;\n const m = [cc - sp * ss, cs + sp * sc, -cp * sh, -cp * sb, cp * cb, sp, sc + sp * cs, ss - sp * cc, cp * ch];\n return [m[0]!, m[3]!, m[6]!, m[1]!, m[4]!, m[7]!, m[2]!, m[5]!, m[8]!];\n}\n\n/** Вершины меша объекта в мир сцены: v·S·R + P (строки-векторы). */\nexport function placeMesh(m: XrObjectMesh, ref: SceneObjectRef): { pos: Float32Array; nor: Float32Array } {\n const R = sceneRotation(ref.rotation), [sx, sy, sz] = ref.scale as [number, number, number], [px, py, pz] = ref.position as [number, number, number];\n const n = m.pos.length / 3, pos = new Float32Array(n * 3), nor = new Float32Array(n * 3);\n for (let i = 0; i < n; i++) {\n const x = m.pos[i * 3]! * sx, y = m.pos[i * 3 + 1]! * sy, z = m.pos[i * 3 + 2]! * sz;\n pos[i * 3] = x * R[0]! + y * R[3]! + z * R[6]! + px;\n pos[i * 3 + 1] = x * R[1]! + y * R[4]! + z * R[7]! + py;\n pos[i * 3 + 2] = x * R[2]! + y * R[5]! + z * R[8]! + pz;\n // нормаль: при неравномерном масштабе — через обратный масштаб\n const a = m.nor[i * 3]! / sx, b = m.nor[i * 3 + 1]! / sy, c = m.nor[i * 3 + 2]! / sz;\n let nx = a * R[0]! + b * R[3]! + c * R[6]!, ny = a * R[1]! + b * R[4]! + c * R[7]!, nz = a * R[2]! + b * R[5]! + c * R[8]!;\n const l = Math.hypot(nx, ny, nz) || 1; nx /= l; ny /= l; nz /= l;\n nor[i * 3] = nx; nor[i * 3 + 1] = ny; nor[i * 3 + 2] = nz;\n }\n return { pos, nor };\n}\n\n/** Найти файл по пути rawdata/… (в открытых папках/архивах путь может начинаться выше: editors/rawdata, sdk/editors/rawdata). */\nasync function readRaw(ctx: LoadContext, rel: string): Promise<Uint8Array | null> {\n const want = rel.toLowerCase().replace(/\\\\/g, '/');\n for (const a of ctx.archives) {\n const e = a.lookup(want) ?? a.entries.find((x) => x.path.endsWith('/' + want));\n if (e) return a.read(e);\n }\n return null;\n}\n\n/** Уровень SDK: .level + scene_object.part + объекты. Меши объединяются по текстуре и шейдеру. */\nexport async function loadSceneLevel(main: VFile, ctx: LoadContext): Promise<Model> {\n const level = parseIni(new TextDecoder('windows-1251').decode(await main.arrayBuffer()));\n const opts = level.get('level_options'), name = main.name.replace(/\\.level$/i, '');\n const dir = (main.path ?? '').replace(/[^/]*$/, '');\n const partPath = `${dir}${name}/scene_object.part`;\n let part = await ctx.readPath(partPath).catch(() => null);\n if (!part) part = await readRaw(ctx, `rawdata/levels/${name}/scene_object.part`);\n if (!part) throw new Error(`Нет ${name}/scene_object.part рядом с ${main.name}: откройте папку SDK (editors/rawdata) целиком`);\n const refs = sceneObjects(parseIni(new TextDecoder('windows-1251').decode(part)));\n const cache = new Map<string, XrObjectMesh[] | null>(), missing = new Set<string>();\n const groups = new Map<string, { texture: string; shader: string; material?: string; pos: number[]; nor: number[]; uv: number[]; idx: number[] }>();\n let placed = 0;\n for (const ref of refs) {\n let list = cache.get(ref.reference);\n if (list === undefined) {\n const raw = await readRaw(ctx, `rawdata/objects/${ref.reference}.object`);\n try { list = raw ? objectMeshes(parseObject(raw.buffer.slice(raw.byteOffset, raw.byteOffset + raw.byteLength) as ArrayBuffer)) : null; } catch { list = null; }\n cache.set(ref.reference, list);\n }\n if (!list) { missing.add(ref.reference); continue; }\n placed++;\n for (const m of list) {\n const s = m.surface, key = `${s?.texture ?? ''}|${s?.eshader ?? ''}`;\n let g = groups.get(key);\n if (!g) groups.set(key, (g = { texture: s?.texture ?? '', shader: s?.eshader ?? '', material: s?.gamemtl, pos: [], nor: [], uv: [], idx: [] }));\n const { pos, nor } = placeMesh(m, ref), base = g.pos.length / 3;\n for (let i = 0; i < pos.length; i++) { g.pos.push(pos[i]!); g.nor.push(nor[i]!); }\n for (let i = 0; i < m.uv.length; i++) g.uv.push(m.uv[i]!);\n for (let i = 0; i < m.indices.length; i++) g.idx.push(m.indices[i]! + base);\n }\n }\n const meshes: Mesh[] = [...groups.values()].map((g) => {\n const n = g.pos.length / 3;\n return {\n name: `${g.texture || '(без текстуры)'} · ${g.shader}`, texture: g.texture, shader: g.shader, material: g.material, vertexCount: n,\n pos: Float32Array.from(g.pos), nor: Float32Array.from(g.nor), uv: Float32Array.from(g.uv),\n bone: new Float32Array(n * 4), weight: new Float32Array(n * 4).map((_, i) => (i % 4 === 0 ? 1 : 0)), indices: Uint32Array.from(g.idx), skinned: false,\n };\n });\n if (!meshes.length) throw new Error(`Объекты уровня не найдены (${missing.size} ссылок): откройте папку SDK с rawdata/objects`);\n const info = [`Уровень SDK: ${opts?.get('level_path') ?? name}, объектов ${refs.length}, показано ${placed}, мешей (по текстурам) ${meshes.length}`];\n if (missing.size) info.push(`Нет файлов объектов (${missing.size}): ${[...missing].slice(0, 6).join(', ')}${missing.size > 6 ? '…' : ''}`);\n return { meshes, skeleton: null, motions: [], bounds: boundsOf(meshes), flipZ: true, info };\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"scene.js","sources":["../src/scene.ts"],"sourcesContent":["// X-Ray SDK 0.7 level scene (CoP): text .level files and rawdata/levels/<level>/*.part parts (ini format).\n// scene_object.part: [object_N] objects with reference_name (a path in rawdata/objects without .object), position, rotation, scale.\nimport { boundsOf } from '@gmvjs/core/geometry';\nimport type { LoadContext } from '@gmvjs/core/plugin';\nimport type { Mesh, Model, VFile } from '@gmvjs/core/types';\nimport { objectMeshes, parseObject, type XrObjectMesh } from './object';\n\nexport type Ini = Map<string, Map<string, string>>;\n\n/** X-Ray ini parsing (sections, \"key = value\", \";\" comments). */\nexport function parseIni(text: string): Ini {\n const out: Ini = new Map();\n let cur: Map<string, string> | null = null;\n for (const raw of text.split(/\\r?\\n/)) {\n const line = raw.replace(/;.*$/, '').trim();\n if (!line) continue;\n const sec = /^\\[([^\\]]+)\\]/.exec(line);\n if (sec) { cur = new Map(); out.set(sec[1]!.trim(), cur); continue; }\n const eq = line.indexOf('=');\n if (cur && eq > 0) cur.set(line.slice(0, eq).trim(), line.slice(eq + 1).trim());\n }\n return out;\n}\n\nexport interface SceneObjectRef { name: string; reference: string; position: number[]; rotation: number[]; scale: number[]; flags: number }\n\nconst vec = (s: string | undefined, d: number[]) => (s ? s.split(',').map((x) => +x.trim()) : d);\n\n/** Objects from scene_object.part. */\nexport function sceneObjects(ini: Ini): SceneObjectRef[] {\n const out: SceneObjectRef[] = [];\n for (const [name, sec] of ini) {\n if (!/^object_\\d+$/.test(name) || !sec.get('reference_name')) continue;\n out.push({\n name: sec.get('name') ?? name, reference: sec.get('reference_name')!, flags: +(sec.get('flags') ?? 0),\n position: vec(sec.get('position'), [0, 0, 0]), rotation: vec(sec.get('rotation'), [0, 0, 0]), scale: vec(sec.get('scale'), [1, 1, 1]),\n });\n }\n return out;\n}\n\n/**\n * Scene object rotation matrix (row vectors: v' = v·R). Verified on labx8 (CoP): the vertices of 40 out of 40 rotated scene objects\n * matched the compiled level geometry exactly with R = transpose(setHPB(y, x, z)); other angle interpretations did not.\n */\nexport function sceneRotation(rot: number[]): number[] {\n const h = rot[1]!, p = rot[0]!, b = rot[2]!;\n const sh = Math.sin(h), ch = Math.cos(h), sp = Math.sin(p), cp = Math.cos(p), sb = Math.sin(b), cb = Math.cos(b);\n const cc = ch * cb, cs = ch * sb, sc = sh * cb, ss = sh * sb;\n const m = [cc - sp * ss, cs + sp * sc, -cp * sh, -cp * sb, cp * cb, sp, sc + sp * cs, ss - sp * cc, cp * ch];\n return [m[0]!, m[3]!, m[6]!, m[1]!, m[4]!, m[7]!, m[2]!, m[5]!, m[8]!];\n}\n\n/** Object mesh vertices into the scene world: v·S·R + P (row vectors). */\nexport function placeMesh(m: XrObjectMesh, ref: SceneObjectRef): { pos: Float32Array; nor: Float32Array } {\n const R = sceneRotation(ref.rotation), [sx, sy, sz] = ref.scale as [number, number, number], [px, py, pz] = ref.position as [number, number, number];\n const n = m.pos.length / 3, pos = new Float32Array(n * 3), nor = new Float32Array(n * 3);\n for (let i = 0; i < n; i++) {\n const x = m.pos[i * 3]! * sx, y = m.pos[i * 3 + 1]! * sy, z = m.pos[i * 3 + 2]! * sz;\n pos[i * 3] = x * R[0]! + y * R[3]! + z * R[6]! + px;\n pos[i * 3 + 1] = x * R[1]! + y * R[4]! + z * R[7]! + py;\n pos[i * 3 + 2] = x * R[2]! + y * R[5]! + z * R[8]! + pz;\n // normal: with non-uniform scale, through the inverse scale\n const a = m.nor[i * 3]! / sx, b = m.nor[i * 3 + 1]! / sy, c = m.nor[i * 3 + 2]! / sz;\n let nx = a * R[0]! + b * R[3]! + c * R[6]!, ny = a * R[1]! + b * R[4]! + c * R[7]!, nz = a * R[2]! + b * R[5]! + c * R[8]!;\n const l = Math.hypot(nx, ny, nz) || 1; nx /= l; ny /= l; nz /= l;\n nor[i * 3] = nx; nor[i * 3 + 1] = ny; nor[i * 3 + 2] = nz;\n }\n return { pos, nor };\n}\n\n/** Find a file by a rawdata/… path (in open folders/archives the path may start higher: editors/rawdata, sdk/editors/rawdata). */\nasync function readRaw(ctx: LoadContext, rel: string): Promise<Uint8Array | null> {\n const want = rel.toLowerCase().replace(/\\\\/g, '/');\n for (const a of ctx.archives) {\n const e = a.lookup(want) ?? a.entries.find((x) => x.path.endsWith('/' + want));\n if (e) return a.read(e);\n }\n return null;\n}\n\n/** SDK level: .level + scene_object.part + objects. Meshes are merged by texture and shader. */\nexport async function loadSceneLevel(main: VFile, ctx: LoadContext): Promise<Model> {\n const level = parseIni(new TextDecoder('windows-1251').decode(await main.arrayBuffer()));\n const opts = level.get('level_options'), name = main.name.replace(/\\.level$/i, '');\n const dir = (main.path ?? '').replace(/[^/]*$/, '');\n const partPath = `${dir}${name}/scene_object.part`;\n let part = await ctx.readPath(partPath).catch(() => null);\n if (!part) part = await readRaw(ctx, `rawdata/levels/${name}/scene_object.part`);\n if (!part) throw new Error(`Нет ${name}/scene_object.part рядом с ${main.name}: откройте папку SDK (editors/rawdata) целиком`);\n const refs = sceneObjects(parseIni(new TextDecoder('windows-1251').decode(part)));\n const cache = new Map<string, XrObjectMesh[] | null>(), missing = new Set<string>();\n const groups = new Map<string, { texture: string; shader: string; material?: string; pos: number[]; nor: number[]; uv: number[]; idx: number[] }>();\n let placed = 0;\n for (const ref of refs) {\n let list = cache.get(ref.reference);\n if (list === undefined) {\n const raw = await readRaw(ctx, `rawdata/objects/${ref.reference}.object`);\n try { list = raw ? objectMeshes(parseObject(raw.buffer.slice(raw.byteOffset, raw.byteOffset + raw.byteLength) as ArrayBuffer)) : null; } catch { list = null; }\n cache.set(ref.reference, list);\n }\n if (!list) { missing.add(ref.reference); continue; }\n placed++;\n for (const m of list) {\n const s = m.surface, key = `${s?.texture ?? ''}|${s?.eshader ?? ''}`;\n let g = groups.get(key);\n if (!g) groups.set(key, (g = { texture: s?.texture ?? '', shader: s?.eshader ?? '', material: s?.gamemtl, pos: [], nor: [], uv: [], idx: [] }));\n const { pos, nor } = placeMesh(m, ref), base = g.pos.length / 3;\n for (let i = 0; i < pos.length; i++) { g.pos.push(pos[i]!); g.nor.push(nor[i]!); }\n for (let i = 0; i < m.uv.length; i++) g.uv.push(m.uv[i]!);\n for (let i = 0; i < m.indices.length; i++) g.idx.push(m.indices[i]! + base);\n }\n }\n const meshes: Mesh[] = [...groups.values()].map((g) => {\n const n = g.pos.length / 3;\n return {\n name: `${g.texture || '(без текстуры)'} · ${g.shader}`, texture: g.texture, shader: g.shader, material: g.material, vertexCount: n,\n pos: Float32Array.from(g.pos), nor: Float32Array.from(g.nor), uv: Float32Array.from(g.uv),\n bone: new Float32Array(n * 4), weight: new Float32Array(n * 4).map((_, i) => (i % 4 === 0 ? 1 : 0)), indices: Uint32Array.from(g.idx), skinned: false,\n };\n });\n if (!meshes.length) throw new Error(`Объекты уровня не найдены (${missing.size} ссылок): откройте папку SDK с rawdata/objects`);\n const info = [`Уровень SDK: ${opts?.get('level_path') ?? name}, объектов ${refs.length}, показано ${placed}, мешей (по текстурам) ${meshes.length}`];\n if (missing.size) info.push(`Нет файлов объектов (${missing.size}): ${[...missing].slice(0, 6).join(', ')}${missing.size > 6 ? '…' : ''}`);\n return { meshes, skeleton: null, motions: [], bounds: boundsOf(meshes), flipZ: true, info };\n}\n"],"names":[],"mappings":"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"}
@@ -21,14 +21,14 @@ export declare class XraySkeleton implements SkeletonRuntime {
21
21
  bindVariant: string;
22
22
  bindErr: [number, number];
23
23
  constructor(bones: OgfBone[], transposeBind?: boolean);
24
- /** Матрица кости по углам setXYZi и позиции — в той же трактовке, что bind-поза (для анимаций SDK). */
24
+ /** Bone matrix from setXYZi angles and position, interpreted the same way as the bind pose (for SDK animations). */
25
25
  local(rot: number[], pos: number[], o: Float32Array): void;
26
- /** Выбор варианта трактовки углов: вершины должны лежать рядом со своими костями. */
26
+ /** Choose the angle interpretation: vertices must lie near their bones. */
27
27
  static auto(bones: OgfBone[], meshes: readonly Mesh[]): XraySkeleton;
28
28
  pose(motion: Motion | null, time: number, loop: boolean, invQ?: boolean): void;
29
- /** Автоподбор знака кватерниона: у верного варианта длины рёбер меша почти не меняются. */
29
+ /** Automatic quaternion sign selection: with the right variant, mesh edge lengths barely change. */
30
30
  detectInvert(meshes: readonly Mesh[], motion: XrayMotion): boolean;
31
- /** Искажение меша анимацией: средняя относительная ошибка длин рёбер на трёх кадрах (0 — рёбра не тянутся). */
31
+ /** Mesh distortion by an animation: the mean relative edge length error over three frames (0 = edges do not stretch). */
32
32
  motionError(meshes: readonly Mesh[], motion: XrayMotion, inv: boolean): number;
33
33
  }
34
34
  export {};
package/dist/skeleton.js CHANGED
@@ -139,11 +139,11 @@ class XraySkeleton {
139
139
  scratch = new Float32Array(16);
140
140
  bindVariant = "";
141
141
  bindErr = [0, 0];
142
- /** Матрица кости по углам setXYZi и позиции — в той же трактовке, что bind-поза (для анимаций SDK). */
142
+ /** Bone matrix from setXYZi angles and position, interpreted the same way as the bind pose (for SDK animations). */
143
143
  local(rot, pos, o) {
144
144
  eulerLocal(rot, pos, o, this.transposeBind);
145
145
  }
146
- /** Выбор варианта трактовки углов: вершины должны лежать рядом со своими костями. */
146
+ /** Choose the angle interpretation: vertices must lie near their bones. */
147
147
  static auto(bones, meshes) {
148
148
  const a = new XraySkeleton(bones, false);
149
149
  if (!a.n) return a;
@@ -201,12 +201,12 @@ class XraySkeleton {
201
201
  mulRow(this.invV[i], this.worldV[i], this.skinV[i]);
202
202
  }
203
203
  }
204
- /** Автоподбор знака кватерниона: у верного варианта длины рёбер меша почти не меняются. */
204
+ /** Automatic quaternion sign selection: with the right variant, mesh edge lengths barely change. */
205
205
  detectInvert(meshes, motion) {
206
206
  const s0 = this.motionError(meshes, motion, false), s1 = this.motionError(meshes, motion, true);
207
207
  return s1 < s0 * 0.9;
208
208
  }
209
- /** Искажение меша анимацией: средняя относительная ошибка длин рёбер на трёх кадрах (0 — рёбра не тянутся). */
209
+ /** Mesh distortion by an animation: the mean relative edge length error over three frames (0 = edges do not stretch). */
210
210
  motionError(meshes, motion, inv) {
211
211
  const edges = [];
212
212
  for (const m of meshes) {
@@ -1 +1 @@
1
- {"version":3,"file":"skeleton.js","sources":["../src/skeleton.ts"],"sourcesContent":["// Скелет X-Ray: углы bind-позы из IK-данных, анимации — квантованные кватернионы (row-vector матрицы, как в движке).\nimport type { Mesh, Motion, SkeletonRuntime } from '@gmvjs/core/types';\nimport type { XrayMotion, XrayTrack } from './motion';\nimport { FPS, type OgfBone } from './ogf';\n\nconst Q = 1 / 32767;\ntype M16 = Float32Array;\n\nfunction mulRow(a: M16, b: M16, o: M16): void { // строки-векторы: сначала a, затем b\n for (let r = 0; r < 4; r++)\n for (let c = 0; c < 4; c++)\n o[r * 4 + c] = a[r * 4]! * b[c]! + a[r * 4 + 1]! * b[4 + c]! + a[r * 4 + 2]! * b[8 + c]! + a[r * 4 + 3]! * b[12 + c]!;\n}\nfunction rigidInv(a: M16, o: M16): void {\n for (let r = 0; r < 3; r++) for (let c = 0; c < 3; c++) o[r * 4 + c] = a[c * 4 + r]!;\n for (let c = 0; c < 3; c++) o[12 + c] = -(a[12]! * a[c * 4]! + a[13]! * a[c * 4 + 1]! + a[14]! * a[c * 4 + 2]!);\n o[3] = o[7] = o[11] = 0; o[15] = 1;\n}\nfunction eulerLocal(rot: number[], pos: number[], o: M16, transpose: boolean): void {\n // Fmatrix::setXYZi(x, y, z) = setHPB(−y, −x, −z): для вектора-строки сначала поворот вокруг Z, затем X, затем Y\n // (крен, тангаж, курс). Проверено по скинингу ЗП: длины рёбер меша в анимациях сохраняются только при таком порядке.\n const cx = Math.cos(rot[0]!), sx = Math.sin(rot[0]!), cy = Math.cos(rot[1]!), sy = Math.sin(rot[1]!), cz = Math.cos(rot[2]!), sz = Math.sin(rot[2]!);\n const m = [cz * cy + sz * sx * sy, sz * cx, -cz * sy + sz * sx * cy, -sz * cy + cz * sx * sy, cz * cx, sz * sy + cz * sx * cy, cx * sy, -sx, cx * cy];\n for (let r = 0; r < 3; r++) for (let c = 0; c < 3; c++) o[r * 4 + c] = transpose ? m[c * 3 + r]! : m[r * 3 + c]!;\n o[3] = o[7] = o[11] = 0; o[12] = pos[0]!; o[13] = pos[1]!; o[14] = pos[2]!; o[15] = 1;\n}\nfunction quatLocal(x: number, y: number, z: number, w: number, tx: number, ty: number, tz: number, o: M16): void { // Fmatrix::rotation(Fquaternion) + translate_over\n const xx = x * x, yy = y * y, zz = z * z, xy = x * y, xz = x * z, yz = y * z, wx = w * x, wy = w * y, wz = w * z;\n o[0] = 1 - 2 * (yy + zz); o[1] = 2 * (xy - wz); o[2] = 2 * (xz + wy); o[3] = 0;\n o[4] = 2 * (xy + wz); o[5] = 1 - 2 * (xx + zz); o[6] = 2 * (yz - wx); o[7] = 0;\n o[8] = 2 * (xz - wy); o[9] = 2 * (yz + wx); o[10] = 1 - 2 * (xx + yy); o[11] = 0;\n o[12] = tx; o[13] = ty; o[14] = tz; o[15] = 1;\n}\nfunction trackLocal(t: XrayTrack, f0: number, f1: number, a: number, invQ: boolean, o: M16): void {\n const R = t.rot;\n let x: number, y: number, z: number, w: number;\n if (R.length === 4) { x = R[0]! * Q; y = R[1]! * Q; z = R[2]! * Q; w = R[3]! * Q; }\n else {\n const i = f0 * 4, j = f1 * 4;\n const x0 = R[i]! * Q, y0 = R[i + 1]! * Q, z0 = R[i + 2]! * Q, w0 = R[i + 3]! * Q;\n let x1 = R[j]! * Q, y1 = R[j + 1]! * Q, z1 = R[j + 2]! * Q, w1 = R[j + 3]! * Q;\n if (x0 * x1 + y0 * y1 + z0 * z1 + w0 * w1 < 0) { x1 = -x1; y1 = -y1; z1 = -z1; w1 = -w1; }\n x = x0 + (x1 - x0) * a; y = y0 + (y1 - y0) * a; z = z0 + (z1 - z0) * a; w = w0 + (w1 - w0) * a;\n }\n const l = Math.hypot(x, y, z, w) || 1;\n x /= l; y /= l; z /= l; w /= l;\n if (invQ) { x = -x; y = -y; z = -z; }\n const T = t.trans;\n let tx: number, ty: number, tz: number;\n if (T.length === 3) { tx = T[0]!; ty = T[1]!; tz = T[2]!; }\n else { const i = f0 * 3, j = f1 * 3; tx = T[i]! + (T[j]! - T[i]!) * a; ty = T[i + 1]! + (T[j + 1]! - T[i + 1]!) * a; tz = T[i + 2]! + (T[j + 2]! - T[i + 2]!) * a; }\n quatLocal(x, y, z, w, tx, ty, tz, o);\n}\n\nexport class XraySkeleton implements SkeletonRuntime {\n readonly n: number;\n readonly parent: number[];\n readonly order: number[];\n readonly bindLocal: Float32Array; readonly bindWorld: Float32Array; readonly invBind: Float32Array;\n readonly world: Float32Array; readonly skin: Float32Array;\n readonly bindLocalV: M16[]; readonly bindWorldV: M16[]; readonly invV: M16[]; readonly worldV: M16[]; readonly skinV: M16[];\n private readonly scratch = new Float32Array(16);\n bindVariant = '';\n bindErr: [number, number] = [0, 0];\n\n constructor(bones: OgfBone[], readonly transposeBind = false) {\n const n = (this.n = bones.length);\n this.parent = bones.map((b) => b.parent);\n const order: number[] = [], seen = new Uint8Array(n);\n const visit = (i: number) => { if (seen[i]) return; seen[i] = 1; if (this.parent[i]! >= 0) visit(this.parent[i]!); order.push(i); };\n for (let i = 0; i < n; i++) visit(i);\n this.order = order;\n const mk = () => new Float32Array(16 * n), view = (arr: Float32Array) => Array.from({ length: n }, (_, i) => arr.subarray(16 * i, 16 * i + 16));\n this.bindLocal = mk(); this.bindWorld = mk(); this.invBind = mk(); this.world = mk(); this.skin = mk();\n this.bindLocalV = view(this.bindLocal); this.bindWorldV = view(this.bindWorld); this.invV = view(this.invBind);\n this.worldV = view(this.world); this.skinV = view(this.skin);\n for (const i of order) {\n eulerLocal(bones[i]!.rot, bones[i]!.pos, this.bindLocalV[i]!, transposeBind);\n const p = this.parent[i]!;\n if (p < 0) this.bindWorldV[i]!.set(this.bindLocalV[i]!); else mulRow(this.bindLocalV[i]!, this.bindWorldV[p]!, this.bindWorldV[i]!);\n rigidInv(this.bindWorldV[i]!, this.invV[i]!);\n }\n for (let k = 0; k < 16 * n; k++) this.skin[k] = (k % 16) % 5 === 0 ? 1 : 0;\n this.world.set(this.bindWorld);\n }\n\n /** Матрица кости по углам setXYZi и позиции — в той же трактовке, что bind-поза (для анимаций SDK). */\n local(rot: number[], pos: number[], o: Float32Array): void { eulerLocal(rot, pos, o, this.transposeBind); }\n\n /** Выбор варианта трактовки углов: вершины должны лежать рядом со своими костями. */\n static auto(bones: OgfBone[], meshes: readonly Mesh[]): XraySkeleton {\n const a = new XraySkeleton(bones, false);\n if (!a.n) return a;\n const b = new XraySkeleton(bones, true);\n const err = (s: XraySkeleton) => {\n let e = 0, c = 0;\n for (const m of meshes) {\n if (!m.skinned) continue;\n const step = Math.max(1, Math.floor(m.vertexCount / 1500));\n for (let v = 0; v < m.vertexCount; v += step) {\n let bi = m.bone[v * 4]!, bw = m.weight[v * 4]!;\n for (let k = 1; k < 4; k++) if (m.weight[v * 4 + k]! > bw) { bw = m.weight[v * 4 + k]!; bi = m.bone[v * 4 + k]!; }\n const W = s.bindWorldV[bi]!;\n e += Math.hypot(m.pos[v * 3]! - W[12]!, m.pos[v * 3 + 1]! - W[13]!, m.pos[v * 3 + 2]! - W[14]!);\n c++;\n }\n }\n return c ? e / c : 0;\n };\n const ea = err(a), eb = err(b);\n const s = eb < ea * 0.98 ? b : a;\n s.bindVariant = s === b ? 'B (транспонированный)' : 'A';\n s.bindErr = [ea, eb];\n return s;\n }\n\n pose(motion: Motion | null, time: number, loop: boolean, invQ = false): void {\n if (!this.n) return;\n const m = motion && motion.kind === 'xray' ? motion : null;\n // кадры основной анимации и слоёв (у каждого своя длина; слои всегда по кругу)\n const frame = (x: XrayMotion, lp: boolean): [number, number, number] => {\n const F = x.frames;\n let fr = time * FPS;\n fr = lp ? ((fr % F) + F) % F : Math.min(Math.max(fr, 0), F - 1);\n const f0 = Math.floor(fr);\n return [f0, lp ? (f0 + 1) % F : Math.min(f0 + 1, F - 1), fr - f0];\n };\n const list: Array<[XrayMotion, number, number, number]> = m ? [[m, ...frame(m, loop)], ...(m.layers ?? []).map((x): [XrayMotion, number, number, number] => [x, ...frame(x, true)])] : [];\n for (const i of this.order) {\n const L = this.scratch;\n let done = false;\n for (const [x, f0, f1, a] of list) { const tr = x.tracks[i]; if (tr) { trackLocal(tr, f0, f1, a, invQ, L); done = true; break; } }\n if (!done) L.set(this.bindLocalV[i]!);\n const p = this.parent[i]!;\n if (p < 0) this.worldV[i]!.set(L); else mulRow(L, this.worldV[p]!, this.worldV[i]!);\n mulRow(this.invV[i]!, this.worldV[i]!, this.skinV[i]!);\n }\n }\n\n /** Автоподбор знака кватерниона: у верного варианта длины рёбер меша почти не меняются. */\n detectInvert(meshes: readonly Mesh[], motion: XrayMotion): boolean {\n const s0 = this.motionError(meshes, motion, false), s1 = this.motionError(meshes, motion, true);\n return s1 < s0 * 0.9;\n }\n\n /** Искажение меша анимацией: средняя относительная ошибка длин рёбер на трёх кадрах (0 — рёбра не тянутся). */\n motionError(meshes: readonly Mesh[], motion: XrayMotion, inv: boolean): number {\n const edges: Array<[Mesh, number, number]> = [];\n for (const m of meshes) {\n if (!m.skinned) continue;\n const tc = m.indices.length / 3, step = Math.max(1, Math.floor(tc / 1500));\n for (let t = 0; t < tc; t += step) edges.push([m, m.indices[t * 3]!, m.indices[t * 3 + 1]!]);\n }\n if (!edges.length) return 0;\n const sk = (m: Mesh, v: number, o: number[]) => {\n const x = m.pos[v * 3]!, y = m.pos[v * 3 + 1]!, z = m.pos[v * 3 + 2]!;\n o[0] = o[1] = o[2] = 0;\n for (let k = 0; k < 4; k++) {\n const w = m.weight[v * 4 + k]!;\n if (!w) continue;\n const M = this.skinV[m.bone[v * 4 + k]!]!;\n o[0] += w * (x * M[0]! + y * M[4]! + z * M[8]! + M[12]!); o[1] += w * (x * M[1]! + y * M[5]! + z * M[9]! + M[13]!); o[2] += w * (x * M[2]! + y * M[6]! + z * M[10]! + M[14]!);\n }\n };\n const A = [0, 0, 0], B = [0, 0, 0];\n const score = (inv: boolean) => {\n let d = 0, l = 0;\n for (const fr of [0, Math.floor(motion.frames / 2), motion.frames - 1]) {\n this.pose(motion, fr / FPS, false, inv);\n for (const [m, a, b] of edges) {\n sk(m, a, A); sk(m, b, B);\n const l1 = Math.hypot(A[0]! - B[0]!, A[1]! - B[1]!, A[2]! - B[2]!);\n const l0 = Math.hypot(m.pos[a * 3]! - m.pos[b * 3]!, m.pos[a * 3 + 1]! - m.pos[b * 3 + 1]!, m.pos[a * 3 + 2]! - m.pos[b * 3 + 2]!);\n d += Math.abs(l1 - l0); l += l0;\n }\n }\n return d / (l || 1);\n };\n return score(inv);\n }\n}\n\n"],"names":["s","inv"],"mappings":"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"}
1
+ {"version":3,"file":"skeleton.js","sources":["../src/skeleton.ts"],"sourcesContent":["// X-Ray skeleton: bind pose angles from IK data, animations as quantized quaternions (row-vector matrices, as in the engine).\nimport type { Mesh, Motion, SkeletonRuntime } from '@gmvjs/core/types';\nimport type { XrayMotion, XrayTrack } from './motion';\nimport { FPS, type OgfBone } from './ogf';\n\nconst Q = 1 / 32767;\ntype M16 = Float32Array;\n\nfunction mulRow(a: M16, b: M16, o: M16): void { // row vectors: a first, then b\n for (let r = 0; r < 4; r++)\n for (let c = 0; c < 4; c++)\n o[r * 4 + c] = a[r * 4]! * b[c]! + a[r * 4 + 1]! * b[4 + c]! + a[r * 4 + 2]! * b[8 + c]! + a[r * 4 + 3]! * b[12 + c]!;\n}\nfunction rigidInv(a: M16, o: M16): void {\n for (let r = 0; r < 3; r++) for (let c = 0; c < 3; c++) o[r * 4 + c] = a[c * 4 + r]!;\n for (let c = 0; c < 3; c++) o[12 + c] = -(a[12]! * a[c * 4]! + a[13]! * a[c * 4 + 1]! + a[14]! * a[c * 4 + 2]!);\n o[3] = o[7] = o[11] = 0; o[15] = 1;\n}\nfunction eulerLocal(rot: number[], pos: number[], o: M16, transpose: boolean): void {\n // Fmatrix::setXYZi(x, y, z) = setHPB(−y, −x, −z): for a row vector, rotation about Z first, then X, then Y\n // (roll, pitch, heading). Verified on CoP skinning: mesh edge lengths are preserved in animations only with this order.\n const cx = Math.cos(rot[0]!), sx = Math.sin(rot[0]!), cy = Math.cos(rot[1]!), sy = Math.sin(rot[1]!), cz = Math.cos(rot[2]!), sz = Math.sin(rot[2]!);\n const m = [cz * cy + sz * sx * sy, sz * cx, -cz * sy + sz * sx * cy, -sz * cy + cz * sx * sy, cz * cx, sz * sy + cz * sx * cy, cx * sy, -sx, cx * cy];\n for (let r = 0; r < 3; r++) for (let c = 0; c < 3; c++) o[r * 4 + c] = transpose ? m[c * 3 + r]! : m[r * 3 + c]!;\n o[3] = o[7] = o[11] = 0; o[12] = pos[0]!; o[13] = pos[1]!; o[14] = pos[2]!; o[15] = 1;\n}\nfunction quatLocal(x: number, y: number, z: number, w: number, tx: number, ty: number, tz: number, o: M16): void { // Fmatrix::rotation(Fquaternion) + translate_over\n const xx = x * x, yy = y * y, zz = z * z, xy = x * y, xz = x * z, yz = y * z, wx = w * x, wy = w * y, wz = w * z;\n o[0] = 1 - 2 * (yy + zz); o[1] = 2 * (xy - wz); o[2] = 2 * (xz + wy); o[3] = 0;\n o[4] = 2 * (xy + wz); o[5] = 1 - 2 * (xx + zz); o[6] = 2 * (yz - wx); o[7] = 0;\n o[8] = 2 * (xz - wy); o[9] = 2 * (yz + wx); o[10] = 1 - 2 * (xx + yy); o[11] = 0;\n o[12] = tx; o[13] = ty; o[14] = tz; o[15] = 1;\n}\nfunction trackLocal(t: XrayTrack, f0: number, f1: number, a: number, invQ: boolean, o: M16): void {\n const R = t.rot;\n let x: number, y: number, z: number, w: number;\n if (R.length === 4) { x = R[0]! * Q; y = R[1]! * Q; z = R[2]! * Q; w = R[3]! * Q; }\n else {\n const i = f0 * 4, j = f1 * 4;\n const x0 = R[i]! * Q, y0 = R[i + 1]! * Q, z0 = R[i + 2]! * Q, w0 = R[i + 3]! * Q;\n let x1 = R[j]! * Q, y1 = R[j + 1]! * Q, z1 = R[j + 2]! * Q, w1 = R[j + 3]! * Q;\n if (x0 * x1 + y0 * y1 + z0 * z1 + w0 * w1 < 0) { x1 = -x1; y1 = -y1; z1 = -z1; w1 = -w1; }\n x = x0 + (x1 - x0) * a; y = y0 + (y1 - y0) * a; z = z0 + (z1 - z0) * a; w = w0 + (w1 - w0) * a;\n }\n const l = Math.hypot(x, y, z, w) || 1;\n x /= l; y /= l; z /= l; w /= l;\n if (invQ) { x = -x; y = -y; z = -z; }\n const T = t.trans;\n let tx: number, ty: number, tz: number;\n if (T.length === 3) { tx = T[0]!; ty = T[1]!; tz = T[2]!; }\n else { const i = f0 * 3, j = f1 * 3; tx = T[i]! + (T[j]! - T[i]!) * a; ty = T[i + 1]! + (T[j + 1]! - T[i + 1]!) * a; tz = T[i + 2]! + (T[j + 2]! - T[i + 2]!) * a; }\n quatLocal(x, y, z, w, tx, ty, tz, o);\n}\n\nexport class XraySkeleton implements SkeletonRuntime {\n readonly n: number;\n readonly parent: number[];\n readonly order: number[];\n readonly bindLocal: Float32Array; readonly bindWorld: Float32Array; readonly invBind: Float32Array;\n readonly world: Float32Array; readonly skin: Float32Array;\n readonly bindLocalV: M16[]; readonly bindWorldV: M16[]; readonly invV: M16[]; readonly worldV: M16[]; readonly skinV: M16[];\n private readonly scratch = new Float32Array(16);\n bindVariant = '';\n bindErr: [number, number] = [0, 0];\n\n constructor(bones: OgfBone[], readonly transposeBind = false) {\n const n = (this.n = bones.length);\n this.parent = bones.map((b) => b.parent);\n const order: number[] = [], seen = new Uint8Array(n);\n const visit = (i: number) => { if (seen[i]) return; seen[i] = 1; if (this.parent[i]! >= 0) visit(this.parent[i]!); order.push(i); };\n for (let i = 0; i < n; i++) visit(i);\n this.order = order;\n const mk = () => new Float32Array(16 * n), view = (arr: Float32Array) => Array.from({ length: n }, (_, i) => arr.subarray(16 * i, 16 * i + 16));\n this.bindLocal = mk(); this.bindWorld = mk(); this.invBind = mk(); this.world = mk(); this.skin = mk();\n this.bindLocalV = view(this.bindLocal); this.bindWorldV = view(this.bindWorld); this.invV = view(this.invBind);\n this.worldV = view(this.world); this.skinV = view(this.skin);\n for (const i of order) {\n eulerLocal(bones[i]!.rot, bones[i]!.pos, this.bindLocalV[i]!, transposeBind);\n const p = this.parent[i]!;\n if (p < 0) this.bindWorldV[i]!.set(this.bindLocalV[i]!); else mulRow(this.bindLocalV[i]!, this.bindWorldV[p]!, this.bindWorldV[i]!);\n rigidInv(this.bindWorldV[i]!, this.invV[i]!);\n }\n for (let k = 0; k < 16 * n; k++) this.skin[k] = (k % 16) % 5 === 0 ? 1 : 0;\n this.world.set(this.bindWorld);\n }\n\n /** Bone matrix from setXYZi angles and position, interpreted the same way as the bind pose (for SDK animations). */\n local(rot: number[], pos: number[], o: Float32Array): void { eulerLocal(rot, pos, o, this.transposeBind); }\n\n /** Choose the angle interpretation: vertices must lie near their bones. */\n static auto(bones: OgfBone[], meshes: readonly Mesh[]): XraySkeleton {\n const a = new XraySkeleton(bones, false);\n if (!a.n) return a;\n const b = new XraySkeleton(bones, true);\n const err = (s: XraySkeleton) => {\n let e = 0, c = 0;\n for (const m of meshes) {\n if (!m.skinned) continue;\n const step = Math.max(1, Math.floor(m.vertexCount / 1500));\n for (let v = 0; v < m.vertexCount; v += step) {\n let bi = m.bone[v * 4]!, bw = m.weight[v * 4]!;\n for (let k = 1; k < 4; k++) if (m.weight[v * 4 + k]! > bw) { bw = m.weight[v * 4 + k]!; bi = m.bone[v * 4 + k]!; }\n const W = s.bindWorldV[bi]!;\n e += Math.hypot(m.pos[v * 3]! - W[12]!, m.pos[v * 3 + 1]! - W[13]!, m.pos[v * 3 + 2]! - W[14]!);\n c++;\n }\n }\n return c ? e / c : 0;\n };\n const ea = err(a), eb = err(b);\n const s = eb < ea * 0.98 ? b : a;\n s.bindVariant = s === b ? 'B (транспонированный)' : 'A';\n s.bindErr = [ea, eb];\n return s;\n }\n\n pose(motion: Motion | null, time: number, loop: boolean, invQ = false): void {\n if (!this.n) return;\n const m = motion && motion.kind === 'xray' ? motion : null;\n // frames of the main animation and of the layers (each has its own length; layers always loop)\n const frame = (x: XrayMotion, lp: boolean): [number, number, number] => {\n const F = x.frames;\n let fr = time * FPS;\n fr = lp ? ((fr % F) + F) % F : Math.min(Math.max(fr, 0), F - 1);\n const f0 = Math.floor(fr);\n return [f0, lp ? (f0 + 1) % F : Math.min(f0 + 1, F - 1), fr - f0];\n };\n const list: Array<[XrayMotion, number, number, number]> = m ? [[m, ...frame(m, loop)], ...(m.layers ?? []).map((x): [XrayMotion, number, number, number] => [x, ...frame(x, true)])] : [];\n for (const i of this.order) {\n const L = this.scratch;\n let done = false;\n for (const [x, f0, f1, a] of list) { const tr = x.tracks[i]; if (tr) { trackLocal(tr, f0, f1, a, invQ, L); done = true; break; } }\n if (!done) L.set(this.bindLocalV[i]!);\n const p = this.parent[i]!;\n if (p < 0) this.worldV[i]!.set(L); else mulRow(L, this.worldV[p]!, this.worldV[i]!);\n mulRow(this.invV[i]!, this.worldV[i]!, this.skinV[i]!);\n }\n }\n\n /** Automatic quaternion sign selection: with the right variant, mesh edge lengths barely change. */\n detectInvert(meshes: readonly Mesh[], motion: XrayMotion): boolean {\n const s0 = this.motionError(meshes, motion, false), s1 = this.motionError(meshes, motion, true);\n return s1 < s0 * 0.9;\n }\n\n /** Mesh distortion by an animation: the mean relative edge length error over three frames (0 = edges do not stretch). */\n motionError(meshes: readonly Mesh[], motion: XrayMotion, inv: boolean): number {\n const edges: Array<[Mesh, number, number]> = [];\n for (const m of meshes) {\n if (!m.skinned) continue;\n const tc = m.indices.length / 3, step = Math.max(1, Math.floor(tc / 1500));\n for (let t = 0; t < tc; t += step) edges.push([m, m.indices[t * 3]!, m.indices[t * 3 + 1]!]);\n }\n if (!edges.length) return 0;\n const sk = (m: Mesh, v: number, o: number[]) => {\n const x = m.pos[v * 3]!, y = m.pos[v * 3 + 1]!, z = m.pos[v * 3 + 2]!;\n o[0] = o[1] = o[2] = 0;\n for (let k = 0; k < 4; k++) {\n const w = m.weight[v * 4 + k]!;\n if (!w) continue;\n const M = this.skinV[m.bone[v * 4 + k]!]!;\n o[0] += w * (x * M[0]! + y * M[4]! + z * M[8]! + M[12]!); o[1] += w * (x * M[1]! + y * M[5]! + z * M[9]! + M[13]!); o[2] += w * (x * M[2]! + y * M[6]! + z * M[10]! + M[14]!);\n }\n };\n const A = [0, 0, 0], B = [0, 0, 0];\n const score = (inv: boolean) => {\n let d = 0, l = 0;\n for (const fr of [0, Math.floor(motion.frames / 2), motion.frames - 1]) {\n this.pose(motion, fr / FPS, false, inv);\n for (const [m, a, b] of edges) {\n sk(m, a, A); sk(m, b, B);\n const l1 = Math.hypot(A[0]! - B[0]!, A[1]! - B[1]!, A[2]! - B[2]!);\n const l0 = Math.hypot(m.pos[a * 3]! - m.pos[b * 3]!, m.pos[a * 3 + 1]! - m.pos[b * 3 + 1]!, m.pos[a * 3 + 2]! - m.pos[b * 3 + 2]!);\n d += Math.abs(l1 - l0); l += l0;\n }\n }\n return d / (l || 1);\n };\n return score(inv);\n }\n}\n\n"],"names":["s","inv"],"mappings":"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"}