1use anyhow::Result;
3use clap::{Args, ValueEnum};
4use glam::{Mat4, Vec4};
5use std::fmt;
6use std::path::Path;
7use voxquant_core::{Format, OutputFormat, VoxelizationConfig, scene::Scene};
8
9mod serialization;
10mod voxelization;
11
12#[derive(Debug, Clone, Copy, ValueEnum)]
15pub enum ColorMode {
16 #[value(name = "static")]
19 Static,
20 #[cfg(feature = "dynamic_palette")]
24 #[value(name = "dynamic")]
25 Dynamic,
26}
27
28impl fmt::Display for ColorMode {
29 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
30 match self {
31 Self::Static => f.write_str("static"),
32 #[cfg(feature = "dynamic_palette")]
33 Self::Dynamic => f.write_str("dynamic"),
34 }
35 }
36}
37
38#[profiling::function]
39fn voxelize_and_save(
40 scene: Scene,
41 format_config: &DotVoxConfig,
42 voxelization_config: &VoxelizationConfig,
43 output: &Path,
44) -> Result<()> {
45 let largest_dim = scene.bounds.size().max_element();
46 let scale = voxelization_config.res as f32 / largest_dim;
47
48 let voxel_bounds_size = scene.bounds.size() * scale;
49
50 let center_offset = -(voxel_bounds_size / 2.0).round().as_ivec3() + 128;
51
52 match format_config.color {
53 ColorMode::Static => {
54 let data = voxelization::voxelize(
55 &scene,
56 voxelization_config.res,
57 voxelization_config.mode,
58 !format_config.no_optimization,
59 );
60
61 serialization::save_vox_static(data, output, center_offset)?;
62 }
63 #[cfg(feature = "dynamic_palette")]
64 ColorMode::Dynamic => {
65 let data = voxelization::voxelize(
66 &scene,
67 voxelization_config.res,
68 voxelization_config.mode,
69 !format_config.no_optimization,
70 );
71
72 serialization::save_vox_dynamic(data, output, center_offset)?;
73 }
74 }
75
76 Ok(())
77}
78
79#[derive(Debug, Args)]
81#[command(next_help_heading = "`.vox` format options")]
82pub struct DotVoxConfig {
83 #[cfg_attr(feature = "dynamic_palette", arg(long, default_value_t = ColorMode::Dynamic))]
89 #[cfg_attr(not(feature = "dynamic_palette"), arg(long, default_value_t = ColorMode::Static))]
90 pub color: ColorMode,
91
92 #[arg(long, default_value_t = false)]
96 pub no_optimization: bool,
97}
98
99pub struct DotVox;
101
102impl Format for DotVox {
103 const BASIS: Mat4 = Mat4::from_cols(
105 Vec4::new(1.0, 0.0, 0.0, 0.0),
106 Vec4::new(0.0, 0.0, 1.0, 0.0),
107 Vec4::new(0.0, 1.0, 0.0, 0.0),
108 Vec4::new(0.0, 0.0, 0.0, 1.0),
109 );
110}
111
112impl OutputFormat for DotVox {
113 type Config = DotVoxConfig;
114
115 fn voxelize_and_save(
116 scene: Scene,
117 output: &Path,
118 format_config: Self::Config,
119 voxelization_config: &VoxelizationConfig,
120 ) -> Result<()> {
121 voxelize_and_save(scene, &format_config, voxelization_config, output)
122 }
123}