fix(render): scale solid tessellation
Derive one drawing-space chordal tolerance so large curves stay smooth while small solids avoid excessive detail.
This commit is contained in:
parent
7b4af0aa75
commit
ca331fff48
7 changed files with 138 additions and 32 deletions
2
Cargo.lock
generated
2
Cargo.lock
generated
|
|
@ -890,7 +890,7 @@ checksum = "fc652a48c352aef3ea3aed32080501cf3ef6ed5da78602a020c991775b0aff04"
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cadkernel"
|
name = "cadkernel"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/HakanSeven12/cadkernel.git?rev=574cf13#574cf13345c266cce01f4413c2ba54dff936f8ab"
|
source = "git+https://github.com/HakanSeven12/cadkernel.git?rev=07f0739#07f0739549892f2ba8b7556932a0f831c4b64052"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"acadrust",
|
"acadrust",
|
||||||
"cavalier_contours",
|
"cavalier_contours",
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,7 @@ rfd = "0.17"
|
||||||
clap = { version = "4", features = ["derive"] }
|
clap = { version = "4", features = ["derive"] }
|
||||||
env_logger = "0.11"
|
env_logger = "0.11"
|
||||||
acadrust = { git = "https://github.com/HakanSeven12/cadcodec.git", rev = "74c5fe9", features = ["serde"] }
|
acadrust = { git = "https://github.com/HakanSeven12/cadcodec.git", rev = "74c5fe9", features = ["serde"] }
|
||||||
cadkernel = { git = "https://github.com/HakanSeven12/cadkernel.git", rev = "574cf13", features = ["acis", "offset"] }
|
cadkernel = { git = "https://github.com/HakanSeven12/cadkernel.git", rev = "07f0739", features = ["acis", "offset"] }
|
||||||
acadifc = { git = "https://github.com/OpenAEC-Foundation/acadifc.git", rev = "47b5603", optional = true }
|
acadifc = { git = "https://github.com/OpenAEC-Foundation/acadifc.git", rev = "47b5603", optional = true }
|
||||||
dwg-thumbnailer = { path = "crates/dwg-thumbnailer" }
|
dwg-thumbnailer = { path = "crates/dwg-thumbnailer" }
|
||||||
flate2 = "1"
|
flate2 = "1"
|
||||||
|
|
|
||||||
|
|
@ -747,6 +747,33 @@ use crate::scene::model::mesh_model::MeshLodSet;
|
||||||
use crate::scene::convert::solid3d_tess;
|
use crate::scene::convert::solid3d_tess;
|
||||||
use acadrust::{types::Vector3, EntityType};
|
use acadrust::{types::Vector3, EntityType};
|
||||||
|
|
||||||
|
const DISPLAY_DEFLECTION_COEFFICIENT: f64 = 2.5e-4;
|
||||||
|
|
||||||
|
/// Shared world-space chord tolerance for solid display.
|
||||||
|
pub fn display_deflection(
|
||||||
|
header: &acadrust::document::HeaderVariables,
|
||||||
|
facet_res: f64,
|
||||||
|
) -> Option<f64> {
|
||||||
|
let low = header.model_space_extents_min;
|
||||||
|
let high = header.model_space_extents_max;
|
||||||
|
let spans = [high.x - low.x, high.y - low.y, high.z - low.z];
|
||||||
|
let span = spans
|
||||||
|
.into_iter()
|
||||||
|
.filter(|value| value.is_finite() && *value > 0.0)
|
||||||
|
.fold(0.0, f64::max);
|
||||||
|
if !span.is_finite() || span <= 0.0 || span > 1.0e16 {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
let resolution = if facet_res.is_finite() && facet_res > 0.0 {
|
||||||
|
facet_res.clamp(0.01, 10.0)
|
||||||
|
} else {
|
||||||
|
1.0
|
||||||
|
};
|
||||||
|
Some(
|
||||||
|
(span * DISPLAY_DEFLECTION_COEFFICIENT / resolution.max(1.0).sqrt()).max(1e-9),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
/// `point_of_reference` of an ACIS-backed volume entity, if applicable.
|
/// `point_of_reference` of an ACIS-backed volume entity, if applicable.
|
||||||
pub fn point_of_reference(e: &EntityType) -> Option<&Vector3> {
|
pub fn point_of_reference(e: &EntityType) -> Option<&Vector3> {
|
||||||
match e {
|
match e {
|
||||||
|
|
@ -764,13 +791,38 @@ pub fn tessellate_volume(
|
||||||
e: &EntityType,
|
e: &EntityType,
|
||||||
color: [f32; 4],
|
color: [f32; 4],
|
||||||
facet_res: f64,
|
facet_res: f64,
|
||||||
|
chordal_deflection: Option<f64>,
|
||||||
isolines: usize,
|
isolines: usize,
|
||||||
) -> Option<MeshLodSet> {
|
) -> Option<MeshLodSet> {
|
||||||
match e {
|
match e {
|
||||||
EntityType::Solid3D(s) => solid3d_tess::tessellate_solid3d(s, color, facet_res, isolines),
|
EntityType::Solid3D(s) => solid3d_tess::tessellate_solid3d(
|
||||||
EntityType::Region(r) => solid3d_tess::tessellate_region(r, color, facet_res, isolines),
|
s,
|
||||||
EntityType::Body(b) => solid3d_tess::tessellate_body(b, color, facet_res, isolines),
|
color,
|
||||||
EntityType::Surface(s) => solid3d_tess::tessellate_surface(s, color, facet_res, isolines),
|
facet_res,
|
||||||
|
chordal_deflection,
|
||||||
|
isolines,
|
||||||
|
),
|
||||||
|
EntityType::Region(r) => solid3d_tess::tessellate_region(
|
||||||
|
r,
|
||||||
|
color,
|
||||||
|
facet_res,
|
||||||
|
chordal_deflection,
|
||||||
|
isolines,
|
||||||
|
),
|
||||||
|
EntityType::Body(b) => solid3d_tess::tessellate_body(
|
||||||
|
b,
|
||||||
|
color,
|
||||||
|
facet_res,
|
||||||
|
chordal_deflection,
|
||||||
|
isolines,
|
||||||
|
),
|
||||||
|
EntityType::Surface(s) => solid3d_tess::tessellate_surface(
|
||||||
|
s,
|
||||||
|
color,
|
||||||
|
facet_res,
|
||||||
|
chordal_deflection,
|
||||||
|
isolines,
|
||||||
|
),
|
||||||
EntityType::Mesh(_) | EntityType::PolygonMesh(_) | EntityType::PolyfaceMesh(_) => {
|
EntityType::Mesh(_) | EntityType::PolygonMesh(_) | EntityType::PolyfaceMesh(_) => {
|
||||||
crate::entities::mesh::tessellate_shaded_mesh(e, color)
|
crate::entities::mesh::tessellate_shaded_mesh(e, color)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@ pub fn tessellate_sat(
|
||||||
name: String,
|
name: String,
|
||||||
color: [f32; 4],
|
color: [f32; 4],
|
||||||
facet_res: f64,
|
facet_res: f64,
|
||||||
|
chordal_deflection: Option<f64>,
|
||||||
isolines: usize,
|
isolines: usize,
|
||||||
) -> Option<MeshLodSet> {
|
) -> Option<MeshLodSet> {
|
||||||
let (bodies, loss) = lift(document);
|
let (bodies, loss) = lift(document);
|
||||||
|
|
@ -53,7 +54,10 @@ pub fn tessellate_sat(
|
||||||
} else {
|
} else {
|
||||||
1.0
|
1.0
|
||||||
};
|
};
|
||||||
let max_angle = cadkernel::tessellation::angle_for_resolution(resolution);
|
let max_angle = chordal_deflection.map_or_else(
|
||||||
|
|| cadkernel::tessellation::angle_for_resolution(resolution),
|
||||||
|
|_| cadkernel::tessellation::display_angle_for_resolution(resolution),
|
||||||
|
);
|
||||||
|
|
||||||
// Positions stay f64 until `finalize_mesh` splits them into the coarse
|
// Positions stay f64 until `finalize_mesh` splits them into the coarse
|
||||||
// and fine pair, so a solid at survey coordinates keeps its millimetres.
|
// and fine pair, so a solid at survey coordinates keeps its millimetres.
|
||||||
|
|
@ -106,11 +110,14 @@ pub fn tessellate_sat(
|
||||||
DEFAULT_FIT_TOLERANCE
|
DEFAULT_FIT_TOLERANCE
|
||||||
};
|
};
|
||||||
for (body, placement_scale) in &bodies {
|
for (body, placement_scale) in &bodies {
|
||||||
let tolerance = brep::mesh::TessellationTolerance::new(
|
let mut tolerance = brep::mesh::TessellationTolerance::new(
|
||||||
max_angle,
|
max_angle,
|
||||||
source_fit * placement_scale,
|
source_fit * placement_scale,
|
||||||
)
|
)
|
||||||
.with_isolines(isolines);
|
.with_isolines(isolines);
|
||||||
|
if let Some(deflection) = chordal_deflection {
|
||||||
|
tolerance = tolerance.with_chordal_deflection(deflection);
|
||||||
|
}
|
||||||
let tessellation = brep::mesh::tessellate(body, tolerance);
|
let tessellation = brep::mesh::tessellate(body, tolerance);
|
||||||
undrawn += tessellation.missing_faces.len();
|
undrawn += tessellation.missing_faces.len();
|
||||||
for face in &tessellation.triangle_faces {
|
for face in &tessellation.triangle_faces {
|
||||||
|
|
@ -244,15 +251,4 @@ mod tests {
|
||||||
assert_eq!(moved, [10.0, 20.0, 30.0]);
|
assert_eq!(moved, [10.0, 20.0, 30.0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sides(max_angle: f64) -> f64 {
|
|
||||||
std::f64::consts::TAU / max_angle
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn a_round_surface_gets_the_same_sides_whatever_its_size() {
|
|
||||||
let angle = cadkernel::tessellation::DEFAULT_ANGLE;
|
|
||||||
assert!(sides(angle) > 24.0, "{}", sides(angle));
|
|
||||||
assert!(sides(angle) < 96.0, "{}", sides(angle));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,9 +8,17 @@ fn tessellate_acis(
|
||||||
name: String,
|
name: String,
|
||||||
color: [f32; 4],
|
color: [f32; 4],
|
||||||
facet_res: f64,
|
facet_res: f64,
|
||||||
|
chordal_deflection: Option<f64>,
|
||||||
isolines: usize,
|
isolines: usize,
|
||||||
) -> Option<MeshLodSet> {
|
) -> Option<MeshLodSet> {
|
||||||
crate::scene::convert::acis_kernel::tessellate_sat(sat, name, color, facet_res, isolines)
|
crate::scene::convert::acis_kernel::tessellate_sat(
|
||||||
|
sat,
|
||||||
|
name,
|
||||||
|
color,
|
||||||
|
facet_res,
|
||||||
|
chordal_deflection,
|
||||||
|
isolines,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn body_transform(
|
pub(crate) fn body_transform(
|
||||||
|
|
@ -167,10 +175,18 @@ fn finish(
|
||||||
name: String,
|
name: String,
|
||||||
color: [f32; 4],
|
color: [f32; 4],
|
||||||
facet_res: f64,
|
facet_res: f64,
|
||||||
|
chordal_deflection: Option<f64>,
|
||||||
isolines: usize,
|
isolines: usize,
|
||||||
acis: &acadrust::entities::AcisData,
|
acis: &acadrust::entities::AcisData,
|
||||||
) -> Option<MeshLodSet> {
|
) -> Option<MeshLodSet> {
|
||||||
let mut set = tessellate_acis(&sat, name, color, facet_res, isolines)?;
|
let mut set = tessellate_acis(
|
||||||
|
&sat,
|
||||||
|
name,
|
||||||
|
color,
|
||||||
|
facet_res,
|
||||||
|
chordal_deflection,
|
||||||
|
isolines,
|
||||||
|
)?;
|
||||||
remap_acis_material_bindings(&mut set, acis);
|
remap_acis_material_bindings(&mut set, acis);
|
||||||
Some(set)
|
Some(set)
|
||||||
}
|
}
|
||||||
|
|
@ -179,6 +195,7 @@ pub fn tessellate_region(
|
||||||
region: &Region,
|
region: &Region,
|
||||||
color: [f32; 4],
|
color: [f32; 4],
|
||||||
facet_res: f64,
|
facet_res: f64,
|
||||||
|
chordal_deflection: Option<f64>,
|
||||||
isolines: usize,
|
isolines: usize,
|
||||||
) -> Option<MeshLodSet> {
|
) -> Option<MeshLodSet> {
|
||||||
let sat = parse_acis(
|
let sat = parse_acis(
|
||||||
|
|
@ -191,6 +208,7 @@ pub fn tessellate_region(
|
||||||
region.common.handle.value().to_string(),
|
region.common.handle.value().to_string(),
|
||||||
color,
|
color,
|
||||||
facet_res,
|
facet_res,
|
||||||
|
chordal_deflection,
|
||||||
isolines,
|
isolines,
|
||||||
®ion.acis_data,
|
®ion.acis_data,
|
||||||
)
|
)
|
||||||
|
|
@ -200,6 +218,7 @@ pub fn tessellate_body(
|
||||||
body: &Body,
|
body: &Body,
|
||||||
color: [f32; 4],
|
color: [f32; 4],
|
||||||
facet_res: f64,
|
facet_res: f64,
|
||||||
|
chordal_deflection: Option<f64>,
|
||||||
isolines: usize,
|
isolines: usize,
|
||||||
) -> Option<MeshLodSet> {
|
) -> Option<MeshLodSet> {
|
||||||
let sat = parse_acis(
|
let sat = parse_acis(
|
||||||
|
|
@ -212,6 +231,7 @@ pub fn tessellate_body(
|
||||||
body.common.handle.value().to_string(),
|
body.common.handle.value().to_string(),
|
||||||
color,
|
color,
|
||||||
facet_res,
|
facet_res,
|
||||||
|
chordal_deflection,
|
||||||
isolines,
|
isolines,
|
||||||
&body.acis_data,
|
&body.acis_data,
|
||||||
)
|
)
|
||||||
|
|
@ -221,6 +241,7 @@ pub fn tessellate_surface(
|
||||||
surface: &acadrust::entities::Surface,
|
surface: &acadrust::entities::Surface,
|
||||||
color: [f32; 4],
|
color: [f32; 4],
|
||||||
facet_res: f64,
|
facet_res: f64,
|
||||||
|
chordal_deflection: Option<f64>,
|
||||||
isolines: usize,
|
isolines: usize,
|
||||||
) -> Option<MeshLodSet> {
|
) -> Option<MeshLodSet> {
|
||||||
let sat = parse_acis(
|
let sat = parse_acis(
|
||||||
|
|
@ -233,6 +254,7 @@ pub fn tessellate_surface(
|
||||||
surface.common.handle.value().to_string(),
|
surface.common.handle.value().to_string(),
|
||||||
color,
|
color,
|
||||||
facet_res,
|
facet_res,
|
||||||
|
chordal_deflection,
|
||||||
isolines,
|
isolines,
|
||||||
&surface.acis_data,
|
&surface.acis_data,
|
||||||
)
|
)
|
||||||
|
|
@ -242,6 +264,7 @@ pub fn tessellate_solid3d(
|
||||||
solid: &Solid3D,
|
solid: &Solid3D,
|
||||||
color: [f32; 4],
|
color: [f32; 4],
|
||||||
facet_res: f64,
|
facet_res: f64,
|
||||||
|
chordal_deflection: Option<f64>,
|
||||||
isolines: usize,
|
isolines: usize,
|
||||||
) -> Option<MeshLodSet> {
|
) -> Option<MeshLodSet> {
|
||||||
let sat = parse_acis(
|
let sat = parse_acis(
|
||||||
|
|
@ -254,6 +277,7 @@ pub fn tessellate_solid3d(
|
||||||
solid.common.handle.value().to_string(),
|
solid.common.handle.value().to_string(),
|
||||||
color,
|
color,
|
||||||
facet_res,
|
facet_res,
|
||||||
|
chordal_deflection,
|
||||||
isolines,
|
isolines,
|
||||||
&solid.acis_data,
|
&solid.acis_data,
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -136,6 +136,8 @@ impl Scene {
|
||||||
};
|
};
|
||||||
let image_seed = self.image_seed_for(&entity);
|
let image_seed = self.image_seed_for(&entity);
|
||||||
let facet_res = self.document.header.facet_resolution;
|
let facet_res = self.document.header.facet_resolution;
|
||||||
|
let chordal_deflection =
|
||||||
|
crate::entities::solid3d::display_deflection(&self.document.header, facet_res);
|
||||||
let isolines = self.document.header.isolines.max(0) as usize;
|
let isolines = self.document.header.isolines.max(0) as usize;
|
||||||
let mesh_seed = if matches!(
|
let mesh_seed = if matches!(
|
||||||
&entity,
|
&entity,
|
||||||
|
|
@ -148,8 +150,14 @@ impl Scene {
|
||||||
| EntityType::PolyfaceMesh(_)
|
| EntityType::PolyfaceMesh(_)
|
||||||
) {
|
) {
|
||||||
let color = self.render_style(&entity).0;
|
let color = self.render_style(&entity).0;
|
||||||
crate::entities::solid3d::tessellate_volume(&entity, color, facet_res, isolines)
|
crate::entities::solid3d::tessellate_volume(
|
||||||
.map(|m| offset_mesh_lod_set(m))
|
&entity,
|
||||||
|
color,
|
||||||
|
facet_res,
|
||||||
|
chordal_deflection,
|
||||||
|
isolines,
|
||||||
|
)
|
||||||
|
.map(offset_mesh_lod_set)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
@ -357,6 +365,8 @@ impl Scene {
|
||||||
};
|
};
|
||||||
let image_seed = self.image_seed_for(&entity);
|
let image_seed = self.image_seed_for(&entity);
|
||||||
let facet_res = self.document.header.facet_resolution;
|
let facet_res = self.document.header.facet_resolution;
|
||||||
|
let chordal_deflection =
|
||||||
|
crate::entities::solid3d::display_deflection(&self.document.header, facet_res);
|
||||||
let isolines = self.document.header.isolines.max(0) as usize;
|
let isolines = self.document.header.isolines.max(0) as usize;
|
||||||
let mesh_seed = if matches!(
|
let mesh_seed = if matches!(
|
||||||
&entity,
|
&entity,
|
||||||
|
|
@ -369,8 +379,14 @@ impl Scene {
|
||||||
| EntityType::PolyfaceMesh(_)
|
| EntityType::PolyfaceMesh(_)
|
||||||
) {
|
) {
|
||||||
let color = self.render_style(&entity).0;
|
let color = self.render_style(&entity).0;
|
||||||
crate::entities::solid3d::tessellate_volume(&entity, color, facet_res, isolines)
|
crate::entities::solid3d::tessellate_volume(
|
||||||
.map(|m| offset_mesh_lod_set(m))
|
&entity,
|
||||||
|
color,
|
||||||
|
facet_res,
|
||||||
|
chordal_deflection,
|
||||||
|
isolines,
|
||||||
|
)
|
||||||
|
.map(offset_mesh_lod_set)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
@ -538,6 +554,8 @@ impl Scene {
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
let facet_res = self.document.header.facet_resolution;
|
let facet_res = self.document.header.facet_resolution;
|
||||||
|
let chordal_deflection =
|
||||||
|
crate::entities::solid3d::display_deflection(&self.document.header, facet_res);
|
||||||
let isolines = self.document.header.isolines.max(0) as usize;
|
let isolines = self.document.header.isolines.max(0) as usize;
|
||||||
use crate::par::prelude::*;
|
use crate::par::prelude::*;
|
||||||
let built: Vec<(Handle, MeshLodSet, bool)> = entries
|
let built: Vec<(Handle, MeshLodSet, bool)> = entries
|
||||||
|
|
@ -547,6 +565,7 @@ impl Scene {
|
||||||
entity.as_ref(),
|
entity.as_ref(),
|
||||||
color,
|
color,
|
||||||
facet_res,
|
facet_res,
|
||||||
|
chordal_deflection,
|
||||||
isolines,
|
isolines,
|
||||||
)
|
)
|
||||||
.map(|mut mesh| {
|
.map(|mut mesh| {
|
||||||
|
|
@ -1892,6 +1911,8 @@ impl Scene {
|
||||||
|
|
||||||
use crate::par::prelude::*;
|
use crate::par::prelude::*;
|
||||||
let facet_res = self.document.header.facet_resolution;
|
let facet_res = self.document.header.facet_resolution;
|
||||||
|
let chordal_deflection =
|
||||||
|
crate::entities::solid3d::display_deflection(&self.document.header, facet_res);
|
||||||
let isolines = self.document.header.isolines.max(0) as usize;
|
let isolines = self.document.header.isolines.max(0) as usize;
|
||||||
// Top-level solids: offset into the render frame, drawn flat.
|
// Top-level solids: offset into the render frame, drawn flat.
|
||||||
// Block-definition solids: keep block-local coords for per-INSERT
|
// Block-definition solids: keep block-local coords for per-INSERT
|
||||||
|
|
@ -1899,7 +1920,14 @@ impl Scene {
|
||||||
let built: Vec<(Handle, MeshLodSet, bool)> = entries
|
let built: Vec<(Handle, MeshLodSet, bool)> = entries
|
||||||
.into_par_iter()
|
.into_par_iter()
|
||||||
.filter_map(|(handle, entity, color, top_level)| {
|
.filter_map(|(handle, entity, color, top_level)| {
|
||||||
crate::entities::solid3d::tessellate_volume(&entity, color, facet_res, isolines).map(|mut mesh| {
|
crate::entities::solid3d::tessellate_volume(
|
||||||
|
&entity,
|
||||||
|
color,
|
||||||
|
facet_res,
|
||||||
|
chordal_deflection,
|
||||||
|
isolines,
|
||||||
|
)
|
||||||
|
.map(|mut mesh| {
|
||||||
let material = crate::scene::model::material_model::resolve_material_with_base(
|
let material = crate::scene::model::material_model::resolve_material_with_base(
|
||||||
&self.document,
|
&self.document,
|
||||||
&entity,
|
&entity,
|
||||||
|
|
|
||||||
|
|
@ -763,12 +763,12 @@ fn build_derived_caches_impl(
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
// meshes (parallel tessellation). FACETRES (header.facet_resolution)
|
// FACETRES biases one shared chordal tolerance for all solids.
|
||||||
// scales the per-LOD segment counts so users with finer drawings get
|
|
||||||
// smoother solids; clamped to AutoCAD's [0.01, 10.0] range inside.
|
|
||||||
// Top-level (layout-owned) solids are offset into the render frame; block
|
// Top-level (layout-owned) solids are offset into the render frame; block
|
||||||
// definition solids keep block-local coords for per-INSERT instancing. (#123)
|
// definition solids keep block-local coords for per-INSERT instancing. (#123)
|
||||||
let facet_res = doc.header.facet_resolution;
|
let facet_res = doc.header.facet_resolution;
|
||||||
|
let chordal_deflection =
|
||||||
|
crate::entities::solid3d::display_deflection(&doc.header, facet_res);
|
||||||
let isolines = doc.header.isolines.max(0) as usize;
|
let isolines = doc.header.isolines.max(0) as usize;
|
||||||
// Real layout blocks come from the Layout objects' block_record handles —
|
// Real layout blocks come from the Layout objects' block_record handles —
|
||||||
// `BlockRecord::is_layout()` is unreliable here (it flags ordinary blocks).
|
// `BlockRecord::is_layout()` is unreliable here (it flags ordinary blocks).
|
||||||
|
|
@ -796,8 +796,14 @@ fn build_derived_caches_impl(
|
||||||
material_base_dir,
|
material_base_dir,
|
||||||
);
|
);
|
||||||
let top_level = layout_blocks.contains(&e.common().owner_handle);
|
let top_level = layout_blocks.contains(&e.common().owner_handle);
|
||||||
let result = crate::entities::solid3d::tessellate_volume(e, color, facet_res, isolines)
|
let result = crate::entities::solid3d::tessellate_volume(
|
||||||
.map(|mut mesh| {
|
e,
|
||||||
|
color,
|
||||||
|
facet_res,
|
||||||
|
chordal_deflection,
|
||||||
|
isolines,
|
||||||
|
)
|
||||||
|
.map(|mut mesh| {
|
||||||
material.apply_to_with_face_overrides(
|
material.apply_to_with_face_overrides(
|
||||||
&mut mesh,
|
&mut mesh,
|
||||||
doc,
|
doc,
|
||||||
|
|
@ -810,7 +816,7 @@ fn build_derived_caches_impl(
|
||||||
);
|
);
|
||||||
let mesh = if top_level { offset_mesh_lod_set(mesh) } else { mesh };
|
let mesh = if top_level { offset_mesh_lod_set(mesh) } else { mesh };
|
||||||
(handle, mesh, top_level)
|
(handle, mesh, top_level)
|
||||||
});
|
});
|
||||||
let done = detail_done.fetch_add(1, Ordering::Relaxed) + 1;
|
let done = detail_done.fetch_add(1, Ordering::Relaxed) + 1;
|
||||||
if done & 0xff == 0 || done == detail_total {
|
if done & 0xff == 0 || done == detail_total {
|
||||||
report_detail(done);
|
report_detail(done);
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue