Skip to content

Commit

Permalink
Decode mask vertices
Browse files Browse the repository at this point in the history
  • Loading branch information
DCNick3 committed May 1, 2024
1 parent 2d00724 commit 2a954e9
Show file tree
Hide file tree
Showing 4 changed files with 187 additions and 4 deletions.
3 changes: 3 additions & 0 deletions junk/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use clap::Parser;
mod buffer_parser;
mod check_info_uniqueness;
mod debug_tex_parser;
mod mask_visualize_vertices;

// use clap to select what to do
#[derive(Parser)]
Expand All @@ -18,6 +19,7 @@ enum JunkAction {
BufferParser,
DebugTexParser,
CheckInfoUniqueness { snr_path: String },
MaskVisualizeVertices { msk_path: String },
}

fn main() {
Expand All @@ -26,5 +28,6 @@ fn main() {
JunkAction::BufferParser => buffer_parser::main(),
JunkAction::DebugTexParser => debug_tex_parser::main(),
JunkAction::CheckInfoUniqueness { snr_path } => check_info_uniqueness::main(snr_path),
JunkAction::MaskVisualizeVertices { msk_path } => mask_visualize_vertices::main(msk_path),
}
}
109 changes: 109 additions & 0 deletions junk/src/mask_visualize_vertices.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
use shin_core::format::mask::MaskVertex;

fn make_svg(vertices: &[MaskVertex], color: &str, view_box: (f32, f32, f32, f32)) -> String {
use std::fmt::Write;

let mut result = String::new();
writeln!(
result,
r#"<svg xmlns="http://www.w3.org/2000/svg" viewBox="{} {} {} {}">"#,
view_box.0,
view_box.1,
view_box.2 - view_box.0,
view_box.3 - view_box.1
)
.unwrap();

let mut rect = |x: f32, y: f32, width: f32, height: f32| {
writeln!(
result,
r#" <rect x="{}" y="{}" width="{}" height="{}" fill="none" stroke="{}" />"#,
x, y, width, height, color
)
.unwrap();
};

for vertex in vertices {
rect(
vertex.from_x as f32,
vertex.from_y as f32,
vertex.to_x as f32 - vertex.from_x as f32,
vertex.to_y as f32 - vertex.from_y as f32,
)
}

result.push_str("</svg>\n");

result
}

fn compute_area(vertices: &[MaskVertex]) -> u32 {
vertices
.iter()
.map(|v| (v.to_x - v.from_x) as u32 * (v.to_y - v.from_y) as u32)
.sum()
}

pub fn main(msk_path: String) {
let mask = std::fs::read(msk_path).unwrap();
let mask = shin_core::format::mask::read_mask(&mask).unwrap();

let black_range = 0..mask.vertices.black_regions.vertex_count as usize;
let white_range =
black_range.end..black_range.end + mask.vertices.white_regions.vertex_count as usize;
let transparent_range =
white_range.end..white_range.end + mask.vertices.transparent_regions.vertex_count as usize;

assert!(mask
.vertices
.vertices
.iter()
.all(|v| v.from_x % 4 == 0 && v.from_y % 4 == 0 && v.to_x % 4 == 0 && v.to_y % 4 == 0));

let black_vertices = &mask.vertices.vertices[black_range];
let white_vertices = &mask.vertices.vertices[white_range];
let transparent_vertices = &mask.vertices.vertices[transparent_range];

// the areas are computed in 4x4 blocks
println!("Black area: {}", compute_area(black_vertices) / 16);
println!("White area: {}", compute_area(white_vertices) / 16);
println!(
"Transparent area: {}",
compute_area(transparent_vertices) / 16
);

let black_svg = make_svg(
black_vertices,
"red",
(
0.0,
0.0,
mask.texels.width() as f32,
mask.texels.height() as f32,
),
);
let white_svg = make_svg(
&white_vertices,
"green",
(
0.0,
0.0,
mask.texels.width() as f32,
mask.texels.height() as f32,
),
);
let transparent_svg = make_svg(
&transparent_vertices,
"blue",
(
0.0,
0.0,
mask.texels.width() as f32,
mask.texels.height() as f32,
),
);

std::fs::write("mask_black.svg", black_svg).unwrap();
std::fs::write("mask_white.svg", white_svg).unwrap();
std::fs::write("mask_transparent.svg", transparent_svg).unwrap();
}
38 changes: 37 additions & 1 deletion sdu/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -176,10 +176,46 @@ fn mask_command(command: MaskCommand) -> Result<()> {
mask_path,
output_path,
} => {
use std::io::Write;

let mask = std::fs::read(mask_path)?;
let mask = shin_core::format::mask::read_mask(&mask)?;

mask.texels.save(output_path)?;
std::fs::create_dir_all(&output_path)?;

mask.texels
.save(output_path.join("mask.png"))
.context("Writing mask.png")?;

let v = &mask.vertices;
let mut v_out =
File::create(output_path.join("vertices.txt")).context("Creating vertices.txt")?;
writeln!(
v_out,
"({}, {}) ({}, {}) ({}, {})",
v.black_regions.vertex_count,
v.black_regions.region_area,
v.white_regions.vertex_count,
v.white_regions.region_area,
v.transparent_regions.vertex_count,
v.transparent_regions.region_area
)
.context("Writing vertices.txt")?;

for (i, vertex) in (0..).zip(&v.vertices) {
if i == v.black_regions.vertex_count
|| i == v.black_regions.vertex_count + v.white_regions.vertex_count
{
writeln!(v_out).context("Writing vertices.txt")?;
}

writeln!(
v_out,
"{} {} {} {}",
vertex.from_x, vertex.from_y, vertex.to_x, vertex.to_y
)
.context("Writing vertices.txt")?;
}

Ok(())
}
Expand Down
41 changes: 38 additions & 3 deletions shin-core/src/format/mask/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ struct MskHeader {

pub struct MaskTexture {
pub id: u32,
// TODO: vertices
pub vertices: VertexData,
pub texels: GrayImage,
}

Expand Down Expand Up @@ -70,21 +70,56 @@ fn read_texels(texels_data: &[u8], width: u32, height: u32) -> Result<GrayImage>
Ok(result)
}

#[derive(BinRead, BinWrite, Debug, Copy, Clone)]
#[br(little)]
pub struct MaskVertex {
pub from_x: u16,
pub from_y: u16,
pub to_x: u16,
pub to_y: u16,
}

#[derive(BinRead, BinWrite, Debug, Copy, Clone)]
#[br(little)]
pub struct MaskRegionInfo {
pub vertex_count: u32,
/// Area in 4x4 blocks
pub region_area: u32,
}

#[derive(BinRead, Debug, Clone)]
pub struct VertexData {
pub black_regions: MaskRegionInfo,
pub white_regions: MaskRegionInfo,
pub transparent_regions: MaskRegionInfo,
#[br(count = black_regions.vertex_count + white_regions.vertex_count + transparent_regions.vertex_count)]
pub vertices: Vec<MaskVertex>,
}

fn read_vertices(vertices_data: &[u8]) -> Result<VertexData> {
let mut source = std::io::Cursor::new(vertices_data);

let vertex_data = VertexData::read_le(&mut source)?;

Ok(vertex_data)
}

pub fn read_mask(source: &[u8]) -> Result<MaskTexture> {
let mut source = std::io::Cursor::new(source);
let source = &mut source;

let header = MskHeader::read(source)?;

let data = &source.get_ref()[header.data_offset as usize..][..header.data_size as usize];
let _vertices =
let vertices_data =
&source.get_ref()[header.vertices_data as usize..][..header.vertices_size as usize];
// vertices are not parsed here, as our engine does not use them

let vertices = read_vertices(vertices_data)?;
let texels = read_texels(data, header.width as u32, header.height as u32)?;

Ok(MaskTexture {
id: header.mask_id,
vertices,
texels,
})
}

0 comments on commit 2a954e9

Please sign in to comment.