mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Merge branch 'muphblu/item-img-export' into 'master'
Items images export for wiki Closes #1334 See merge request veloren/veloren!3494
This commit is contained in:
commit
c90be1b56c
@ -16,6 +16,7 @@ csv-export = "run --manifest-path common/Cargo.toml --features=bin_csv --bin csv
|
|||||||
csv-import = "run --manifest-path common/Cargo.toml --features=bin_csv --bin csv_import"
|
csv-import = "run --manifest-path common/Cargo.toml --features=bin_csv --bin csv_import"
|
||||||
dot-recipes = "run --manifest-path common/Cargo.toml --features=bin_graphviz --bin recipe_graphviz"
|
dot-recipes = "run --manifest-path common/Cargo.toml --features=bin_graphviz --bin recipe_graphviz"
|
||||||
dot-skills = "run --manifest-path common/Cargo.toml --features=bin_graphviz --bin skill_graphviz"
|
dot-skills = "run --manifest-path common/Cargo.toml --features=bin_graphviz --bin skill_graphviz"
|
||||||
|
img-export = "run --manifest-path voxygen/Cargo.toml --features=bin_img-export --bin img-export"
|
||||||
# server-cli
|
# server-cli
|
||||||
server = "run --bin veloren-server-cli"
|
server = "run --bin veloren-server-cli"
|
||||||
test-server = "run --bin veloren-server-cli --no-default-features --features simd"
|
test-server = "run --bin veloren-server-cli --no-default-features --features simd"
|
||||||
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -52,6 +52,7 @@ wgpu-trace/
|
|||||||
|
|
||||||
# Export data
|
# Export data
|
||||||
*.csv
|
*.csv
|
||||||
|
img-export/**/*.png
|
||||||
|
|
||||||
# Game data
|
# Game data
|
||||||
*.sqlite
|
*.sqlite
|
||||||
|
@ -38,6 +38,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
- NPCs now move to their target's last known position.
|
- NPCs now move to their target's last known position.
|
||||||
- Experience bar below the hotbar
|
- Experience bar below the hotbar
|
||||||
- Bridges.
|
- Bridges.
|
||||||
|
- Tool for exporting PNG images of all in-game models (`cargo img-export`)
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
@ -78,6 +79,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
- Camera jittering in third person has been significantly reduced
|
- Camera jittering in third person has been significantly reduced
|
||||||
- Many water shader issues have been fixed
|
- Many water shader issues have been fixed
|
||||||
- Flee if attacked even if attacker is not close.
|
- Flee if attacked even if attacker is not close.
|
||||||
|
- `/time` command will never rewind time, only advance it to not break rtsim
|
||||||
|
|
||||||
## [0.13.0] - 2022-07-23
|
## [0.13.0] - 2022-07-23
|
||||||
|
|
||||||
|
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -7104,6 +7104,7 @@ dependencies = [
|
|||||||
"veloren-client",
|
"veloren-client",
|
||||||
"veloren-client-i18n",
|
"veloren-client-i18n",
|
||||||
"veloren-common",
|
"veloren-common",
|
||||||
|
"veloren-common-assets",
|
||||||
"veloren-common-base",
|
"veloren-common-base",
|
||||||
"veloren-common-ecs",
|
"veloren-common-ecs",
|
||||||
"veloren-common-frontend",
|
"veloren-common-frontend",
|
||||||
|
@ -31,6 +31,7 @@ plugins = ["client/plugins"]
|
|||||||
egui-ui = ["voxygen-egui", "egui", "egui_wgpu_backend", "egui_winit_platform"]
|
egui-ui = ["voxygen-egui", "egui", "egui_wgpu_backend", "egui_winit_platform"]
|
||||||
shaderc-from-source = ["shaderc/build-from-source"]
|
shaderc-from-source = ["shaderc/build-from-source"]
|
||||||
discord = ["discord-sdk"]
|
discord = ["discord-sdk"]
|
||||||
|
bin_img-export = ["common-assets"]
|
||||||
|
|
||||||
# We don't ship egui with published release builds so a separate feature is required that excludes it.
|
# We don't ship egui with published release builds so a separate feature is required that excludes it.
|
||||||
default-publish = ["singleplayer", "native-dialog", "plugins", "discord", "simd"]
|
default-publish = ["singleplayer", "native-dialog", "plugins", "discord", "simd"]
|
||||||
@ -41,12 +42,13 @@ default = ["default-no-egui", "egui-ui"]
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
client = {package = "veloren-client", path = "../client"}
|
client = {package = "veloren-client", path = "../client"}
|
||||||
common = {package = "veloren-common", path = "../common"}
|
common = {package = "veloren-common", path = "../common"}
|
||||||
|
common-assets = {package = "veloren-common-assets", path = "../common/assets", optional = true} # img-export
|
||||||
common-base = {package = "veloren-common-base", path = "../common/base"}
|
common-base = {package = "veloren-common-base", path = "../common/base"}
|
||||||
common-ecs = {package = "veloren-common-ecs", path = "../common/ecs"}
|
common-ecs = {package = "veloren-common-ecs", path = "../common/ecs"}
|
||||||
common-frontend = {package = "veloren-common-frontend", path = "../common/frontend"}
|
common-frontend = {package = "veloren-common-frontend", path = "../common/frontend"}
|
||||||
common-net = {package = "veloren-common-net", path = "../common/net"}
|
common-net = {package = "veloren-common-net", path = "../common/net"}
|
||||||
common-systems = {package = "veloren-common-systems", path = "../common/systems"}
|
|
||||||
common-state = {package = "veloren-common-state", path = "../common/state"}
|
common-state = {package = "veloren-common-state", path = "../common/state"}
|
||||||
|
common-systems = {package = "veloren-common-systems", path = "../common/systems"}
|
||||||
|
|
||||||
anim = {package = "veloren-voxygen-anim", path = "anim"}
|
anim = {package = "veloren-voxygen-anim", path = "anim"}
|
||||||
i18n = {package = "veloren-client-i18n", path = "../client/i18n"}
|
i18n = {package = "veloren-client-i18n", path = "../client/i18n"}
|
||||||
@ -160,3 +162,7 @@ rayon = "1.5.0"
|
|||||||
[[bench]]
|
[[bench]]
|
||||||
harness = false
|
harness = false
|
||||||
name = "meshing_benchmark"
|
name = "meshing_benchmark"
|
||||||
|
|
||||||
|
[[bin]]
|
||||||
|
name = "img-export"
|
||||||
|
required-features = ["bin_img-export"]
|
||||||
|
129
voxygen/src/bin/img-export.rs
Normal file
129
voxygen/src/bin/img-export.rs
Normal file
@ -0,0 +1,129 @@
|
|||||||
|
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 veloren_voxygen::{
|
||||||
|
hud::item_imgs::{ImageSpec, ItemImagesSpec},
|
||||||
|
ui::graphic::renderer::{draw_vox, SampleStrat, Transform},
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(Parser)]
|
||||||
|
struct Cli {
|
||||||
|
///Optional width and height scaling
|
||||||
|
#[clap(default_value_t = 20)]
|
||||||
|
scale: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn main() {
|
||||||
|
let args = Cli::parse();
|
||||||
|
let manifest = ItemImagesSpec::load_expect("voxygen.item_image_manifest");
|
||||||
|
for (_, spec) in manifest.read().0.iter() {
|
||||||
|
match spec {
|
||||||
|
ImageSpec::Vox(specifier) => voxel_to_png(&specifier, Transform::default(), args.scale),
|
||||||
|
ImageSpec::VoxTrans(specifier, offset, [rot_x, rot_y, rot_z], zoom) => 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,
|
||||||
|
),
|
||||||
|
ImageSpec::Png(specifier) => {
|
||||||
|
println!("Skip png image {}", specifier);
|
||||||
|
continue;
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn voxel_to_png(specifier: &String, transform: Transform, scale: u32) {
|
||||||
|
let voxel = match DotVoxAsset::load(&format!("voxygen.{}", specifier)) {
|
||||||
|
Ok(dot_vox) => dot_vox,
|
||||||
|
Err(err) => {
|
||||||
|
println!("Coudn't load voxel: {}", err);
|
||||||
|
return;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
let dot_vox_data = &voxel.read().0;
|
||||||
|
let model_size = dot_vox_data
|
||||||
|
.models
|
||||||
|
.get(0)
|
||||||
|
.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)
|
||||||
|
.save(full_path)
|
||||||
|
.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,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn specifier_to_path(specifier: &String) -> String {
|
||||||
|
specifier
|
||||||
|
.strip_prefix("voxel.")
|
||||||
|
.unwrap_or_else(|| panic!("There was no prefix in {}", specifier))
|
||||||
|
.replace('.', "/")
|
||||||
|
}
|
@ -18,7 +18,7 @@ pub fn animate_by_pulse(ids: &[Id], pulse: f32) -> Id {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
enum ImageSpec {
|
pub enum ImageSpec {
|
||||||
Png(String),
|
Png(String),
|
||||||
Vox(String),
|
Vox(String),
|
||||||
// (specifier, offset, (axis, 2 * angle / pi), zoom)
|
// (specifier, offset, (axis, 2 * angle / pi), zoom)
|
||||||
@ -54,7 +54,7 @@ impl ImageSpec {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
struct ItemImagesSpec(HashMap<ItemKey, ImageSpec>);
|
pub struct ItemImagesSpec(pub HashMap<ItemKey, ImageSpec>);
|
||||||
impl assets::Asset for ItemImagesSpec {
|
impl assets::Asset for ItemImagesSpec {
|
||||||
type Loader = assets::RonLoader;
|
type Loader = assets::RonLoader;
|
||||||
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
mod pixel_art;
|
mod pixel_art;
|
||||||
mod renderer;
|
pub mod renderer;
|
||||||
|
|
||||||
pub use renderer::{SampleStrat, Transform};
|
pub use renderer::{SampleStrat, Transform};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
mod cache;
|
mod cache;
|
||||||
mod event;
|
mod event;
|
||||||
mod graphic;
|
pub mod graphic;
|
||||||
mod scale;
|
mod scale;
|
||||||
mod widgets;
|
mod widgets;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
|
Loading…
Reference in New Issue
Block a user