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
);