From 8a2c3e98403083987aa6f3b50cadcbc92281164a Mon Sep 17 00:00:00 2001 From: Valentin Popov Date: Sat, 31 Oct 2026 22:44:00 +0400 Subject: fix(render): select native Land2 multitexture variants --- crates/fparkan-terrain-format/src/lib.rs | 34 +++++++++++++++++++++++++++----- 1 file changed, 29 insertions(+), 5 deletions(-) (limited to 'crates/fparkan-terrain-format/src') diff --git a/crates/fparkan-terrain-format/src/lib.rs b/crates/fparkan-terrain-format/src/lib.rs index e4028f9..595f4d8 100644 --- a/crates/fparkan-terrain-format/src/lib.rs +++ b/crates/fparkan-terrain-format/src/lib.rs @@ -58,7 +58,7 @@ pub struct TerrainMaterialLayers { pub overlay_selector: Option, } -/// One `World3D` material-manager lookup key. +/// One `World3D` material-manager phase query. /// /// The original manager selects a WEAR table in the upper 16 bits and its /// positional material row in the lower 16 bits. @@ -68,6 +68,9 @@ pub struct TerrainMaterialSelection { pub table_index: u16, /// Positional material row in that WEAR table. pub material_index: u16, + /// Animation block passed separately to GetMaterialPhase. The multitexture + /// path uses block 1 for Land2, with the material sampler's block-0 fallback. + pub animation_block_index: usize, } impl TerrainMaterialSelection { @@ -99,6 +102,7 @@ impl TerrainMaterialLayers { TerrainMaterialSelection { table_index: 0, material_index: u16::from(self.base_selector), + animation_block_index: 0, } } @@ -109,27 +113,30 @@ impl TerrainMaterialLayers { .map(|material_index| TerrainMaterialSelection { table_index: 0, material_index: u16::from(material_index), + animation_block_index: 0, }) } - /// Returns the detail selection corresponding to the base row in - /// `Land2.wea`. + /// Returns the multitexture detail selection corresponding to the base + /// row in `Land2.wea`. #[must_use] pub fn detail_base_selection(self) -> TerrainMaterialSelection { TerrainMaterialSelection { table_index: 1, material_index: u16::from(self.base_selector), + animation_block_index: 1, } } - /// Returns the optional detail selection corresponding to the overlay row - /// in `Land2.wea`. + /// Returns the optional multitexture detail selection corresponding to + /// the overlay row in `Land2.wea`. #[must_use] pub fn detail_overlay_selection(self) -> Option { self.overlay_selector .map(|material_index| TerrainMaterialSelection { table_index: 1, material_index: u16::from(material_index), + animation_block_index: 1, }) } } @@ -1948,6 +1955,7 @@ mod tests { TerrainMaterialSelection { table_index: 0, material_index: 2, + animation_block_index: 0, } ); assert_eq!( @@ -1965,6 +1973,13 @@ mod tests { .phase_key(), 0x0001_0002 ); + assert_eq!( + document.faces[0] + .material_layers() + .detail_base_selection() + .animation_block_index, + 1 + ); assert_eq!( document.faces[0] .material_layers() @@ -1973,6 +1988,14 @@ mod tests { .phase_key(), 0x0001_0001 ); + assert_eq!( + document.faces[0] + .material_layers() + .detail_overlay_selection() + .unwrap() + .animation_block_index, + 1 + ); raw_face[4..6].copy_from_slice(&0xff03_u16.to_le_bytes()); let nres = decode_nres(&minimal_land_msh(&raw_face)).expect("nres"); @@ -1989,6 +2012,7 @@ mod tests { TerrainMaterialSelection { table_index: 0, material_index: 3, + animation_block_index: 0, } ); assert_eq!( -- cgit v1.2.3