From a60c69a3ef3d26027f44f2f500806be04d56cd11 Mon Sep 17 00:00:00 2001 From: Daan Vanden Bosch Date: Tue, 9 Jul 2019 20:22:18 +0200 Subject: [PATCH] Refactored area render geometry code. --- src/data_formats/cursor/ArrayBufferCursor.ts | 5 + src/data_formats/cursor/Cursor.ts | 11 +- .../cursor/ResizableBufferCursor.ts | 5 + .../parsing/area_collision_geometry.test.ts | 21 ++ .../parsing/area_collision_geometry.ts | 6 +- src/data_formats/parsing/area_geometry.ts | 312 +++++------------- src/data_formats/parsing/itempmt.test.ts | 18 + src/data_formats/parsing/itempmt.ts | 34 +- src/data_formats/parsing/ninja/index.ts | 4 +- src/data_formats/parsing/ninja/motion.ts | 5 +- src/data_formats/parsing/ninja/xj.ts | 69 ++-- src/data_formats/parsing/rel.ts | 44 +++ src/domain/index.ts | 48 ++- src/rendering/QuestRenderer.ts | 19 +- src/rendering/areas.ts | 48 +++ src/rendering/models.ts | 104 +----- src/rendering/xj_model_to_geometry.ts | 94 ++++++ src/stores/AreaStore.ts | 66 ++-- src/stores/QuestEditorStore.ts | 8 +- test/resources/ItemPMT.bin | Bin 0 -> 86880 bytes test/resources/map_forest01c.rel | Bin 0 -> 72096 bytes 21 files changed, 450 insertions(+), 471 deletions(-) create mode 100644 src/data_formats/parsing/area_collision_geometry.test.ts create mode 100644 src/data_formats/parsing/itempmt.test.ts create mode 100644 src/data_formats/parsing/rel.ts create mode 100644 src/rendering/xj_model_to_geometry.ts create mode 100644 test/resources/ItemPMT.bin create mode 100644 test/resources/map_forest01c.rel diff --git a/src/data_formats/cursor/ArrayBufferCursor.ts b/src/data_formats/cursor/ArrayBufferCursor.ts index 5406ca73..bcdf420a 100644 --- a/src/data_formats/cursor/ArrayBufferCursor.ts +++ b/src/data_formats/cursor/ArrayBufferCursor.ts @@ -7,6 +7,7 @@ import { } from "."; import { Endianness } from ".."; import { Cursor } from "./Cursor"; +import { Vec3 } from "../Vec3"; /** * A cursor for reading from an array buffer or part of an array buffer. @@ -186,6 +187,10 @@ export class ArrayBufferCursor implements Cursor { return array; } + vec3(): Vec3 { + return new Vec3(this.f32(), this.f32(), this.f32()); + } + take(size: number): ArrayBufferCursor { const offset = this.offset + this.position; const wrapper = new ArrayBufferCursor(this.buffer, this.endianness, offset, size); diff --git a/src/data_formats/cursor/Cursor.ts b/src/data_formats/cursor/Cursor.ts index d6e07ab9..a5156d68 100644 --- a/src/data_formats/cursor/Cursor.ts +++ b/src/data_formats/cursor/Cursor.ts @@ -1,4 +1,5 @@ import { Endianness } from ".."; +import { Vec3 } from "../Vec3"; /** * A cursor for reading binary data. @@ -24,21 +25,21 @@ export interface Cursor { /** * Seek forward or backward by a number of bytes. * - * @param offset - if positive, seeks forward by offset bytes, otherwise seeks backward by -offset bytes. + * @param offset if positive, seeks forward by offset bytes, otherwise seeks backward by -offset bytes. */ seek(offset: number): this; /** * Seek forward from the start of the cursor by a number of bytes. * - * @param offset - greater or equal to 0 and smaller than size + * @param offset greater or equal to 0 and smaller than size */ seek_start(offset: number): this; /** * Seek backward from the end of the cursor by a number of bytes. * - * @param offset - greater or equal to 0 and smaller than size + * @param offset greater or equal to 0 and smaller than size */ seek_end(offset: number): this; @@ -127,10 +128,12 @@ export interface Cursor { */ u32_array(n: number): number[]; + vec3(): Vec3; + /** * Consumes a variable number of bytes. * - * @param size - the amount bytes to consume. + * @param size the amount bytes to consume. * @returns a write-through view containing size bytes. */ take(size: number): Cursor; diff --git a/src/data_formats/cursor/ResizableBufferCursor.ts b/src/data_formats/cursor/ResizableBufferCursor.ts index a89a072d..3abb0d9d 100644 --- a/src/data_formats/cursor/ResizableBufferCursor.ts +++ b/src/data_formats/cursor/ResizableBufferCursor.ts @@ -8,6 +8,7 @@ import { import { Endianness } from ".."; import { ResizableBuffer } from "../ResizableBuffer"; import { Cursor } from "./Cursor"; +import { Vec3 } from "../Vec3"; export class ResizableBufferCursor implements Cursor { private _offset: number; @@ -213,6 +214,10 @@ export class ResizableBufferCursor implements Cursor { return array; } + vec3(): Vec3 { + return new Vec3(this.f32(), this.f32(), this.f32()); + } + take(size: number): ResizableBufferCursor { this.check_size("size", size, size); diff --git a/src/data_formats/parsing/area_collision_geometry.test.ts b/src/data_formats/parsing/area_collision_geometry.test.ts new file mode 100644 index 00000000..f2a5ad5b --- /dev/null +++ b/src/data_formats/parsing/area_collision_geometry.test.ts @@ -0,0 +1,21 @@ +import { readFileSync } from "fs"; +import { parse_area_collision_geometry } from "./area_collision_geometry"; +import { BufferCursor } from "../cursor/BufferCursor"; +import { Endianness } from ".."; + +test("parse_area_collision_geometry", () => { + const buf = readFileSync("test/resources/map_forest01c.rel"); + const object = parse_area_collision_geometry(new BufferCursor(buf, Endianness.Little)); + + expect(object.meshes.length).toBe(69); + expect(object.meshes[0].vertices.length).toBe(11); + expect(object.meshes[0].vertices[0].x).toBeCloseTo(-589.5195, 4); + expect(object.meshes[0].vertices[0].y).toBeCloseTo(16.7166, 4); + expect(object.meshes[0].vertices[0].z).toBeCloseTo(-218.6852, 4); + expect(object.meshes[0].triangles.length).toBe(12); + expect(object.meshes[0].triangles[0].flags).toBe(0b100000001); + expect(object.meshes[0].triangles[0].indices).toEqual([5, 0, 7]); + expect(object.meshes[0].triangles[0].normal.x).toBeCloseTo(0.0137, 4); + expect(object.meshes[0].triangles[0].normal.y).toBeCloseTo(0.9994, 4); + expect(object.meshes[0].triangles[0].normal.z).toBeCloseTo(-0.0307, 4); +}); diff --git a/src/data_formats/parsing/area_collision_geometry.ts b/src/data_formats/parsing/area_collision_geometry.ts index 5d91ae0f..e6e240f1 100644 --- a/src/data_formats/parsing/area_collision_geometry.ts +++ b/src/data_formats/parsing/area_collision_geometry.ts @@ -1,5 +1,6 @@ import { Cursor } from "../cursor/Cursor"; import { Vec3 } from "../Vec3"; +import { parse_rel } from "./rel"; export type CollisionObject = { meshes: CollisionMesh[]; @@ -17,9 +18,8 @@ export type CollisionTriangle = { }; export function parse_area_collision_geometry(cursor: Cursor): CollisionObject { - cursor.seek_end(16); - const main_block_offset = cursor.u32(); - cursor.seek_start(main_block_offset); + const { data_offset } = parse_rel(cursor, false); + cursor.seek_start(data_offset); const main_offset_table_offset = cursor.u32(); cursor.seek_start(main_offset_table_offset); diff --git a/src/data_formats/parsing/area_geometry.ts b/src/data_formats/parsing/area_geometry.ts index b01fb829..12a74b96 100644 --- a/src/data_formats/parsing/area_geometry.ts +++ b/src/data_formats/parsing/area_geometry.ts @@ -1,257 +1,101 @@ -import Logger from "js-logger"; -import { - BufferGeometry, - DoubleSide, - Float32BufferAttribute, - Mesh, - MeshLambertMaterial, - Object3D, - TriangleStripDrawMode, - Uint16BufferAttribute, -} from "three"; -import { Section } from "../../domain"; +import { Cursor } from "../cursor/Cursor"; import { Vec3 } from "../Vec3"; +import { ANGLE_TO_RAD } from "./ninja"; +import { parse_xj_model, XjModel } from "./ninja/xj"; +import { parse_rel } from "./rel"; -const logger = Logger.get("data_formats/parsing/area_geometry"); +export type RenderObject = { + sections: RenderSection[]; +}; -export function parse_area_geometry( - array_buffer: ArrayBuffer -): { sections: Section[]; object_3d: Object3D } { - const dv = new DataView(array_buffer); - const sections = new Map(); +export type RenderSection = { + id: number; + position: Vec3; + rotation: Vec3; + models: XjModel[]; +}; - const object = new Object3D(); +export type Vertex = { + position: Vec3; + normal?: Vec3; +}; - const main_block_offset = dv.getUint32(dv.byteLength - 16, true); - const section_count = dv.getUint32(main_block_offset + 8, true); - const section_table_offset = dv.getUint32(main_block_offset + 16, true); - // const texture_name_offset = dv.getUint32(main_block_offset + 20, true); +export function parse_area_geometry(cursor: Cursor): RenderObject { + const sections: RenderSection[] = []; - for (let i = section_table_offset; i < section_table_offset + section_count * 52; i += 52) { - const section_id = dv.getInt32(i, true); - const section_x = dv.getFloat32(i + 4, true); - const section_y = dv.getFloat32(i + 8, true); - const section_z = dv.getFloat32(i + 12, true); - const section_rotation = (dv.getInt32(i + 20, true) / 0xffff) * 2 * Math.PI; - const section = new Section( - section_id, - new Vec3(section_x, section_y, section_z), - section_rotation + cursor.seek_end(16); + + const { data_offset } = parse_rel(cursor, false); + cursor.seek_start(data_offset); + cursor.seek(8); // Format "fmt2" in UTF-16. + const section_count = cursor.u32(); + cursor.seek(4); + const section_table_offset = cursor.u32(); + // const texture_name_offset = cursor.u32(); + + for (let i = 0; i < section_count; i++) { + cursor.seek_start(section_table_offset + 52 * i); + + const section_id = cursor.i32(); + const section_position = cursor.vec3(); + const section_rotation = new Vec3( + cursor.u32() * ANGLE_TO_RAD, + cursor.u32() * ANGLE_TO_RAD, + cursor.u32() * ANGLE_TO_RAD ); - sections.set(section_id, section); - const index_lists_list = []; - const position_lists_list = []; - const normal_lists_list = []; + cursor.seek(4); - const simple_geometry_offset_table_offset = dv.getUint32(i + 32, true); - // const complex_geometry_offset_table_offset = dv.getUint32(i + 36, true); - const simple_geometry_offset_count = dv.getUint32(i + 40, true); - // const complex_geometry_offset_count = dv.getUint32(i + 44, true); + const simple_geometry_offset_table_offset = cursor.u32(); + // const animated_geometry_offset_table_offset = cursor.u32(); + cursor.seek(4); + const simple_geometry_offset_count = cursor.u32(); + // const animated_geometry_offset_count = cursor.u32(); + // Ignore animated_geometry_offset_count and the last 4 bytes. - for ( - let j = simple_geometry_offset_table_offset; - j < simple_geometry_offset_table_offset + simple_geometry_offset_count * 16; - j += 16 - ) { - let offset = dv.getUint32(j, true); - const flags = dv.getUint32(j + 12, true); + const models = parse_geometry_table( + cursor, + simple_geometry_offset_table_offset, + simple_geometry_offset_count + ); - if (flags & 0b100) { - offset = dv.getUint32(offset, true); - } + sections.push({ + id: section_id, + position: section_position, + rotation: section_rotation, + models, + }); + } - const geometry_offset = dv.getUint32(offset + 4, true); + return { sections }; +} - if (geometry_offset > 0) { - const vertex_info_table_offset = dv.getUint32(geometry_offset + 4, true); - const vertex_info_count = dv.getUint32(geometry_offset + 8, true); - const triangle_strip_table_offset = dv.getUint32(geometry_offset + 12, true); - const triangle_strip_count = dv.getUint32(geometry_offset + 16, true); - // const transparent_object_table_offset = dv.getUint32(blockOffset + 20, true); - // const transparent_object_count = dv.getUint32(blockOffset + 24, true); +function parse_geometry_table( + cursor: Cursor, + table_offset: number, + table_entry_count: number +): XjModel[] { + const models: XjModel[] = []; - const geom_index_lists = []; + for (let i = 0; i < table_entry_count; i++) { + cursor.seek_start(table_offset + 16 * i); - for ( - let k = triangle_strip_table_offset; - k < triangle_strip_table_offset + triangle_strip_count * 20; - k += 20 - ) { - // const flag_and_texture_id_offset = dv.getUint32(k, true); - // const data_type = dv.getUint32(k + 4, true); - const triangle_strip_index_table_offset = dv.getUint32(k + 8, true); - const triangle_strip_index_count = dv.getUint32(k + 12, true); + let offset = cursor.u32(); + cursor.seek(8); + const flags = cursor.u32(); - const triangle_strip_indices = []; - - for ( - let l = triangle_strip_index_table_offset; - l < triangle_strip_index_table_offset + triangle_strip_index_count * 2; - l += 2 - ) { - triangle_strip_indices.push(dv.getUint16(l, true)); - } - - geom_index_lists.push(triangle_strip_indices); - - // TODO: Read texture info. - } - - // TODO: Do the previous for the transparent index table. - - // Assume vertexInfoCount == 1. TODO: Does that make sense? - if (vertex_info_count > 1) { - logger.warn( - `Vertex info count of ${vertex_info_count} was larger than expected.` - ); - } - - // const vertex_type = dv.getUint32(vertexInfoTableOffset, true); - const vertex_table_offset = dv.getUint32(vertex_info_table_offset + 4, true); - const vertex_size = dv.getUint32(vertex_info_table_offset + 8, true); - const vertex_count = dv.getUint32(vertex_info_table_offset + 12, true); - - const geom_positions = []; - const geom_normals = []; - - for ( - let k = vertex_table_offset; - k < vertex_table_offset + vertex_count * vertex_size; - k += vertex_size - ) { - let n_x, n_y, n_z; - - switch (vertex_size) { - case 16: - case 24: - // TODO: are these values sensible? - n_x = 0; - n_y = 1; - n_z = 0; - break; - case 28: - case 36: - n_x = dv.getFloat32(k + 12, true); - n_y = dv.getFloat32(k + 16, true); - n_z = dv.getFloat32(k + 20, true); - // TODO: color, texture coords. - break; - default: - logger.error(`Unexpected vertex size of ${vertex_size}.`); - continue; - } - - const x = dv.getFloat32(k, true); - const y = dv.getFloat32(k + 4, true); - const z = dv.getFloat32(k + 8, true); - const rotated_x = - section.cos_y_axis_rotation * x + section.sin_y_axis_rotation * z; - const rotated_z = - -section.sin_y_axis_rotation * x + section.cos_y_axis_rotation * z; - - geom_positions.push(section_x + rotated_x); - geom_positions.push(section_y + y); - geom_positions.push(section_z + rotated_z); - geom_normals.push(n_x); - geom_normals.push(n_y); - geom_normals.push(n_z); - } - - index_lists_list.push(geom_index_lists); - position_lists_list.push(geom_positions); - normal_lists_list.push(geom_normals); - } + if (flags & 0b100) { + offset = cursor.seek_start(offset).u32(); } - // function vEqual(v, w) { - // return v[0] === w[0] && v[1] === w[1] && v[2] === w[2]; - // } + cursor.seek_start(offset + 4); + const geometry_offset = cursor.u32(); - for (let i = 0; i < position_lists_list.length; ++i) { - const positions = position_lists_list[i]; - const normals = normal_lists_list[i]; - const geom_index_lists = index_lists_list[i]; - // const indices = []; - - geom_index_lists.forEach(object_indices => { - // for (let j = 2; j < objectIndices.length; ++j) { - // const a = objectIndices[j - 2]; - // const b = objectIndices[j - 1]; - // const c = objectIndices[j]; - - // if (a !== b && a !== c && b !== c) { - // const ap = positions.slice(3 * a, 3 * a + 3); - // const bp = positions.slice(3 * b, 3 * b + 3); - // const cp = positions.slice(3 * c, 3 * c + 3); - - // if (!vEqual(ap, bp) && !vEqual(ap, cp) && !vEqual(bp, cp)) { - // if (j % 2 === 0) { - // indices.push(a); - // indices.push(b); - // indices.push(c); - // } else { - // indices.push(b); - // indices.push(a); - // indices.push(c); - // } - // } - // } - // } - - const geometry = new BufferGeometry(); - geometry.addAttribute("position", new Float32BufferAttribute(positions, 3)); - geometry.addAttribute("normal", new Float32BufferAttribute(normals, 3)); - geometry.setIndex(new Uint16BufferAttribute(object_indices, 1)); - - const mesh = new Mesh( - geometry, - new MeshLambertMaterial({ - color: 0x44aaff, - // transparent: true, - opacity: 0.25, - side: DoubleSide, - }) - ); - mesh.setDrawMode(TriangleStripDrawMode); - mesh.userData.section = section; - object.add(mesh); - }); - - // const geometry = new BufferGeometry(); - // geometry.addAttribute( - // 'position', new BufferAttribute(new Float32Array(positions), 3)); - // geometry.addAttribute( - // 'normal', new BufferAttribute(new Float32Array(normals), 3)); - // geometry.setIndex(new BufferAttribute(new Uint16Array(indices), 1)); - - // const mesh = new Mesh( - // geometry, - // new MeshLambertMaterial({ - // color: 0x44aaff, - // transparent: true, - // opacity: 0.25, - // side: DoubleSide - // }) - // ); - // object.add(mesh); - - // const wireframeMesh = new Mesh( - // geometry, - // new MeshBasicMaterial({ - // color: 0x88ccff, - // wireframe: true, - // transparent: true, - // opacity: 0.75, - // }) - // ); - // wireframeMesh.setDrawMode(THREE.TriangleStripDrawMode); - // object.add(wireframeMesh); + if (geometry_offset > 0) { + cursor.seek_start(geometry_offset); + models.push(parse_xj_model(cursor)); } } - return { - sections: [...sections.values()].sort((a, b) => a.id - b.id), - object_3d: object, - }; + return models; } diff --git a/src/data_formats/parsing/itempmt.test.ts b/src/data_formats/parsing/itempmt.test.ts new file mode 100644 index 00000000..855b270b --- /dev/null +++ b/src/data_formats/parsing/itempmt.test.ts @@ -0,0 +1,18 @@ +import { parse_item_pmt } from "./itempmt"; +import { readFileSync } from "fs"; +import { BufferCursor } from "../cursor/BufferCursor"; +import { Endianness } from ".."; + +test("parse_item_pmt", () => { + const buf = readFileSync("test/resources/ItemPMT.bin"); + const item_pmt = parse_item_pmt(new BufferCursor(buf, Endianness.Little)); + + const saber = item_pmt.weapons[1][0]; + + expect(saber.id).toBe(177); + expect(saber.min_atp).toBe(40); + expect(saber.max_atp).toBe(55); + expect(saber.ata).toBe(30); + expect(saber.max_grind).toBe(35); + expect(saber.req_atp).toBe(30); +}); diff --git a/src/data_formats/parsing/itempmt.ts b/src/data_formats/parsing/itempmt.ts index c1d26389..b5a45cd9 100644 --- a/src/data_formats/parsing/itempmt.ts +++ b/src/data_formats/parsing/itempmt.ts @@ -1,4 +1,5 @@ import { Cursor } from "../cursor/Cursor"; +import { parse_rel } from "./rel"; export type ItemPmt = { stat_boosts: PmtStatBoost[]; @@ -95,43 +96,24 @@ export type PmtTool = { }; export function parse_item_pmt(cursor: Cursor): ItemPmt { - cursor.seek_end(32); - const main_table_offset = cursor.u32(); - const main_table_size = cursor.u32(); - // const main_table_count = cursor.u32(); // Should be 1. - - cursor.seek_start(main_table_offset); - - const compact_table_offsets = cursor.u16_array(main_table_size); - const table_offsets: { offset: number; size: number }[] = []; - let expanded_offset = 0; - - for (const compact_offset of compact_table_offsets) { - expanded_offset = expanded_offset + 4 * compact_offset; - cursor.seek_start(expanded_offset - 4); - const size = cursor.u32(); - const offset = cursor.u32(); - table_offsets.push({ offset, size }); - } + const { index } = parse_rel(cursor, true); const item_pmt: ItemPmt = { // This size (65268) of this table seems wrong, so we pass in a hard-coded value. - stat_boosts: parse_stat_boosts(cursor, table_offsets[305].offset, 52), - armors: parse_armors(cursor, table_offsets[7].offset, table_offsets[7].size), - shields: parse_shields(cursor, table_offsets[8].offset, table_offsets[8].size), - units: parse_units(cursor, table_offsets[9].offset, table_offsets[9].size), + stat_boosts: parse_stat_boosts(cursor, index[305].offset, 52), + armors: parse_armors(cursor, index[7].offset, index[7].size), + shields: parse_shields(cursor, index[8].offset, index[8].size), + units: parse_units(cursor, index[9].offset, index[9].size), tools: [], weapons: [], }; for (let i = 11; i <= 37; i++) { - item_pmt.tools.push(parse_tools(cursor, table_offsets[i].offset, table_offsets[i].size)); + item_pmt.tools.push(parse_tools(cursor, index[i].offset, index[i].size)); } for (let i = 38; i <= 275; i++) { - item_pmt.weapons.push( - parse_weapons(cursor, table_offsets[i].offset, table_offsets[i].size) - ); + item_pmt.weapons.push(parse_weapons(cursor, index[i].offset, index[i].size)); } return item_pmt; diff --git a/src/data_formats/parsing/ninja/index.ts b/src/data_formats/parsing/ninja/index.ts index 82d7ee63..95c91a0f 100644 --- a/src/data_formats/parsing/ninja/index.ts +++ b/src/data_formats/parsing/ninja/index.ts @@ -1,13 +1,13 @@ +import { Cursor } from "../../cursor/Cursor"; import { Vec3 } from "../../Vec3"; import { NjcmModel, parse_njcm_model } from "./njcm"; import { parse_xj_model, XjModel } from "./xj"; -import { Cursor } from "../../cursor/Cursor"; // TODO: // - deal with multiple NJCM chunks // - deal with other types of chunks -const ANGLE_TO_RAD = (2 * Math.PI) / 65536; +export const ANGLE_TO_RAD = (2 * Math.PI) / 0xffff; export type NjVertex = { position: Vec3; diff --git a/src/data_formats/parsing/ninja/motion.ts b/src/data_formats/parsing/ninja/motion.ts index 20d03133..5767184e 100644 --- a/src/data_formats/parsing/ninja/motion.ts +++ b/src/data_formats/parsing/ninja/motion.ts @@ -1,7 +1,6 @@ -import { Vec3 } from "../../Vec3"; +import { ANGLE_TO_RAD } from "."; import { Cursor } from "../../cursor/Cursor"; - -const ANGLE_TO_RAD = (2 * Math.PI) / 0xffff; +import { Vec3 } from "../../Vec3"; export type NjMotion = { motion_data: NjMotionData[]; diff --git a/src/data_formats/parsing/ninja/xj.ts b/src/data_formats/parsing/ninja/xj.ts index fe3dfe42..dda64b75 100644 --- a/src/data_formats/parsing/ninja/xj.ts +++ b/src/data_formats/parsing/ninja/xj.ts @@ -1,7 +1,10 @@ +import Logger from "js-logger"; import { Cursor } from "../../cursor/Cursor"; import { Vec3 } from "../../Vec3"; import { NjVertex } from "../ninja"; +const logger = Logger.get("data_formats/parsing/ninja/xj"); + // TODO: // - textures // - colors @@ -11,7 +14,9 @@ import { NjVertex } from "../ninja"; export type XjModel = { type: "xj"; vertices: NjVertex[]; - meshes: XjTriangleStrip[]; + strips: XjTriangleStrip[]; + collision_sphere_position: Vec3; + collision_sphere_radius: number; }; export type XjTriangleStrip = { @@ -20,34 +25,42 @@ export type XjTriangleStrip = { export function parse_xj_model(cursor: Cursor): XjModel { cursor.seek(4); // Flags according to QEdit, seemingly always 0. - const vertex_info_list_offset = cursor.u32(); - cursor.seek(4); // Seems to be the vertexInfoCount, always 1. - const triangle_strip_list_a_offset = cursor.u32(); - const triangle_strip_a_count = cursor.u32(); - const triangle_strip_list_b_offset = cursor.u32(); - const triangle_strip_b_count = cursor.u32(); - cursor.seek(16); // Bounding sphere position and radius in floats. + const vertex_info_table_offset = cursor.u32(); + const vertex_info_count = cursor.u32(); + const triangle_strip_table_offset = cursor.u32(); + const triangle_strip_count = cursor.u32(); + const transparent_triangle_strip_table_offset = cursor.u32(); + const transparent_triangle_strip_count = cursor.u32(); + const collision_sphere_position = cursor.vec3(); + const collision_sphere_radius = cursor.f32(); const model: XjModel = { type: "xj", vertices: [], - meshes: [], + strips: [], + collision_sphere_position, + collision_sphere_radius, }; - if (vertex_info_list_offset) { - cursor.seek_start(vertex_info_list_offset); - cursor.seek(4); // Possibly the vertex type. - const vertexList_offset = cursor.u32(); + if (vertex_info_count >= 1) { + if (vertex_info_count > 1) { + logger.warn(`Vertex info count of ${vertex_info_count} was larger than expected.`); + } + + cursor.seek_start(vertex_info_table_offset); + cursor.seek(4); // Vertex type. + const vertex_table_offset = cursor.u32(); const vertex_size = cursor.u32(); const vertex_count = cursor.u32(); for (let i = 0; i < vertex_count; ++i) { - cursor.seek_start(vertexList_offset + i * vertex_size); - const position = new Vec3(cursor.f32(), cursor.f32(), cursor.f32()); + cursor.seek_start(vertex_table_offset + i * vertex_size); + + const position = cursor.vec3(); let normal: Vec3 | undefined; if (vertex_size === 28 || vertex_size === 32 || vertex_size === 36) { - normal = new Vec3(cursor.f32(), cursor.f32(), cursor.f32()); + normal = cursor.vec3(); } model.vertices.push({ @@ -60,22 +73,18 @@ export function parse_xj_model(cursor: Cursor): XjModel { } } - if (triangle_strip_list_a_offset) { - model.meshes.push( - ...parse_triangle_strip_list( - cursor, - triangle_strip_list_a_offset, - triangle_strip_a_count - ) + if (triangle_strip_table_offset) { + model.strips.push( + ...parse_triangle_strip_table(cursor, triangle_strip_table_offset, triangle_strip_count) ); } - if (triangle_strip_list_b_offset) { - model.meshes.push( - ...parse_triangle_strip_list( + if (transparent_triangle_strip_table_offset) { + model.strips.push( + ...parse_triangle_strip_table( cursor, - triangle_strip_list_b_offset, - triangle_strip_b_count + transparent_triangle_strip_table_offset, + transparent_triangle_strip_count ) ); } @@ -83,7 +92,7 @@ export function parse_xj_model(cursor: Cursor): XjModel { return model; } -function parse_triangle_strip_list( +function parse_triangle_strip_table( cursor: Cursor, triangle_strip_list_offset: number, triangle_strip_count: number @@ -92,7 +101,7 @@ function parse_triangle_strip_list( for (let i = 0; i < triangle_strip_count; ++i) { cursor.seek_start(triangle_strip_list_offset + i * 20); - cursor.seek(8); // Skip material information. + cursor.seek(8); // Skip flag_and_texture_id_offset and data_type. const index_list_offset = cursor.u32(); const index_count = cursor.u32(); // Ignoring 4 bytes. diff --git a/src/data_formats/parsing/rel.ts b/src/data_formats/parsing/rel.ts new file mode 100644 index 00000000..2374f02f --- /dev/null +++ b/src/data_formats/parsing/rel.ts @@ -0,0 +1,44 @@ +import { Cursor } from "../cursor/Cursor"; + +export type Rel = { + data_offset: number; + index: RelIndexEntry[]; +}; + +export type RelIndexEntry = { + offset: number; + size: number; +}; + +export function parse_rel(cursor: Cursor, parse_index: boolean): Rel { + cursor.seek_end(32); + + const index_offset = cursor.u32(); + const index_size = cursor.u32(); + cursor.seek(8); // Typically 1, 0, 0,... + const data_offset = cursor.u32(); + // Typically followed by 12 nul bytes. + + cursor.seek_start(index_offset); + const index = parse_index ? parse_indices(cursor, index_size) : []; + + return { data_offset, index }; +} + +function parse_indices(cursor: Cursor, index_size: number): RelIndexEntry[] { + const compact_offsets = cursor.u16_array(index_size); + const index: RelIndexEntry[] = []; + let expanded_offset = 0; + + for (const compact_offset of compact_offsets) { + expanded_offset = expanded_offset + 4 * compact_offset; + + // Size is not always present. + cursor.seek_start(expanded_offset - 4); + const size = cursor.u32(); + const offset = cursor.u32(); + index.push({ offset, size }); + } + + return index; +} diff --git a/src/domain/index.ts b/src/domain/index.ts index a66235eb..b2d41afd 100644 --- a/src/domain/index.ts +++ b/src/domain/index.ts @@ -59,17 +59,11 @@ export enum Difficulty { export const Difficulties: Difficulty[] = enum_values(Difficulty); export class Section { - id: number; - @observable position: Vec3; - @observable y_axis_rotation: number; - - @computed get sin_y_axis_rotation(): number { - return Math.sin(this.y_axis_rotation); - } - - @computed get cos_y_axis_rotation(): number { - return Math.cos(this.y_axis_rotation); - } + readonly id: number; + readonly position: Vec3; + readonly y_axis_rotation: number; + readonly sin_y_axis_rotation: number; + readonly cos_y_axis_rotation: number; constructor(id: number, position: Vec3, y_axis_rotation: number) { if (!Number.isInteger(id) || id < -1) @@ -80,6 +74,8 @@ export class Section { this.id = id; this.position = position; this.y_axis_rotation = y_axis_rotation; + this.sin_y_axis_rotation = Math.sin(this.y_axis_rotation); + this.cos_y_axis_rotation = Math.cos(this.y_axis_rotation); } } @@ -160,32 +156,32 @@ export class QuestEntity { let { x, y, z } = this.position; if (this.section) { - const relX = x - this.section.position.x; - const relY = y - this.section.position.y; - const relZ = z - this.section.position.z; + const rel_x = x - this.section.position.x; + const rel_y = y - this.section.position.y; + const rel_z = z - this.section.position.z; const sin = -this.section.sin_y_axis_rotation; const cos = this.section.cos_y_axis_rotation; - const rotX = cos * relX + sin * relZ; - const rotZ = -sin * relX + cos * relZ; - x = rotX; - y = relY; - z = rotZ; + const rot_x = cos * rel_x + sin * rel_z; + const rot_z = -sin * rel_x + cos * rel_z; + x = rot_x; + y = rel_y; + z = rot_z; } return new Vec3(x, y, z); } - set section_position(sectPos: Vec3) { - let { x: relX, y: relY, z: relZ } = sectPos; + set section_position(sec_pos: Vec3) { + let { x: rel_x, y: rel_y, z: rel_z } = sec_pos; if (this.section) { const sin = -this.section.sin_y_axis_rotation; const cos = this.section.cos_y_axis_rotation; - const rotX = cos * relX - sin * relZ; - const rotZ = sin * relX + cos * relZ; - const x = rotX + this.section.position.x; - const y = relY + this.section.position.y; - const z = rotZ + this.section.position.z; + const rot_x = cos * rel_x - sin * rel_z; + const rot_z = sin * rel_x + cos * rel_z; + const x = rot_x + this.section.position.x; + const y = rel_y + this.section.position.y; + const z = rot_z + this.section.position.z; this.position = new Vec3(x, y, z); } } diff --git a/src/rendering/QuestRenderer.ts b/src/rendering/QuestRenderer.ts index 58929a52..002a108e 100644 --- a/src/rendering/QuestRenderer.ts +++ b/src/rendering/QuestRenderer.ts @@ -1,4 +1,4 @@ -import { autorun, IReactionDisposer, when } from "mobx"; +import { autorun, IReactionDisposer, when, runInAction } from "mobx"; import { Intersection, Mesh, @@ -98,6 +98,7 @@ export class QuestRenderer extends Renderer { this.scene.add(this.npc_geometry); this.scene.remove(this.collision_geometry); + // this.scene.remove(this.render_geometry); if (this.quest && this.area) { // Add necessary entity geometry when it arrives. @@ -122,6 +123,7 @@ export class QuestRenderer extends Renderer { ); this.scene.remove(this.collision_geometry); + // this.scene.remove(this.render_geometry); this.reset_camera(new Vector3(0, 800, 700), new Vector3(0, 0, 0)); @@ -135,6 +137,7 @@ export class QuestRenderer extends Renderer { ); this.render_geometry = render_geometry; + // this.scene.add(render_geometry); } } @@ -263,12 +266,14 @@ export class QuestRenderer extends Renderer { const { intersection, section } = this.pick_terrain(pointer_pos, data); if (intersection) { - data.entity.position = new Vec3( - intersection.point.x, - intersection.point.y + data.drag_y, - intersection.point.z - ); - data.entity.section = section; + runInAction(() => { + data.entity.position = new Vec3( + intersection.point.x, + intersection.point.y + data.drag_y, + intersection.point.z + ); + data.entity.section = section; + }); } else { // If the cursor is not over any terrain, we translate the entity accross the horizontal plane in which the entity's origin lies. this.raycaster.setFromCamera(pointer_pos, this.camera); diff --git a/src/rendering/areas.ts b/src/rendering/areas.ts index 584d2cbc..b018c83d 100644 --- a/src/rendering/areas.ts +++ b/src/rendering/areas.ts @@ -1,15 +1,22 @@ import { + BufferGeometry, DoubleSide, Face3, + Float32BufferAttribute, Geometry, Group, + Matrix4, Mesh, MeshBasicMaterial, MeshLambertMaterial, Object3D, + Uint16BufferAttribute, Vector3, } from "three"; import { CollisionObject } from "../data_formats/parsing/area_collision_geometry"; +import { RenderObject } from "../data_formats/parsing/area_geometry"; +import { Section } from "../domain"; +import { xj_model_to_geometry } from "./xj_model_to_geometry"; const materials = [ // Wall @@ -99,3 +106,44 @@ export function area_collision_geometry_to_object_3d(object: CollisionObject): O return group; } + +export function area_geometry_to_sections_and_object_3d( + object: RenderObject +): [Section[], Object3D] { + const sections: Section[] = []; + const group = new Group(); + + for (const section of object.sections) { + const positions: number[] = []; + const normals: number[] = []; + const indices: number[] = []; + + for (const model of section.models) { + xj_model_to_geometry(model, new Matrix4(), positions, normals, indices); + } + + const geometry = new BufferGeometry(); + geometry.addAttribute("position", new Float32BufferAttribute(positions, 3)); + geometry.addAttribute("normal", new Float32BufferAttribute(normals, 3)); + geometry.setIndex(new Uint16BufferAttribute(indices, 1)); + + const mesh = new Mesh( + geometry, + new MeshLambertMaterial({ + color: 0x44aaff, + transparent: true, + opacity: 0.25, + side: DoubleSide, + }) + ); + mesh.position.set(section.position.x, section.position.y, section.position.z); + mesh.rotation.set(section.rotation.x, section.rotation.y, section.rotation.z); + group.add(mesh); + + const sec = new Section(section.id, section.position, section.rotation.y); + mesh.userData.section = sec; + sections.push(sec); + } + + return [sections, group]; +} diff --git a/src/rendering/models.ts b/src/rendering/models.ts index 7629888f..a9a534f9 100644 --- a/src/rendering/models.ts +++ b/src/rendering/models.ts @@ -15,9 +15,9 @@ import { Vector3, } from "three"; import { vec3_to_threejs } from "."; -import { NjModel, NjObject, is_njcm_model } from "../data_formats/parsing/ninja"; +import { is_njcm_model, NjModel, NjObject } from "../data_formats/parsing/ninja"; import { NjcmModel } from "../data_formats/parsing/ninja/njcm"; -import { XjModel } from "../data_formats/parsing/ninja/xj"; +import { xj_model_to_geometry } from "./xj_model_to_geometry"; const DEFAULT_MATERIAL = new MeshLambertMaterial({ color: 0xff00ff, @@ -187,7 +187,7 @@ class Object3DCreator { if (is_njcm_model(model)) { this.njcm_model_to_geometry(model, matrix); } else { - this.xj_model_to_geometry(model, matrix); + xj_model_to_geometry(model, matrix, this.positions, this.normals, this.indices); } } @@ -253,102 +253,4 @@ class Object3DCreator { } } } - - private xj_model_to_geometry(model: XjModel, matrix: Matrix4): void { - const positions = this.positions; - const normals = this.normals; - const indices = this.indices; - const index_offset = this.positions.length / 3; - let clockwise = true; - - const normal_matrix = new Matrix3().getNormalMatrix(matrix); - - for (let { position, normal } of model.vertices) { - const p = vec3_to_threejs(position).applyMatrix4(matrix); - positions.push(p.x, p.y, p.z); - - normal = normal || DEFAULT_NORMAL; - const n = vec3_to_threejs(normal).applyMatrix3(normal_matrix); - normals.push(n.x, n.y, n.z); - } - - for (const mesh of model.meshes) { - const strip_indices = mesh.indices; - - for (let j = 2; j < strip_indices.length; ++j) { - const a = index_offset + strip_indices[j - 2]; - const b = index_offset + strip_indices[j - 1]; - const c = index_offset + strip_indices[j]; - const pa = new Vector3( - positions[3 * a], - positions[3 * a + 1], - positions[3 * a + 2] - ); - const pb = new Vector3( - positions[3 * b], - positions[3 * b + 1], - positions[3 * b + 2] - ); - const pc = new Vector3( - positions[3 * c], - positions[3 * c + 1], - positions[3 * c + 2] - ); - const na = new Vector3(normals[3 * a], normals[3 * a + 1], normals[3 * a + 2]); - const nb = new Vector3(normals[3 * a], normals[3 * a + 1], normals[3 * a + 2]); - const nc = new Vector3(normals[3 * a], normals[3 * a + 1], normals[3 * a + 2]); - - // Calculate a surface normal and reverse the vertex winding if at least 2 of the vertex normals point in the opposite direction. - // This hack fixes the winding for most models. - const normal = pb - .clone() - .sub(pa) - .cross(pc.clone().sub(pa)); - - if (clockwise) { - normal.negate(); - } - - const opposite_count = - (normal.dot(na) < 0 ? 1 : 0) + - (normal.dot(nb) < 0 ? 1 : 0) + - (normal.dot(nc) < 0 ? 1 : 0); - - if (opposite_count >= 2) { - clockwise = !clockwise; - } - - if (clockwise) { - indices.push(b); - indices.push(a); - indices.push(c); - } else { - indices.push(a); - indices.push(b); - indices.push(c); - } - - clockwise = !clockwise; - - // The following switch statement fixes model 180.xj (zanba). - // switch (j) { - // case 17: - // case 52: - // case 70: - // case 92: - // case 97: - // case 126: - // case 140: - // case 148: - // case 187: - // case 200: - // console.warn(`swapping winding at: ${j}, (${a}, ${b}, ${c})`); - // break; - // default: - // ccw = !ccw; - // break; - // } - } - } - } } diff --git a/src/rendering/xj_model_to_geometry.ts b/src/rendering/xj_model_to_geometry.ts new file mode 100644 index 00000000..45f14160 --- /dev/null +++ b/src/rendering/xj_model_to_geometry.ts @@ -0,0 +1,94 @@ +import { Matrix3, Matrix4, Vector3 } from "three"; +import { vec3_to_threejs } from "."; +import { XjModel } from "../data_formats/parsing/ninja/xj"; + +const DEFAULT_NORMAL = new Vector3(0, 1, 0); + +export function xj_model_to_geometry( + model: XjModel, + matrix: Matrix4, + positions: number[], + normals: number[], + indices: number[] +): void { + const index_offset = positions.length / 3; + let clockwise = true; + + const normal_matrix = new Matrix3().getNormalMatrix(matrix); + + for (let { position, normal } of model.vertices) { + const p = vec3_to_threejs(position).applyMatrix4(matrix); + positions.push(p.x, p.y, p.z); + + const local_n = normal ? vec3_to_threejs(normal) : DEFAULT_NORMAL; + const n = local_n.applyMatrix3(normal_matrix); + normals.push(n.x, n.y, n.z); + } + + for (const mesh of model.strips) { + const strip_indices = mesh.indices; + + for (let j = 2; j < strip_indices.length; ++j) { + const a = index_offset + strip_indices[j - 2]; + const b = index_offset + strip_indices[j - 1]; + const c = index_offset + strip_indices[j]; + const pa = new Vector3(positions[3 * a], positions[3 * a + 1], positions[3 * a + 2]); + const pb = new Vector3(positions[3 * b], positions[3 * b + 1], positions[3 * b + 2]); + const pc = new Vector3(positions[3 * c], positions[3 * c + 1], positions[3 * c + 2]); + const na = new Vector3(normals[3 * a], normals[3 * a + 1], normals[3 * a + 2]); + const nb = new Vector3(normals[3 * a], normals[3 * a + 1], normals[3 * a + 2]); + const nc = new Vector3(normals[3 * a], normals[3 * a + 1], normals[3 * a + 2]); + + // Calculate a surface normal and reverse the vertex winding if at least 2 of the vertex normals point in the opposite direction. + // This hack fixes the winding for most models. + const normal = pb + .clone() + .sub(pa) + .cross(pc.clone().sub(pa)); + + if (clockwise) { + normal.negate(); + } + + const opposite_count = + (normal.dot(na) < 0 ? 1 : 0) + + (normal.dot(nb) < 0 ? 1 : 0) + + (normal.dot(nc) < 0 ? 1 : 0); + + if (opposite_count >= 2) { + clockwise = !clockwise; + } + + if (clockwise) { + indices.push(b); + indices.push(a); + indices.push(c); + } else { + indices.push(a); + indices.push(b); + indices.push(c); + } + + clockwise = !clockwise; + + // The following switch statement fixes model 180.xj (zanba). + // switch (j) { + // case 17: + // case 52: + // case 70: + // case 92: + // case 97: + // case 126: + // case 140: + // case 148: + // case 187: + // case 200: + // console.warn(`swapping winding at: ${j}, (${a}, ${b}, ${c})`); + // break; + // default: + // ccw = !ccw; + // break; + // } + } + } +} diff --git a/src/stores/AreaStore.ts b/src/stores/AreaStore.ts index 6a874752..7f2fbbad 100644 --- a/src/stores/AreaStore.ts +++ b/src/stores/AreaStore.ts @@ -1,11 +1,14 @@ import { Object3D } from "three"; +import { Endianness } from "../data_formats"; +import { ArrayBufferCursor } from "../data_formats/cursor/ArrayBufferCursor"; import { parse_area_collision_geometry } from "../data_formats/parsing/area_collision_geometry"; import { parse_area_geometry } from "../data_formats/parsing/area_geometry"; import { Area, AreaVariant, Section } from "../domain"; -import { area_collision_geometry_to_object_3d } from "../rendering/areas"; +import { + area_collision_geometry_to_object_3d, + area_geometry_to_sections_and_object_3d, +} from "../rendering/areas"; import { get_area_collision_data, get_area_render_data } from "./binary_assets"; -import { Endianness } from "../data_formats"; -import { ArrayBufferCursor } from "../data_formats/cursor/ArrayBufferCursor"; function area(id: number, name: string, order: number, variants: number): Area { const area = new Area(id, name, order, []); @@ -104,15 +107,15 @@ class AreaStore { area_id: number, area_variant: number ): Promise { - const sections = sections_cache.get(`${episode}-${area_id}-${area_variant}`); + const key = `${episode}-${area_id}-${area_variant}`; + let sections = sections_cache.get(key); - if (sections) { - return sections; - } else { - return this.get_area_sections_and_render_geometry(episode, area_id, area_variant).then( - ({ sections }) => sections - ); + if (!sections) { + this.load_area_sections_and_render_geometry(episode, area_id, area_variant); + sections = sections_cache.get(key)!; } + + return sections; } async get_area_render_geometry( @@ -120,15 +123,15 @@ class AreaStore { area_id: number, area_variant: number ): Promise { - const object_3d = render_geometry_cache.get(`${episode}-${area_id}-${area_variant}`); + const key = `${episode}-${area_id}-${area_variant}`; + let object_3d = render_geometry_cache.get(key); - if (object_3d) { - return object_3d; - } else { - return this.get_area_sections_and_render_geometry(episode, area_id, area_variant).then( - ({ object_3d }) => object_3d - ); + if (!object_3d) { + this.load_area_sections_and_render_geometry(episode, area_id, area_variant); + object_3d = render_geometry_cache.get(key)!; } + + return object_3d; } async get_area_collision_geometry( @@ -151,26 +154,25 @@ class AreaStore { } } - private get_area_sections_and_render_geometry( + private load_area_sections_and_render_geometry( episode: number, area_id: number, area_variant: number - ): Promise<{ sections: Section[]; object_3d: Object3D }> { - const promise = get_area_render_data(episode, area_id, area_variant).then( - parse_area_geometry + ): void { + const promise = get_area_render_data(episode, area_id, area_variant).then(buffer => + area_geometry_to_sections_and_object_3d( + parse_area_geometry(new ArrayBufferCursor(buffer, Endianness.Little)) + ) ); - const sections = new Promise((resolve, reject) => { - promise.then(({ sections }) => resolve(sections)).catch(reject); - }); - const object_3d = new Promise((resolve, reject) => { - promise.then(({ object_3d }) => resolve(object_3d)).catch(reject); - }); - - sections_cache.set(`${episode}-${area_id}-${area_variant}`, sections); - render_geometry_cache.set(`${episode}-${area_id}-${area_variant}`, object_3d); - - return promise; + sections_cache.set( + `${episode}-${area_id}-${area_variant}`, + promise.then(([sections]) => sections) + ); + render_geometry_cache.set( + `${episode}-${area_id}-${area_variant}`, + promise.then(([, object_3d]) => object_3d) + ); } } diff --git a/src/stores/QuestEditorStore.ts b/src/stores/QuestEditorStore.ts index 4341b29c..4f21c799 100644 --- a/src/stores/QuestEditorStore.ts +++ b/src/stores/QuestEditorStore.ts @@ -1,5 +1,5 @@ import Logger from "js-logger"; -import { action, observable } from "mobx"; +import { action, observable, runInAction } from "mobx"; import { parse_quest, write_quest_qst } from "../data_formats/parsing/quest"; import { Vec3 } from "../data_formats/Vec3"; import { Area, Quest, QuestEntity, Section } from "../domain"; @@ -110,7 +110,6 @@ class QuestEditorStore { let { x, y, z } = entity.position; const section = sections.find(s => s.id === entity.section_id); - entity.section = section; if (section) { const { x: sec_x, y: sec_y, z: sec_z } = section.position; @@ -123,7 +122,10 @@ class QuestEditorStore { logger.warn(`Section ${entity.section_id} not found.`); } - entity.position = new Vec3(x, y, z); + runInAction(() => { + entity.section = section; + entity.position = new Vec3(x, y, z); + }); }; save_current_quest_to_file = (file_name: string) => { diff --git a/test/resources/ItemPMT.bin b/test/resources/ItemPMT.bin new file mode 100644 index 0000000000000000000000000000000000000000..8d61df1d18919e6dce2be98f40a4d21aec425ba5 GIT binary patch literal 86880 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

k-VS?o=qJedDm9(E@5+gjKas5T$_ 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

&I&Tlv3H|MPO?jrz|< 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 literal 0 HcmV?d00001 diff --git a/test/resources/map_forest01c.rel b/test/resources/map_forest01c.rel new file mode 100644 index 0000000000000000000000000000000000000000..92d9d34d7aaf1925972b8fc487c3272dac3f8f41 GIT binary patch literal 72096 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 literal 0 HcmV?d00001