Skip to content

Commit

Permalink
Merge branch 'main' into feature/lod-option
Browse files Browse the repository at this point in the history
  • Loading branch information
satoshi7190 committed Sep 2, 2024
2 parents a4e6dc0 + 7e77d88 commit 3079c22
Show file tree
Hide file tree
Showing 7 changed files with 133 additions and 58 deletions.
8 changes: 4 additions & 4 deletions app/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
"postcss": "^8.4.35",
"prettier": "^3.2.5",
"prettier-plugin-svelte": "^3.1.2",
"svelte": "^4.2.10",
"svelte": "^4.2.19",
"svelte-check": "^3.6.4",
"svelte-virtual-scroll-list": "^1.3.0",
"tailwindcss": "^3.4.1",
Expand Down
75 changes: 24 additions & 51 deletions nusamai/src/sink/cesiumtiles/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,20 +48,7 @@ use crate::{
};
use utils::calculate_normal;

const MAX_PIXEL_PER_DISTANCE: f64 = 30.0;

// WARN: This function has an equivalent in `atlas-packer/src/texture.rs`.
fn uv_to_pixel_coords(uv_coords: &[(f64, f64)], width: u32, height: u32) -> Vec<(u32, u32)> {
uv_coords
.iter()
.map(|(u, v)| {
(
(u.clamp(0.0, 1.0) * width as f64).min(width as f64 - 1.0) as u32,
((1.0 - v.clamp(0.0, 1.0)) * height as f64).min(height as f64 - 1.0) as u32,
)
})
.collect()
}
use super::texture_resolution::get_texture_downsample_scale_of_polygon;

pub struct CesiumTilesSinkProvider {}

Expand Down Expand Up @@ -90,6 +77,16 @@ impl DataSinkProvider for CesiumTilesSinkProvider {
// TODO: min Zoom
// TODO: max Zoom

params.define(
"limit_texture_resolution".into(),
ParameterEntry {
description: "limiting texture resolution".into(),
required: false,
parameter: ParameterType::Boolean(BooleanParameter { value: None }),
label: Some("距離(メートル)あたりのテクスチャの解像度を制限する".into()),
},
);

params
}

Expand Down Expand Up @@ -125,18 +122,22 @@ impl DataSinkProvider for CesiumTilesSinkProvider {

fn create(&self, params: &Parameters) -> Box<dyn DataSink> {
let output_path = get_parameter_value!(params, "@output", FileSystemPath);
let limit_texture_resolution =
*get_parameter_value!(params, "limit_texture_resolution", Boolean);
let transform_settings = self.available_transformer();

Box::<CesiumTilesSink>::new(CesiumTilesSink {
output_path: output_path.as_ref().unwrap().into(),
transform_settings,
limit_texture_resolution,
})
}
}

struct CesiumTilesSink {
output_path: PathBuf,
transform_settings: TransformerRegistry,
limit_texture_resolution: Option<bool>,
}

impl DataSink for CesiumTilesSink {
Expand Down Expand Up @@ -164,6 +165,8 @@ impl DataSink for CesiumTilesSink {
let min_zoom = 12;
let max_zoom = 18;

let limit_texture_resolution = self.limit_texture_resolution;

// TODO: refactoring

std::thread::scope(|s| {
Expand Down Expand Up @@ -210,6 +213,7 @@ impl DataSink for CesiumTilesSink {
receiver_sorted,
tile_id_conv,
schema,
limit_texture_resolution,
) {
feedback.fatal_error(error);
}
Expand Down Expand Up @@ -331,6 +335,7 @@ fn tile_writing_stage(
receiver_sorted: mpsc::Receiver<(u64, String, Vec<Vec<u8>>)>,
tile_id_conv: TileIdMethod,
schema: &Schema,
limit_texture_resolution: Option<bool>,
) -> Result<()> {
let ellipsoid = nusamai_projection::ellipsoid::wgs84();
let contents: Arc<Mutex<Vec<TileContent>>> = Default::default();
Expand Down Expand Up @@ -533,43 +538,11 @@ fn tile_writing_stage(
let texture_uri = base_texture.uri.to_file_path().unwrap();
let texture_size = texture_size_cache.get_or_insert(&texture_uri);

let pixel_coords =
uv_to_pixel_coords(&uv_coords, texture_size.0, texture_size.1);

let pixel_per_distance = (0..original_vertices.len())
.map(|i| {
let j = (i + 1) % original_vertices.len();
let (euc0, txl0) = (
(
original_vertices[i].0,
original_vertices[i].1,
original_vertices[i].2,
),
pixel_coords[i],
);
let (euc1, txl1) = (
(
original_vertices[j].0,
original_vertices[j].1,
original_vertices[j].2,
),
pixel_coords[j],
);
let euc_dist = ((euc0.0 - euc1.0).powi(2)
+ (euc0.1 - euc1.1).powi(2)
+ (euc0.2 - euc1.2).powi(2))
.sqrt();
let txl_dist = ((txl0.0 as f64 - txl1.0 as f64).powi(2)
+ (txl0.1 as f64 - txl1.1 as f64).powi(2))
.sqrt();
txl_dist / euc_dist
})
.min_by(|a, b| a.total_cmp(b))
.unwrap_or(1.0);

let max_pixel_per_distance = MAX_PIXEL_PER_DISTANCE;
let downsample_scale =
(1.0_f64).min(max_pixel_per_distance / pixel_per_distance);
let downsample_scale = get_texture_downsample_scale_of_polygon(
&original_vertices,
texture_size,
limit_texture_resolution,
);
let factor = apply_downsample_factor(tile_zoom, downsample_scale as f32);

let downsample_factor = DownsampleFactor::new(&factor);
Expand Down
25 changes: 24 additions & 1 deletion nusamai/src/sink/gltf/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ use crate::{
},
};

use super::texture_resolution::get_texture_downsample_scale_of_polygon;

pub struct GltfSinkProvider {}

impl DataSinkProvider for GltfSinkProvider {
Expand All @@ -63,6 +65,16 @@ impl DataSinkProvider for GltfSinkProvider {
},
);

params.define(
"limit_texture_resolution".into(),
ParameterEntry {
description: "limiting texture resolution".into(),
required: false,
parameter: ParameterType::Boolean(BooleanParameter { value: None }),
label: Some("距離(メートル)あたりのテクスチャの解像度を制限する".into()),
},
);

params
}

Expand Down Expand Up @@ -98,18 +110,22 @@ impl DataSinkProvider for GltfSinkProvider {

fn create(&self, params: &Parameters) -> Box<dyn DataSink> {
let output_path = get_parameter_value!(params, "@output", FileSystemPath);
let limit_texture_resolution =
*get_parameter_value!(params, "limit_texture_resolution", Boolean);
let transform_settings = self.available_transformer();

Box::<GltfSink>::new(GltfSink {
output_path: output_path.as_ref().unwrap().into(),
transform_settings,
limit_texture_resolution,
})
}
}

pub struct GltfSink {
output_path: PathBuf,
transform_settings: TransformerRegistry,
limit_texture_resolution: Option<bool>,
}

pub struct BoundingVolume {
Expand Down Expand Up @@ -456,7 +472,14 @@ impl DataSink for GltfSink {

let texture_uri = base_texture.uri.to_file_path().unwrap();
let texture_size = texture_size_cache.get_or_insert(&texture_uri);
let downsample_factor = DownsampleFactor::new(&1.0);

let downsample_scale = get_texture_downsample_scale_of_polygon(
&original_vertices,
texture_size,
self.limit_texture_resolution,
) as f32;

let downsample_factor = DownsampleFactor::new(&downsample_scale);
let cropped_texture = CroppedTexture::new(
&texture_uri,
texture_size,
Expand Down
1 change: 1 addition & 0 deletions nusamai/src/sink/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ pub mod obj;
pub mod ply;
pub mod serde;
pub mod shapefile;
mod texture_resolution;

use nusamai_citygml::schema::Schema;
use nusamai_projection::crs;
Expand Down
27 changes: 26 additions & 1 deletion nusamai/src/sink/obj/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ use crate::{
},
};

use super::texture_resolution::get_texture_downsample_scale_of_polygon;

pub struct ObjSinkProvider {}

impl DataSinkProvider for ObjSinkProvider {
Expand Down Expand Up @@ -80,6 +82,16 @@ impl DataSinkProvider for ObjSinkProvider {
},
);

params.define(
"limit_texture_resolution".into(),
ParameterEntry {
description: "limiting texture resolution".into(),
required: false,
parameter: ParameterType::Boolean(BooleanParameter { value: None }),
label: Some("距離(メートル)あたりのテクスチャの解像度を制限する".into()),
},
);

params
}

Expand Down Expand Up @@ -115,13 +127,16 @@ impl DataSinkProvider for ObjSinkProvider {

fn create(&self, params: &Parameters) -> Box<dyn DataSink> {
let output_path = get_parameter_value!(params, "@output", FileSystemPath);
let limit_texture_resolution =
*get_parameter_value!(params, "limit_texture_resolution", Boolean);
let transform_options = self.available_transformer();
let is_split = get_parameter_value!(params, "split", Boolean).unwrap();

Box::<ObjSink>::new(ObjSink {
output_path: output_path.as_ref().unwrap().into(),
transform_settings: transform_options,
obj_options: ObjParams { is_split },
limit_texture_resolution,
})
}
}
Expand All @@ -130,6 +145,7 @@ pub struct ObjSink {
output_path: PathBuf,
transform_settings: TransformerRegistry,
obj_options: ObjParams,
limit_texture_resolution: Option<bool>,
}

struct ObjParams {
Expand Down Expand Up @@ -489,10 +505,19 @@ impl DataSink for ObjSink {
.iter()
.map(|(_, _, _, u, v)| (*u, *v))
.collect::<Vec<(f64, f64)>>();
let downsample_factor = DownsampleFactor::new(&1.0);

let texture_size =
texture_size_cache.get_or_insert(&texture_uri);
let downsample_scale = get_texture_downsample_scale_of_polygon(
&original_vertices,
texture_size,
self.limit_texture_resolution,
)
as f32;

let downsample_factor =
DownsampleFactor::new(&downsample_scale);

let texture = CroppedTexture::new(
&texture_uri,
texture_size,
Expand Down
53 changes: 53 additions & 0 deletions nusamai/src/sink/texture_resolution.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/// Limits the texture resolution based on the distance (meters) between the vertices of a polygon.
const MAX_TEXTURE_PIXELS_PER_METER: f64 = 30.0;

// WARN: This function has an equivalent in `atlas-packer/src/texture.rs`.
fn uv_to_pixel_coords(uv_coords: &[(f64, f64)], width: u32, height: u32) -> Vec<(u32, u32)> {
uv_coords
.iter()
.map(|(u, v)| {
(
(u.clamp(0.0, 1.0) * width as f64).min(width as f64 - 1.0) as u32,
((1.0 - v.clamp(0.0, 1.0)) * height as f64).min(height as f64 - 1.0) as u32,
)
})
.collect()
}

pub fn get_texture_downsample_scale_of_polygon(
vertices: &[(f64, f64, f64, f64, f64)], // (x, y, z, u, v)
texture_size: (u32, u32),
limit_texture_resolution: Option<bool>,
) -> f64 {
let uv_coords = vertices.iter().map(|v| (v.3, v.4)).collect::<Vec<_>>();

let pixel_coords = uv_to_pixel_coords(&uv_coords, texture_size.0, texture_size.1);

let pixel_per_distance = (0..vertices.len())
.map(|i| {
let j = (i + 1) % vertices.len();
let (euc0, txl0) = (
(vertices[i].0, vertices[i].1, vertices[i].2),
pixel_coords[i],
);
let (euc1, txl1) = (
(vertices[j].0, vertices[j].1, vertices[j].2),
pixel_coords[j],
);
let euc_dist =
((euc0.0 - euc1.0).powi(2) + (euc0.1 - euc1.1).powi(2) + (euc0.2 - euc1.2).powi(2))
.sqrt();
let txl_dist = ((txl0.0 as f64 - txl1.0 as f64).powi(2)
+ (txl0.1 as f64 - txl1.1 as f64).powi(2))
.sqrt();
txl_dist / euc_dist
})
.min_by(|a, b| a.total_cmp(b))
.unwrap_or(1.0);

if limit_texture_resolution.unwrap_or(false) {
1.0_f64.min(MAX_TEXTURE_PIXELS_PER_METER / pixel_per_distance)
} else {
1.0
}
}

0 comments on commit 3079c22

Please sign in to comment.