diff --git a/src/lib.rs b/src/lib.rs index 10523eb..490b85e 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -61,4 +61,7 @@ pub mod fiin; pub mod log; // Reading textures (TEX). -pub mod tex; \ No newline at end of file +pub mod tex; + +// Reading material files (MTRL) +pub mod mtrl; \ No newline at end of file diff --git a/src/mtrl.rs b/src/mtrl.rs new file mode 100644 index 0000000..e90af67 --- /dev/null +++ b/src/mtrl.rs @@ -0,0 +1,143 @@ +use std::io::Cursor; +use crate::gamedata::MemoryBuffer; +use binrw::{binread, BinRead}; + +#[binread] +#[derive(Debug)] +struct MaterialFileHeader { + version: u32, + file_size: u16, + data_set_size: u16, + string_table_size: u16, + shader_package_name_offset: u16, + texture_count: u8, + uv_set_count: u8, + color_set_count: u8, + additional_data_size: u8 +} + +#[binread] +#[derive(Debug)] +struct MaterialHeader { + shader_value_list_size: u16, + shader_key_count: u16, + constant_count: u16, + #[br(pad_after = 4)] + sampler_count: u16 +} + +#[binread] +#[derive(Debug)] +struct ColorSet { + name_offset: u16, + #[br(pad_after = 1)] + index: u8 +} + +#[binread] +#[derive(Debug)] +struct ColorSetInfo { + #[br(count = 256)] + data: Vec +} + +#[binread] +#[derive(Debug)] +struct ColorSetDyeInfo { + #[br(count = 16)] + data: Vec +} + +#[binread] +#[derive(Debug)] +struct ShaderKey { + category: u32, + value: u32 +} + +#[binread] +#[derive(Debug)] +struct Constant { + constant_id: u32, + value_offset: u16, + value_size: u16 +} + +#[binread] +#[derive(Debug)] +struct Sampler { + sampler_id: u32, + flags: u32, // TODO: unknown + #[br(pad_after = 3)] + texture_index: u8, +} + +#[binread] +#[derive(Debug)] +struct MaterialData { + file_header: MaterialFileHeader, + + #[br(count = file_header.texture_count)] + offsets: Vec, + + #[br(count = file_header.uv_set_count)] + uv_color_sets: Vec, + + #[br(count = file_header.color_set_count)] + color_sets: Vec, + + #[br(count = file_header.string_table_size)] + strings: Vec, + + #[br(if(file_header.data_set_size > 0))] + #[br(pad_before = file_header.additional_data_size)] + color_set_info: Option, + + #[br(if(file_header.data_set_size > 512))] + color_set_due_info: Option, + + header: MaterialHeader, + + #[br(count = header.shader_key_count)] + shader_keys: Vec, + #[br(count = header.constant_count)] + constants: Vec, + #[br(count = header.sampler_count)] + samplers: Vec, + #[br(count = header.shader_value_list_size / 4)] + shader_values: Vec +} + +#[derive(Debug)] +pub struct Material { + texture_paths: Vec +} + +impl Material { + pub fn from_existing(buffer: &MemoryBuffer) -> Option { + let mut cursor = Cursor::new(buffer); + let mat_data = MaterialData::read(&mut cursor).ok()?; + + let mut texture_paths = vec![]; + + let mut offset = 0; + for _ in 0..mat_data.file_header.texture_count { + let mut string = String::new(); + + let mut next_char = mat_data.strings[offset as usize] as char; + while next_char != '\0' { + string.push(next_char); + offset += 1; + next_char = mat_data.strings[offset as usize] as char; + } + + texture_paths.push(string); + + offset += 1; + } + + Some(Material { + texture_paths + }) + } +} \ No newline at end of file