From 5f0fedadb5a728af0bebc0b128bb13b2a803f2be Mon Sep 17 00:00:00 2001 From: Aidar Shaikhiev Date: Fri, 31 May 2024 01:24:45 +0500 Subject: [PATCH 1/5] Fix old compilation bug --- voxygen/src/bin/img-export.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/voxygen/src/bin/img-export.rs b/voxygen/src/bin/img-export.rs index dca0d67a9e..30145d8518 100644 --- a/voxygen/src/bin/img-export.rs +++ b/voxygen/src/bin/img-export.rs @@ -21,7 +21,7 @@ pub fn main() { for (_, spec) in manifest.read().0.iter() { match spec { ImageSpec::Vox(specifier, model_index) => { - voxel_to_png(&specifier, Transform::default(), args.scale, model_index) + voxel_to_png(&specifier, Transform::default(), args.scale, *model_index as usize) }, ImageSpec::VoxTrans(specifier, offset, [rot_x, rot_y, rot_z], zoom, model_index) => { voxel_to_png( @@ -39,7 +39,7 @@ pub fn main() { stretch: false, }, args.scale, - model_index, + *model_index as usize, ) }, ImageSpec::Png(specifier) => { @@ -50,7 +50,7 @@ pub fn main() { } } -fn voxel_to_png(specifier: &String, transform: Transform, scale: u32, model_index: u32) { +fn voxel_to_png(specifier: &String, transform: Transform, scale: u32, model_index: usize) { let voxel = match DotVoxAsset::load(&format!("voxygen.{}", specifier)) { Ok(dot_vox) => dot_vox, Err(err) => { @@ -73,7 +73,7 @@ fn voxel_to_png(specifier: &String, transform: Transform, scale: u32, model_inde x: ((rotated_size.y as u32) * scale) as u16, y: ((rotated_size.z as u32) * scale) as u16, }; - let segment = Segment::from_vox(dot_vox_data, false); + let segment = Segment::from_vox(dot_vox_data, false, model_index); let path = format!("img-export/{}.png", &specifier_to_path(specifier)); let folder_path = path.rsplit_once('/').expect("Invalid path").0; let full_path = Path::new(&path); From 226913d5f5090e2bd08864bd8f5f83bddc38ac6d Mon Sep 17 00:00:00 2001 From: Aidar Shaikhiev Date: Mon, 3 Jun 2024 03:09:06 +0500 Subject: [PATCH 2/5] Fix old compilation bug --- voxygen/src/bin/img-export.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/voxygen/src/bin/img-export.rs b/voxygen/src/bin/img-export.rs index 30145d8518..7ef3361641 100644 --- a/voxygen/src/bin/img-export.rs +++ b/voxygen/src/bin/img-export.rs @@ -70,8 +70,8 @@ fn voxel_to_png(specifier: &String, transform: Transform, scale: u32, model_inde // model_size let rotated_size = calc_rotated_size(&ori_mat, &aabb_size); let projection_size = Vec2 { - x: ((rotated_size.y as u32) * scale) as u16, - y: ((rotated_size.z as u32) * scale) as u16, + x: ((rotated_size.x as u32) * scale) as u16, + y: ((rotated_size.y as u32) * scale) as u16, }; let segment = Segment::from_vox(dot_vox_data, false, model_index); let path = format!("img-export/{}.png", &specifier_to_path(specifier)); @@ -94,9 +94,9 @@ fn calc_rotated_size(ori_mat: &Mat4, aabb_size: &Vec3) -> Vec3 { z: 0f32, }; let aabb_max = Vec3 { - x: aabb_size.y as f32, - y: aabb_size.z as f32, - z: aabb_size.x as f32, + x: aabb_size.x as f32, + y: aabb_size.y as f32, + z: aabb_size.z as f32, }; let aabb_vertices: [Vec3; 8] = [ Vec3::new(aabb_min.x, aabb_min.y, aabb_min.z), @@ -108,7 +108,7 @@ fn calc_rotated_size(ori_mat: &Mat4, aabb_size: &Vec3) -> Vec3 { Vec3::new(aabb_max.x, aabb_max.y, aabb_max.z), Vec3::new(aabb_min.x, aabb_max.y, aabb_max.z), ]; - let rotated_vertices = aabb_vertices.map(|c| (Vec4::::from(c) * *ori_mat).xyz()); + let rotated_vertices = aabb_vertices.map(|c| (*ori_mat * Vec4::::from(c)).xyz()); let max_xyz = rotated_vertices .iter() .copied() From 8221a11fe5474dbe21fb677ba026f1ab2df894cc Mon Sep 17 00:00:00 2001 From: Aidar Shaikhiev Date: Tue, 18 Jun 2024 00:23:07 +0500 Subject: [PATCH 3/5] Fixes #1761 set square dimensions for image Images rendered by veloren_voxygen::ui::graphic::renderer::draw_vox have equal width and height, because of camera settings. Needed just to set square dims for result image instead of calculating its rotated dims. --- voxygen/src/bin/img-export.rs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/voxygen/src/bin/img-export.rs b/voxygen/src/bin/img-export.rs index 7ef3361641..7005f92290 100644 --- a/voxygen/src/bin/img-export.rs +++ b/voxygen/src/bin/img-export.rs @@ -66,12 +66,9 @@ fn voxel_to_png(specifier: &String, transform: Transform, scale: u32, model_inde .size; let ori_mat = Mat4::from(transform.ori); let aabb_size = Vec3::new(model_size.x, model_size.y, model_size.z); - //TODO: skip dims transformation if transform is default(), instead use - // model_size - let rotated_size = calc_rotated_size(&ori_mat, &aabb_size); let projection_size = Vec2 { - x: ((rotated_size.x as u32) * scale) as u16, - y: ((rotated_size.y as u32) * scale) as u16, + x: (10u32 * scale) as u16, + y: (10u32 * scale) as u16, }; let segment = Segment::from_vox(dot_vox_data, false, model_index); let path = format!("img-export/{}.png", &specifier_to_path(specifier)); From 623e3aef93254202e0a5b3ec320e785d63ebd0b1 Mon Sep 17 00:00:00 2001 From: Aidar Shaikhiev Date: Tue, 18 Jun 2024 00:30:13 +0500 Subject: [PATCH 4/5] Fix images that used hollow cells Reused item_imgs.rs for image loading and preprocessing, because it is removes hollow cells. Example: assets/voxygen/voxel/armor/misc/head/bear_bonnet.vox --- voxygen/src/bin/img-export.rs | 132 ++++++++-------------------------- voxygen/src/hud/item_imgs.rs | 2 +- 2 files changed, 30 insertions(+), 104 deletions(-) diff --git a/voxygen/src/bin/img-export.rs b/voxygen/src/bin/img-export.rs index 7005f92290..607d1d8cbf 100644 --- a/voxygen/src/bin/img-export.rs +++ b/voxygen/src/bin/img-export.rs @@ -1,11 +1,12 @@ -use clap::Parser; -use common::figure::Segment; -use common_assets::{AssetExt, DotVoxAsset}; use std::{fs, path::Path}; -use vek::{Mat4, Quaternion, Vec2, Vec3, Vec4}; + +use clap::Parser; +use vek::Vec2; + +use common_assets::AssetExt; use veloren_voxygen::{ hud::item_imgs::{ImageSpec, ItemImagesSpec}, - ui::graphic::renderer::{draw_vox, SampleStrat, Transform}, + ui::{graphic::renderer::draw_vox, Graphic}, }; #[derive(Parser)] @@ -18,108 +19,33 @@ struct Cli { pub fn main() { let args = Cli::parse(); let manifest = ItemImagesSpec::load_expect("voxygen.item_image_manifest"); + let image_size = Vec2 { + x: (10_u32 * args.scale) as u16, + y: (10_u32 * args.scale) as u16, + }; for (_, spec) in manifest.read().0.iter() { - match spec { - ImageSpec::Vox(specifier, model_index) => { - voxel_to_png(&specifier, Transform::default(), args.scale, *model_index as usize) + let graphic = spec.create_graphic(); + let img = match graphic { + Graphic::Voxel(segment, trans, sample_strat) => { + draw_vox(&segment, image_size, trans, sample_strat) }, - ImageSpec::VoxTrans(specifier, offset, [rot_x, rot_y, rot_z], zoom, model_index) => { - voxel_to_png( - &specifier, - Transform { - ori: Quaternion::rotation_x(rot_x * std::f32::consts::PI / 180.0) - .rotated_y(rot_y * std::f32::consts::PI / 180.0) - .rotated_z(rot_z * std::f32::consts::PI / 180.0), - offset: Vec3::from(*offset), - /* FIXME: This is a dirty workaround to not cut off the edges of some - * objects like ./img-export/weapon/component/ - * axe/poleaxe/bronze.vox more details here: https://gitlab.com/veloren/veloren/-/merge_requests/3494#note_1205030803 */ - zoom: *zoom * 0.8, - orth: true, - stretch: false, - }, - args.scale, - *model_index as usize, - ) - }, - ImageSpec::Png(specifier) => { - println!("Skip png image {}", specifier); - continue; - }, - } - } -} - -fn voxel_to_png(specifier: &String, transform: Transform, scale: u32, model_index: usize) { - let voxel = match DotVoxAsset::load(&format!("voxygen.{}", specifier)) { - Ok(dot_vox) => dot_vox, - Err(err) => { - println!("Coudn't load voxel: {}", err); + _ => continue, + }; + let specifier = match spec { + ImageSpec::Vox(specifier, _) => specifier, + ImageSpec::VoxTrans(specifier, _, _, _, _) => specifier, + _ => continue, + }; + let path = format!("img-export/{}.png", &specifier_to_path(specifier)); + let folder_path = path.rsplit_once('/').expect("Invalid path").0; + let full_path = Path::new(&path); + if let Err(e) = fs::create_dir_all(Path::new(folder_path)) { + println!("{}", e); return; - }, - }; - let dot_vox_data = &voxel.read().0; - let model_size = dot_vox_data - .models - .get(model_index) - .expect("Error getting model from voxel") - .size; - let ori_mat = Mat4::from(transform.ori); - let aabb_size = Vec3::new(model_size.x, model_size.y, model_size.z); - let projection_size = Vec2 { - x: (10u32 * scale) as u16, - y: (10u32 * scale) as u16, - }; - let segment = Segment::from_vox(dot_vox_data, false, model_index); - let path = format!("img-export/{}.png", &specifier_to_path(specifier)); - let folder_path = path.rsplit_once('/').expect("Invalid path").0; - let full_path = Path::new(&path); - if let Err(e) = fs::create_dir_all(Path::new(folder_path)) { - println!("{}", e); - return; - } + } - draw_vox(&segment, projection_size, transform, SampleStrat::None) - .save(full_path) - .unwrap_or_else(|_| panic!("Can't save file {}", full_path.to_str().expect(""))); -} - -fn calc_rotated_size(ori_mat: &Mat4, aabb_size: &Vec3) -> Vec3 { - let aabb_min = Vec3 { - x: 0f32, - y: 0f32, - z: 0f32, - }; - let aabb_max = Vec3 { - x: aabb_size.x as f32, - y: aabb_size.y as f32, - z: aabb_size.z as f32, - }; - let aabb_vertices: [Vec3; 8] = [ - Vec3::new(aabb_min.x, aabb_min.y, aabb_min.z), - Vec3::new(aabb_max.x, aabb_min.y, aabb_min.z), - Vec3::new(aabb_max.x, aabb_max.y, aabb_min.z), - Vec3::new(aabb_min.x, aabb_max.y, aabb_min.z), - Vec3::new(aabb_min.x, aabb_min.y, aabb_max.z), - Vec3::new(aabb_max.x, aabb_min.y, aabb_max.z), - Vec3::new(aabb_max.x, aabb_max.y, aabb_max.z), - Vec3::new(aabb_min.x, aabb_max.y, aabb_max.z), - ]; - let rotated_vertices = aabb_vertices.map(|c| (*ori_mat * Vec4::::from(c)).xyz()); - let max_xyz = rotated_vertices - .iter() - .copied() - .reduce(|acc, corner| Vec3::::partial_max(acc, corner)) - .expect("Failed find maximum"); - let min_xyz = rotated_vertices - .iter() - .copied() - .reduce(|acc, vertex| Vec3::::partial_min(acc, vertex)) - .expect("Failed find minimum"); - Vec3 { - x: max_xyz.x - min_xyz.x, - y: max_xyz.y - min_xyz.y, - z: max_xyz.z - min_xyz.z, + img.save(full_path) + .unwrap_or_else(|_| panic!("Can't save file {}", full_path.to_str().expect(""))); } } diff --git a/voxygen/src/hud/item_imgs.rs b/voxygen/src/hud/item_imgs.rs index 7d7234f80c..76cb844f8e 100644 --- a/voxygen/src/hud/item_imgs.rs +++ b/voxygen/src/hud/item_imgs.rs @@ -25,7 +25,7 @@ pub enum ImageSpec { VoxTrans(String, [f32; 3], [f32; 3], f32, #[serde(default)] u32), } impl ImageSpec { - fn create_graphic(&self) -> Graphic { + pub fn create_graphic(&self) -> Graphic { match self { ImageSpec::Png(specifier) => Graphic::Image(graceful_load_img(specifier), None), ImageSpec::Vox(specifier, model_index) => Graphic::Voxel( From 7dcc559f51eca89f9c52a5a0b52cf1c7d0ddf660 Mon Sep 17 00:00:00 2001 From: Aidar Shaikhiev Date: Tue, 18 Jun 2024 01:13:50 +0500 Subject: [PATCH 5/5] Fills CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8cbb46f37c..fe54991e31 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -46,6 +46,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - New cultist dungeons are less overly abundant, sahagin dungeons spawn again. - Cultist dungeons now always have exactly one portal which leads to the boss room. - Prompt dialogs are now localized. +- Image-export for wiki now produces correct images of items as they look like in-game. ## [0.16.0] - 2024-03-30