forked from 1b-agent/opencadstudio-upstream
fix(render): adapt mesh + hatch load colours to background
`adapt_to_bg` (pure black → white on dark bg, pure white → black on light bg) was only running through `render_style`, which the wire and per-frame hatch paths already use. The mesh population paths and the file-load hatch path went straight through `aci_to_rgba`, so: - ACIS solids / regions / bodies appeared in their raw ACI colour even when that colour was pure white on a white paper bg. - The initial hatch upload used the unadapted colour for the first frame after load (`synced_hatch_models` then re-ran adaptation per frame, so the issue cleared after one redraw — but visible). Now every mesh / hatch creation site funnels through `render_style_for` + `adapt_to_bg`: - `build_derived_caches` (load): uses the default model bg as the adaptation target. - `populate_meshes_from_document`: uses `self.render_style` so the per-frame paper / model bg selection applies. - New `Scene::recolor_meshes` rewrites every cached mesh's colour field through `render_style`; called from `BACKGROUND` (after the user changes bg) and `set_current_layout` (Model ↔ paper bg switch) so ACIS mesh colour tracks the live bg without re- tessellating ACIS geometry. Wipeout fills stay bg-coloured by design (that's their job). Raster images skip adaptation — pixel data is not entity colour.
This commit is contained in:
1 parent
e9e3bbbca1
commit
8a510c563c
2 files changed
+51
-13
No files matched your search
+7
-1
@@ -54,7 +54,12 @@ impl OpenCADStudio {
|
||||
// Wire colour adaptation (`adapt_to_bg`) reads the bg
|
||||
// at tessellation time, so the cached wires need to
|
||||
// refresh — otherwise a light→dark bg flip leaves
|
||||
// black lines invisible against the new bg.
|
||||
// black lines invisible against the new bg. Meshes
|
||||
// bake colour into per-vertex GPU buffers at upload
|
||||
// time; `recolor_meshes` rewrites the CPU side so
|
||||
// the next epoch-driven re-upload picks up the new
|
||||
// colour.
|
||||
self.tabs[i].scene.recolor_meshes();
|
||||
self.tabs[i].scene.bump_geometry();
|
||||
self.command_line
|
||||
.push_output("Background reset to default.");
|
||||
@@ -69,6 +74,7 @@ impl OpenCADStudio {
|
||||
self.tabs[i].bg_color = Some([r, g, b, 1.0]);
|
||||
self.tabs[i].scene.bg_color = [r, g, b, 1.0];
|
||||
}
|
||||
self.tabs[i].scene.recolor_meshes();
|
||||
self.tabs[i].scene.bump_geometry();
|
||||
self.command_line.push_output(&format!(
|
||||
"Background: rgb({}, {}, {})",
|
||||
|
||||
+44
-12
@@ -168,6 +168,12 @@ pub fn build_derived_caches(doc: &CadDocument) -> DerivedCaches {
|
||||
}
|
||||
}
|
||||
|
||||
// Default bg adaptation target at load: the model background (paper
|
||||
// bg is only relevant after the user enters a paper layout, and
|
||||
// `synced_hatch_models` re-runs `render_style` per-frame anyway so
|
||||
// the per-layout adaptation kicks in later regardless).
|
||||
const LOAD_BG: [f32; 4] = [0.11, 0.11, 0.11, 1.0];
|
||||
|
||||
// hatches
|
||||
let hatches: HashMap<Handle, HatchModel> = hatch_handles
|
||||
.par_iter()
|
||||
@@ -179,15 +185,11 @@ pub fn build_derived_caches(doc: &CadDocument) -> DerivedCaches {
|
||||
} else {
|
||||
[0.0; 3]
|
||||
};
|
||||
let (raw, ..) = render::render_style_for(doc, e);
|
||||
let color = render::adapt_to_bg(raw, LOAD_BG);
|
||||
let model = match e {
|
||||
EntityType::Hatch(dxf) => {
|
||||
let color = tess_util::aci_to_rgba(&dxf.common.color);
|
||||
Scene::hatch_model_from_dxf(dxf, color, offset)
|
||||
}
|
||||
EntityType::Solid(solid) => {
|
||||
let color = tess_util::aci_to_rgba(&solid.common.color);
|
||||
Some(Scene::solid_hatch_model(solid, color, offset))
|
||||
}
|
||||
EntityType::Hatch(dxf) => Scene::hatch_model_from_dxf(dxf, color, offset),
|
||||
EntityType::Solid(solid) => Some(Scene::solid_hatch_model(solid, color, offset)),
|
||||
_ => None,
|
||||
};
|
||||
model.map(|m| (handle, m))
|
||||
@@ -214,7 +216,8 @@ pub fn build_derived_caches(doc: &CadDocument) -> DerivedCaches {
|
||||
.par_iter()
|
||||
.filter_map(|&handle| {
|
||||
let e = doc.get_entity(handle)?;
|
||||
let color = tess_util::aci_to_rgba(&e.common().color);
|
||||
let (raw, ..) = render::render_style_for(doc, e);
|
||||
let color = render::adapt_to_bg(raw, LOAD_BG);
|
||||
crate::entities::solid3d::tessellate_volume(e, color, facet_res)
|
||||
.map(|m| (handle, offset_mesh_lod_set(m, world_offset)))
|
||||
})
|
||||
@@ -820,13 +823,40 @@ impl Scene {
|
||||
self.geometry_epoch = GEOMETRY_EPOCH.fetch_add(1, Ordering::Relaxed);
|
||||
}
|
||||
|
||||
/// Re-evaluate every cached mesh's color through `render_style` so a
|
||||
/// `BACKGROUND` change picks up the new `adapt_to_bg` result without
|
||||
/// re-tessellating ACIS geometry. Caller must bump `geometry_epoch`
|
||||
/// afterwards so the GPU re-uploads the now-updated colour data.
|
||||
pub fn recolor_meshes(&mut self) {
|
||||
// Cache colour lookups by handle to avoid borrowing the document
|
||||
// re-entrantly through `render_style` inside a `&mut self` loop.
|
||||
let colors: HashMap<Handle, [f32; 4]> = self
|
||||
.meshes
|
||||
.keys()
|
||||
.filter_map(|&h| {
|
||||
self.document
|
||||
.get_entity(h)
|
||||
.map(|e| (h, self.render_style(e).0))
|
||||
})
|
||||
.collect();
|
||||
for (h, set) in self.meshes.iter_mut() {
|
||||
if let Some(&c) = colors.get(h) {
|
||||
for lod in &mut set.lods {
|
||||
lod.color = c;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Switch the active layout. Bumps `geometry_epoch` so the wire cache
|
||||
/// re-tessellates — `render_style`'s `adapt_to_bg` picks the model or
|
||||
/// paper background depending on `current_layout`, so cached wires
|
||||
/// from the previous layout would be coloured against the wrong bg.
|
||||
/// Also runs `recolor_meshes` so ACIS mesh colour tracks the new bg.
|
||||
pub fn set_current_layout(&mut self, name: String) {
|
||||
if self.current_layout != name {
|
||||
self.current_layout = name;
|
||||
self.recolor_meshes();
|
||||
self.bump_geometry();
|
||||
}
|
||||
}
|
||||
@@ -3502,14 +3532,16 @@ impl Scene {
|
||||
/// `Solid3D` entity is represented in the mesh cache.
|
||||
pub fn populate_meshes_from_document(&mut self) {
|
||||
self.meshes.clear();
|
||||
// Collect all ACIS-bearing entities with their color resolved now,
|
||||
// so the parallel phase only sees owned data.
|
||||
// Resolve color through `render_style` so the same bg adaptation
|
||||
// wires use kicks in (pure black on dark bg → white, pure white
|
||||
// on light bg → black). Without this, ACIS meshes ignore
|
||||
// `adapt_to_bg` and stay invisible against matching bg colours.
|
||||
let entries: Vec<(Handle, EntityType, [f32; 4])> = self
|
||||
.document
|
||||
.entities()
|
||||
.filter_map(|e| match e {
|
||||
EntityType::Solid3D(_) | EntityType::Region(_) | EntityType::Body(_) => {
|
||||
let color = tess_util::aci_to_rgba(&e.common().color);
|
||||
let color = self.render_style(e).0;
|
||||
Some((e.common().handle, e.clone(), color))
|
||||
}
|
||||
_ => None,
|
||||
|
||||
Reference in new issue
Block a user