mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Merge branch 'muphblu/fix-item-img-export' into 'master'
Fixes img-export #1761 set square dimensions for image Closes #1761 See merge request veloren/veloren!4505
This commit is contained in:
commit
d6d9c2ca57
@ -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.
|
- 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.
|
- Cultist dungeons now always have exactly one portal which leads to the boss room.
|
||||||
- Prompt dialogs are now localized.
|
- 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
|
## [0.16.0] - 2024-03-30
|
||||||
|
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
use clap::Parser;
|
|
||||||
use common::figure::Segment;
|
|
||||||
use common_assets::{AssetExt, DotVoxAsset};
|
|
||||||
use std::{fs, path::Path};
|
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::{
|
use veloren_voxygen::{
|
||||||
hud::item_imgs::{ImageSpec, ItemImagesSpec},
|
hud::item_imgs::{ImageSpec, ItemImagesSpec},
|
||||||
ui::graphic::renderer::{draw_vox, SampleStrat, Transform},
|
ui::{graphic::renderer::draw_vox, Graphic},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Parser)]
|
#[derive(Parser)]
|
||||||
@ -18,111 +19,33 @@ struct Cli {
|
|||||||
pub fn main() {
|
pub fn main() {
|
||||||
let args = Cli::parse();
|
let args = Cli::parse();
|
||||||
let manifest = ItemImagesSpec::load_expect("voxygen.item_image_manifest");
|
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() {
|
for (_, spec) in manifest.read().0.iter() {
|
||||||
match spec {
|
let graphic = spec.create_graphic();
|
||||||
ImageSpec::Vox(specifier, model_index) => {
|
let img = match graphic {
|
||||||
voxel_to_png(&specifier, Transform::default(), args.scale, model_index)
|
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) => {
|
_ => continue,
|
||||||
voxel_to_png(
|
};
|
||||||
&specifier,
|
let specifier = match spec {
|
||||||
Transform {
|
ImageSpec::Vox(specifier, _) => specifier,
|
||||||
ori: Quaternion::rotation_x(rot_x * std::f32::consts::PI / 180.0)
|
ImageSpec::VoxTrans(specifier, _, _, _, _) => specifier,
|
||||||
.rotated_y(rot_y * std::f32::consts::PI / 180.0)
|
_ => continue,
|
||||||
.rotated_z(rot_z * std::f32::consts::PI / 180.0),
|
};
|
||||||
offset: Vec3::from(*offset),
|
let path = format!("img-export/{}.png", &specifier_to_path(specifier));
|
||||||
/* FIXME: This is a dirty workaround to not cut off the edges of some
|
let folder_path = path.rsplit_once('/').expect("Invalid path").0;
|
||||||
* objects like ./img-export/weapon/component/
|
let full_path = Path::new(&path);
|
||||||
* axe/poleaxe/bronze.vox more details here: https://gitlab.com/veloren/veloren/-/merge_requests/3494#note_1205030803 */
|
if let Err(e) = fs::create_dir_all(Path::new(folder_path)) {
|
||||||
zoom: *zoom * 0.8,
|
println!("{}", e);
|
||||||
orth: true,
|
|
||||||
stretch: false,
|
|
||||||
},
|
|
||||||
args.scale,
|
|
||||||
model_index,
|
|
||||||
)
|
|
||||||
},
|
|
||||||
ImageSpec::Png(specifier) => {
|
|
||||||
println!("Skip png image {}", specifier);
|
|
||||||
continue;
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn voxel_to_png(specifier: &String, transform: Transform, scale: u32, model_index: u32) {
|
|
||||||
let voxel = match DotVoxAsset::load(&format!("voxygen.{}", specifier)) {
|
|
||||||
Ok(dot_vox) => dot_vox,
|
|
||||||
Err(err) => {
|
|
||||||
println!("Coudn't load voxel: {}", err);
|
|
||||||
return;
|
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);
|
|
||||||
//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.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 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)
|
img.save(full_path)
|
||||||
.save(full_path)
|
.unwrap_or_else(|_| panic!("Can't save file {}", full_path.to_str().expect("")));
|
||||||
.unwrap_or_else(|_| panic!("Can't save file {}", full_path.to_str().expect("")));
|
|
||||||
}
|
|
||||||
|
|
||||||
fn calc_rotated_size(ori_mat: &Mat4<f32>, aabb_size: &Vec3<u32>) -> Vec3<f32> {
|
|
||||||
let aabb_min = Vec3 {
|
|
||||||
x: 0f32,
|
|
||||||
y: 0f32,
|
|
||||||
z: 0f32,
|
|
||||||
};
|
|
||||||
let aabb_max = Vec3 {
|
|
||||||
x: aabb_size.y as f32,
|
|
||||||
y: aabb_size.z as f32,
|
|
||||||
z: aabb_size.x as f32,
|
|
||||||
};
|
|
||||||
let aabb_vertices: [Vec3<f32>; 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| (Vec4::<f32>::from(c) * *ori_mat).xyz());
|
|
||||||
let max_xyz = rotated_vertices
|
|
||||||
.iter()
|
|
||||||
.copied()
|
|
||||||
.reduce(|acc, corner| Vec3::<f32>::partial_max(acc, corner))
|
|
||||||
.expect("Failed find maximum");
|
|
||||||
let min_xyz = rotated_vertices
|
|
||||||
.iter()
|
|
||||||
.copied()
|
|
||||||
.reduce(|acc, vertex| Vec3::<f32>::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,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,7 +25,7 @@ pub enum ImageSpec {
|
|||||||
VoxTrans(String, [f32; 3], [f32; 3], f32, #[serde(default)] u32),
|
VoxTrans(String, [f32; 3], [f32; 3], f32, #[serde(default)] u32),
|
||||||
}
|
}
|
||||||
impl ImageSpec {
|
impl ImageSpec {
|
||||||
fn create_graphic(&self) -> Graphic {
|
pub fn create_graphic(&self) -> Graphic {
|
||||||
match self {
|
match self {
|
||||||
ImageSpec::Png(specifier) => Graphic::Image(graceful_load_img(specifier), None),
|
ImageSpec::Png(specifier) => Graphic::Image(graceful_load_img(specifier), None),
|
||||||
ImageSpec::Vox(specifier, model_index) => Graphic::Voxel(
|
ImageSpec::Vox(specifier, model_index) => Graphic::Voxel(
|
||||||
|
Loading…
Reference in New Issue
Block a user