Adds gc-engine's binary and a level.rs that joins the format layer to the renderer: LOD selection and morphing per patch, then triangles grouped by texture so each texture is one draw rather than one per triangle. The PS2 world is Z-up at 1024 raw units per world unit, so the conversion is (x, y, z) -> (x, z, -y). The sign flip on the third axis turns the PS2's right-handed frame into Bevy's left-handed one rather than negating a determinant, which is what stops the level rendering mirrored. Morphing and collapse are kept distinct. Morphing blends a vertex toward the midpoint of its two parents across its tier's band; collapse replaces the vertex outright, position and UV, once it is past the far edge. Morphing is a blend, collapse is a cut, and conflating them makes distant terrain shimmer. Blending has to happen in raw units before the axis swap: mixing a converted parent with an unconverted child scales the blend by 1024. Level 0 renders as 26,758 textured triangles over 92 textures, correct UVs, with LOD selection live (26 patches at LOD 0, 650 at LOD 2 from the start camera). GC_ENGINE_SHOT writes one frame as a PPM and exits. Rendering immediately exposed a bug no test could. Positions are i16 offsets from a per-patch origin, and the obvious rule -- the last non-index STROW row -- is wrong on RAC2, which also uses STROW for per-vertex light records that come *after* the origin. Taking the last one yields [186, 186, 186, 186] and collapses the whole level onto the world origin. The entire level then fit in a 63-unit box and every test still passed: vert_count matched, tri_count matched, every parent and triangle index resolved, because all of those are relative to the same broken origin. Only a screenshot showed it. The rule that works is the STROW immediately preceding the first V3_16 position unpack; with it, level 0 spans x 86..444, y 46..211, z -477..40, matching the patch bounding spheres. That is worth more than the renderer: a parser can be completely self-consistent and still describe the wrong thing, and where a value is absolute rather than relative it has to be checked against something independent. The frame is flat and dark because there are no normals and no lighting yet. That is the next task -- the per-vertex light records -- not something to paper over with an exposure fudge.
20 lines
431 B
TOML
20 lines
431 B
TOML
[package]
|
|
name = "gc-engine"
|
|
version.workspace = true
|
|
edition.workspace = true
|
|
rust-version.workspace = true
|
|
license.workspace = true
|
|
publish.workspace = true
|
|
description = "Bevy application: Graphics Synthesizer, VU0/VU1 and the renderer"
|
|
|
|
[dependencies]
|
|
anyhow.workspace = true
|
|
thiserror.workspace = true
|
|
gc-formats.workspace = true
|
|
gc-game.workspace = true
|
|
bevy.workspace = true
|
|
|
|
[[bin]]
|
|
name = "gc-engine"
|
|
path = "src/main.rs"
|