diff --git a/app/src-tauri/tauri.conf.json b/app/src-tauri/tauri.conf.json index 25cb36b5d..dbfa67e8f 100644 --- a/app/src-tauri/tauri.conf.json +++ b/app/src-tauri/tauri.conf.json @@ -66,7 +66,7 @@ "title": "PLATEAU GIS Converter", "fullscreen": false, "resizable": true, - "height": 800, + "height": 900, "width": 640, "minHeight": 600, "minWidth": 500 diff --git a/app/src/routes/+page.svelte b/app/src/routes/+page.svelte index 4f10a09e2..12baf1580 100644 --- a/app/src/routes/+page.svelte +++ b/app/src/routes/+page.svelte @@ -60,7 +60,7 @@ {/if}
-
+

PLATEAU GIS Converter

diff --git a/nusamai-plateau/src/entity.rs b/nusamai-plateau/src/entity.rs index 38198e259..cbec2dfe0 100644 --- a/nusamai-plateau/src/entity.rs +++ b/nusamai-plateau/src/entity.rs @@ -5,7 +5,7 @@ use nusamai_citygml::{geometry::GeometryStore, object::Value}; use crate::appearance::AppearanceStore; /// City objects, features, objects or data -#[derive(Debug, serde::Deserialize, serde::Serialize)] +#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)] pub struct Entity { /// Attribute tree pub root: Value, diff --git a/nusamai/src/option.rs b/nusamai/src/option.rs index 981c38117..099004ced 100644 --- a/nusamai/src/option.rs +++ b/nusamai/src/option.rs @@ -7,16 +7,18 @@ pub fn use_lod_config(default_value: &str) -> TransformerConfig { TransformerConfig { key: "use_lod".to_string(), label: "出力LODの選択".to_string(), - parameter: transformer::ParameterType::Selection(LodSelection::create_lod_selection( - default_value, - )), + parameter: transformer::ParameterType::Selection( + LodSelection::lod_selection_without_texture(default_value), + ), } } -pub fn use_texture_config(default_value: bool) -> TransformerConfig { +pub fn use_textured_lod_config(default_value: &str) -> TransformerConfig { TransformerConfig { - key: "use_texture".to_string(), - label: "テクスチャの使用".to_string(), - parameter: transformer::ParameterType::Boolean(default_value), + key: "use_lod".to_string(), + label: "出力LODの選択".to_string(), + parameter: transformer::ParameterType::Selection(LodSelection::lod_selection_with_texture( + default_value, + )), } } diff --git a/nusamai/src/sink/cesiumtiles/mod.rs b/nusamai/src/sink/cesiumtiles/mod.rs index 1d795d555..4dbb9f49d 100644 --- a/nusamai/src/sink/cesiumtiles/mod.rs +++ b/nusamai/src/sink/cesiumtiles/mod.rs @@ -38,7 +38,7 @@ use url::Url; use crate::{ get_parameter_value, - option::{use_lod_config, use_texture_config}, + option::use_textured_lod_config, parameters::*, pipeline::{Feedback, PipelineError, Receiver, Result}, sink::{DataRequirements, DataSink, DataSinkProvider, SinkInfo}, @@ -69,8 +69,7 @@ impl DataSinkProvider for CesiumTilesSinkProvider { fn transformer_options(&self) -> TransformerRegistry { let mut settings: TransformerRegistry = TransformerRegistry::new(); - settings.insert(use_lod_config("max_lod")); - settings.insert(use_texture_config(false)); + settings.insert(use_textured_lod_config("max_lod")); settings } diff --git a/nusamai/src/sink/gltf/mod.rs b/nusamai/src/sink/gltf/mod.rs index d8df75283..4a7b58cb7 100644 --- a/nusamai/src/sink/gltf/mod.rs +++ b/nusamai/src/sink/gltf/mod.rs @@ -29,7 +29,7 @@ use url::Url; use crate::{ get_parameter_value, - option::{use_lod_config, use_texture_config}, + option::use_textured_lod_config, parameters::*, pipeline::{Feedback, PipelineError, Receiver, Result}, sink::{cesiumtiles::metadata, DataRequirements, DataSink, DataSinkProvider, SinkInfo}, @@ -58,12 +58,10 @@ impl DataSinkProvider for GltfSinkProvider { fn transformer_options(&self) -> TransformerRegistry { let mut settings: TransformerRegistry = TransformerRegistry::new(); - settings.insert(use_lod_config("max_lod")); - settings.insert(use_texture_config(false)); + settings.insert(use_textured_lod_config("max_lod")); settings } - fn create(&self, params: &Parameters) -> Box { let output_path = get_parameter_value!(params, "@output", FileSystemPath); let limit_texture_resolution = diff --git a/nusamai/src/sink/obj/mod.rs b/nusamai/src/sink/obj/mod.rs index 972e8eb62..39acf3aa5 100644 --- a/nusamai/src/sink/obj/mod.rs +++ b/nusamai/src/sink/obj/mod.rs @@ -36,7 +36,7 @@ use nusamai_projection::cartesian::geodetic_to_geocentric; use crate::{ get_parameter_value, - option::{use_lod_config, use_texture_config}, + option::use_textured_lod_config, parameters::*, pipeline::{Feedback, PipelineError, Receiver, Result}, sink::{DataRequirements, DataSink, DataSinkProvider, SinkInfo}, @@ -75,8 +75,7 @@ impl DataSinkProvider for ObjSinkProvider { fn transformer_options(&self) -> TransformerRegistry { let mut settings: TransformerRegistry = TransformerRegistry::new(); - settings.insert(use_lod_config("max_lod")); - settings.insert(use_texture_config(false)); + settings.insert(use_textured_lod_config("max_lod")); settings } diff --git a/nusamai/src/sink/obj/obj_writer.rs b/nusamai/src/sink/obj/obj_writer.rs index efe6c8e0f..eb878d7e3 100644 --- a/nusamai/src/sink/obj/obj_writer.rs +++ b/nusamai/src/sink/obj/obj_writer.rs @@ -47,6 +47,7 @@ fn write_obj( mesh_data.push((feature_id, mesh, vertex_offset, uv_offset)); } + let mut obj_writer = BufWriter::new(File::create(obj_path)?); writeln!(obj_writer, "mtllib {}.mtl", file_name)?; diff --git a/nusamai/src/transformer/setting.rs b/nusamai/src/transformer/setting.rs index dc9f17670..9e6745a42 100644 --- a/nusamai/src/transformer/setting.rs +++ b/nusamai/src/transformer/setting.rs @@ -68,12 +68,26 @@ pub struct LodSelection; impl LodSelection { pub fn get_lod_selection_options() -> Vec<(&'static str, &'static str)> { - vec![("最大LOD", "max_lod"), ("最小LOD", "min_lod")] + vec![ + ("最大LOD", "max_lod"), + ("最小LOD", "min_lod"), + ("テクスチャ付き最大LOD", "textured_max_lod"), + // This option will be used in 3dtiles sink + // ("すべてのLOD", "all_lod"), + ] } - pub fn create_lod_selection(default_value: &str) -> Selection { + pub fn lod_selection_with_texture(default_value: &str) -> Selection { Selection::new(Self::get_lod_selection_options(), default_value) } + + pub fn lod_selection_without_texture(default_value: &str) -> Selection { + let options = Self::get_lod_selection_options() + .into_iter() + .filter(|&(_, value)| value != "textured_max_lod") + .collect::>(); + Selection::new(options, default_value) + } } #[derive(Debug, Serialize, Deserialize, Clone)] @@ -135,10 +149,8 @@ impl TransformerRegistry { ParameterType::String(_value) => { // TODO: Processing for String types. } - ParameterType::Boolean(value) => { - if config.key == "use_texture" { - data_requirements.set_appearance(*value); - } + ParameterType::Boolean(_value) => { + // TODO: Processing for Boolean types. } ParameterType::Integer(_value) => { // TODO: Processing for Integer types. @@ -150,7 +162,7 @@ impl TransformerRegistry { data_requirements.set_lod_filter(transformer::LodFilterSpec { mode: transformer::LodFilterMode::Highest, ..Default::default() - }) + }); } "min_lod" => { data_requirements.set_lod_filter(transformer::LodFilterSpec { @@ -158,6 +170,20 @@ impl TransformerRegistry { ..Default::default() }) } + "textured_max_lod" => { + data_requirements.set_lod_filter(transformer::LodFilterSpec { + mode: transformer::LodFilterMode::TexturedHighest, + ..Default::default() + }); + data_requirements.set_appearance(true); + } + "all_lod" => { + data_requirements.set_lod_filter(transformer::LodFilterSpec { + mode: transformer::LodFilterMode::All, + ..Default::default() + }); + data_requirements.set_appearance(true); + } _ => {} } } diff --git a/nusamai/src/transformer/transform/lods.rs b/nusamai/src/transformer/transform/lods.rs index 10e8b348a..c98f1bb08 100644 --- a/nusamai/src/transformer/transform/lods.rs +++ b/nusamai/src/transformer/transform/lods.rs @@ -12,6 +12,8 @@ use crate::{pipeline::Feedback, transformer::Transform}; pub enum LodFilterMode { Highest, Lowest, + TexturedHighest, + All, } #[derive()] @@ -29,16 +31,68 @@ impl FilterLodTransform { /// Transform to filter and split the LODs impl Transform for FilterLodTransform { fn transform(&mut self, _feedback: &Feedback, mut entity: Entity, out: &mut Vec) { - let lods = find_lods(&entity.root) & self.mask; - - let target_lod = match self.mode { - LodFilterMode::Highest => lods.highest_lod(), - LodFilterMode::Lowest => lods.lowest_lod(), - }; - - if let Some(target_lod) = target_lod { - edit_tree(&mut entity.root, target_lod); - out.push(entity); + match self.mode { + LodFilterMode::TexturedHighest => { + // TODO: Processing needs to be optimised + let original_lods = find_lods(&entity.root) & self.mask; + let mut current_lods = original_lods; + let mut highest_lod_entity = None; + + while current_lods.0 != 0 { + let target_lod = current_lods.highest_lod(); + + if let Some(lod) = target_lod { + // Create a copy of the entity + let mut entity_copy = entity.clone(); + edit_tree(&mut entity_copy.root, lod); + + let has_textures = { + let appearance = entity_copy.appearance_store.read().unwrap(); + !appearance.textures.is_empty() + }; + + if has_textures { + out.push(entity_copy); + return; + } else { + // Save the highest LOD entity + if highest_lod_entity.is_none() { + highest_lod_entity = Some(entity_copy); + } + // Exclude the current LOD and try the next LOD + current_lods.0 &= !(1 << lod); + } + } else { + break; + } + } + + // If no texture is found, push entity with highest LOD + if let Some(highest_entity) = highest_lod_entity { + out.push(highest_entity); + } + } + LodFilterMode::Highest => { + let lods = find_lods(&entity.root) & self.mask; + let target_lod = lods.highest_lod(); + + if let Some(target_lod) = target_lod { + edit_tree(&mut entity.root, target_lod); + out.push(entity); + } + } + LodFilterMode::Lowest => { + let lods = find_lods(&entity.root) & self.mask; + let target_lod = lods.lowest_lod(); + + if let Some(target_lod) = target_lod { + edit_tree(&mut entity.root, target_lod); + out.push(entity); + } + } + LodFilterMode::All => { + out.push(entity); + } } } @@ -92,7 +146,7 @@ fn find_lods(value: &Value) -> LodMask { mask } -#[derive(Default, Clone, Copy)] +#[derive(Default, Clone, Copy, Debug)] pub struct LodMask( u8, // lods bit mask );