wgtk/space/section/
bwt2.rs

1use std::io::{Read, Seek};
2
3use super::{Section, SectionId};
4use crate::util::io::WgReadExt;
5
6
7/// Terrain2 section, providing many information about `cdata_processed` files and many
8/// settings for the terrain.
9#[derive(Debug)]
10pub struct BWT2 {
11    pub settings1: TerrainSettings1,
12    pub settings2: TerrainSettings2,
13    pub chunks: Vec<TerrainChunk>,
14    pub lod_distances: Vec<f32>,
15    pub outland_cascades: Vec<OutlandCascade>,
16    pub tiles_fnv: Vec<u32>
17}
18
19impl Section for BWT2 {
20
21    const ID: &'static SectionId = b"BWT2";
22
23    fn decode<R: Read + Seek>(read: &mut R) -> std::io::Result<Self> {
24
25        let settings1_size = read.read_single_head()?;
26        assert_eq!(settings1_size, 32);
27        let settings1 = TerrainSettings1 {
28            chunk_size: read.read_f32()?,
29            min_x: read.read_i32()?,
30            max_x: read.read_i32()?,
31            min_y: read.read_i32()?,
32            max_y: read.read_i32()?,
33            normal_map_fnv: read.read_u32()?,
34            global_map_fnv: read.read_u32()?,
35            noise_texture_fnv: read.read_u32()?
36        };
37
38        let chunks = read.read_vector(|buf| {
39            Ok(TerrainChunk {
40                resource_fnv: buf.read_u32()?,
41                loc_x: buf.read_i16()?,
42                loc_y: buf.read_i16()?
43            })
44        })?;
45
46        // currently unused
47        let _3 = read.read_vector(|buf| buf.read_u32())?;
48
49        let settings2_size = read.read_single_head()?;
50        assert_eq!(settings2_size, 128);
51        let terrain_version = read.read_u32()?;
52        let terrain_flags = read.read_u32()?;
53        let settings2 = TerrainSettings2 {
54            terrain_version,
55            blend_map_caching: terrain_flags & 0x1 != 0,
56            normal_map_caching: terrain_flags & 0x2 != 0,
57            enable_auto_rebuild_normal_map: terrain_flags & 0x8 != 0,
58            enable_auto_rebuild_water_geometry: terrain_flags & 0x20 != 0,
59            height_map_size: read.read_u32()?,
60            normal_map_size: read.read_u32()?,
61            hole_map_size: read.read_u32()?,
62            shadow_map_size: read.read_u32()?,
63            blend_map_size: read.read_u32()?,
64            lod_texture_distance: read.read_f32()?,
65            macro_lod_start: read.read_f32()?,
66            start_bias: { read.skip::<4>()?; read.read_f32()? },
67            end_bias: read.read_f32()?,
68            direct_occlusion: read.read_f32()?,
69            reverb_occlusion: read.read_f32()?,
70            wrap_u: read.read_f32()?,
71            wrap_v: read.read_f32()?,
72            blend_macro_influence: {
73                read.skip::<16>()?;
74                read.read_f32()?
75            },
76            blend_global_threshold: read.read_f32()?,
77            blend_height: read.read_f32()?,
78            disabled_blend_height: read.read_f32()?,
79            vt_lod_params: [
80                read.read_f32()?,
81                read.read_f32()?,
82                read.read_f32()?,
83                read.read_f32()?,
84            ],
85            bounding_box: [
86                read.read_f32()?,
87                read.read_f32()?,
88                read.read_f32()?,
89                read.read_f32()?,
90            ]
91        };
92
93        let lod_distances = read.read_vector(|buf| buf.read_f32())?;
94
95        // currently unused
96        let _6 = read.read_vector(|buf| { buf.read_u32()?; buf.read_u32() })?;
97
98        let outland_cascades = read.read_vector(|buf| {
99            Ok(OutlandCascade {
100                extent_min: [
101                    buf.read_f32()?,
102                    buf.read_f32()?,
103                    buf.read_f32()?,
104                ],
105                extent_max: [
106                    buf.read_f32()?,
107                    buf.read_f32()?,
108                    buf.read_f32()?,
109                ],
110                height_map_fnv: buf.read_u32()?,
111                normal_map_fnv: buf.read_u32()?,
112                tile_map_fnv: buf.read_u32()?,
113                tile_scale: buf.read_f32()?
114            })
115        })?;
116
117        let tiles_fnv = read.read_vector(|buf| buf.read_u32())?;
118
119        Ok(BWT2 {
120            settings1,
121            settings2,
122            chunks,
123            lod_distances,
124            outland_cascades,
125            tiles_fnv
126        })
127
128    }
129
130}
131
132
133/// Terrain settings v1.
134/// Decoded by [BWT2] section.
135#[derive(Debug)]
136pub struct TerrainSettings1 {
137    /// space.settings/chunkSize or 100.0 by default
138    pub chunk_size: f32,
139    /// space.settings/bounds
140    pub min_x: i32,
141    /// space.settings/bounds
142    pub max_x: i32,
143    /// space.settings/bounds
144    pub min_y: i32,
145    /// space.settings/bounds
146    pub max_y: i32,
147    pub normal_map_fnv: u32,
148    /// global_AM.dds, maybe tintTexture - global terrain albedo map
149    pub global_map_fnv: u32,
150    pub noise_texture_fnv: u32
151}
152
153
154/// Terrain chunk definition, each chunk has its own `cdata_processed` archive.
155/// Each chunk has a size defined by [chunk_size](TerrainSettings1.chunk_size).
156/// Decoded by [BWT2] section.
157#[derive(Debug)]
158pub struct TerrainChunk {
159    /// Resource FNV hash, you can find the path to the `cdata_processed` archive by resolving
160    /// this hash in the [BWST](super::BWST) section.
161    pub resource_fnv: u32,
162    pub loc_x: i16,
163    pub loc_y: i16
164}
165
166
167/// Terrain settings v2.
168/// Decoded by [BWT2] section.
169#[derive(Debug)]
170pub struct TerrainSettings2 {
171    /// space.settings/terrain/version
172    pub terrain_version: u32,
173    /// terrain/blendMapCaching
174    pub blend_map_caching: bool,
175    /// terrain/normalMapCaching
176    pub normal_map_caching: bool,
177    /// terrain/editor/enableAutoRebuildNormalMap
178    pub enable_auto_rebuild_normal_map: bool,
179    /// terrain/editor/enableAutoRebuildWaterGeometry
180    pub enable_auto_rebuild_water_geometry: bool,
181    /// terrain/heightMapSize
182    pub height_map_size: u32,
183    /// terrain/normalMapSize
184    pub normal_map_size: u32,
185    /// terrain/holeMapSize
186    pub hole_map_size: u32,
187    /// terrain/shadowMapSize
188    pub shadow_map_size: u32,
189    /// terrain/blendMapSize
190    pub blend_map_size: u32,
191    /// terrain/lodInfo/lodTextureDistance
192    pub lod_texture_distance: f32,
193    /// terrain/lodInfo/macroLODStart
194    pub macro_lod_start: f32,
195    /// terrain/lodInfo/startBias
196    pub start_bias: f32,
197    /// terrain/lodInfo/endBias
198    pub end_bias: f32,
199    /// terrain/soundOcclusion/directOcclusion
200    pub direct_occlusion: f32,
201    /// terrain/soundOcclusion/reverbOcclusion
202    pub reverb_occlusion: f32,
203    /// terrain/detailNormal/wrapU
204    pub wrap_u: f32,
205    /// terrain/detailNormal/wrapV
206    pub wrap_v: f32,
207    /// terrain/blendMacroInfluence
208    pub blend_macro_influence: f32,
209    /// terrain/blendGlobalThreshold
210    pub blend_global_threshold: f32,
211    /// terrain/blendHeight
212    pub blend_height: f32,
213    /// terrain/disabledBlendHeight
214    pub disabled_blend_height: f32,
215    /// terrain/VTLodParams
216    pub vt_lod_params: [f32; 4],
217    pub bounding_box: [f32; 4],
218}
219
220
221/// Definition of a cascade in the terrain.
222/// Decoded by [BWT2] section.
223#[derive(Debug)]
224pub struct OutlandCascade {
225    pub extent_min: [f32; 3],
226    pub extent_max: [f32; 3],
227    pub height_map_fnv: u32,
228    pub normal_map_fnv: u32,
229    pub tile_map_fnv: u32,
230    pub tile_scale: f32,
231}