fix(render): show Inventor drawing views, each in its own viewport (#1285)

Inventor DWG exports place every sheet block with AcIdBlockReference,
which the codec skipped, so these drawings opened blank. opencadcodec
7c20aa7 decodes it as an INSERT and keeps the viewport each model-space
view reference is bound to.

Those view blocks overlap in model space, so a content viewport now also
hides model-space references bound to a different viewport. The handles
join the viewport's frozen-layer set (entity and layer handles never
collide), which the wire and render-graph visibility checks and every
per-viewport cache key already use.

Pins opencadcodec 7c20aa7, opencadkernel d71a828, opencadgraph 1543a5a.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Hakan SevenandClaude Opus 5.5 committed 2026-09-25 19:48:36 +03:00
1 parent 5fcf741c51
commit fdc01e13c8
9 files changed
+46 -24

No files matched your search

Generated
+4 -4
View File
@@ -4201,7 +4201,7 @@ dependencies = [
[[package]]
name = "opencadcodec"
version = "0.5.5"
source = "git+https://github.com/HakanSeven12/opencadcodec.git?rev=d6d534f#d6d534fcfec5823e47ef5630668d8e16d62c1641"
source = "git+https://github.com/HakanSeven12/opencadcodec.git?rev=7c20aa7#7c20aa7fad405845c5bd5cdcc2a232cdc2a4687d"
dependencies = [
"ahash 0.8.12",
"anyhow",
@@ -4224,7 +4224,7 @@ dependencies = [
[[package]]
name = "opencadgraph"
version = "0.1.0"
source = "git+https://github.com/HakanSeven12/opencadgraph.git?rev=5c9b004#5c9b004a2fd10b9eb62b8d54ce443120ee417a95"
source = "git+https://github.com/HakanSeven12/opencadgraph.git?rev=1543a5a#1543a5aeb0b871a2f23a3b55117c7f5af1e1d229"
dependencies = [
"opencadkernel",
"serde_json",
@@ -4233,7 +4233,7 @@ dependencies = [
[[package]]
name = "opencadkernel"
version = "0.1.0"
source = "git+https://github.com/HakanSeven12/opencadkernel.git?rev=5d9e921#5d9e92104830444ca48ac7c5a8cdcfa24c21786b"
source = "git+https://github.com/HakanSeven12/opencadkernel.git?rev=d71a828#d71a8284f0388025e07f219c7b8f6bb86e7188ec"
dependencies = [
"cavalier_contours",
"opencadcodec",
@@ -4244,7 +4244,7 @@ dependencies = [
[[package]]
name = "opencadkernel-constraints"
version = "0.1.0"
source = "git+https://github.com/HakanSeven12/opencadkernel.git?rev=5d9e921#5d9e92104830444ca48ac7c5a8cdcfa24c21786b"
source = "git+https://github.com/HakanSeven12/opencadkernel.git?rev=d71a828#d71a8284f0388025e07f219c7b8f6bb86e7188ec"
dependencies = [
"nalgebra",
]
+4 -4
View File
@@ -33,10 +33,10 @@ rfd = "0.17"
clap = { version = "4", features = ["derive", "string"] }
env_logger = "0.11"
log = "0.4"
codec = { package = "opencadcodec", git = "https://github.com/HakanSeven12/opencadcodec.git", rev = "d6d534f", features = ["serde"] }
kernel = { package = "opencadkernel", git = "https://github.com/HakanSeven12/opencadkernel.git", rev = "5d9e921", features = ["acis", "offset"] }
kernel-constraints = { package = "opencadkernel-constraints", git = "https://github.com/HakanSeven12/opencadkernel.git", rev = "5d9e921" }
graph = { package = "opencadgraph", git = "https://github.com/HakanSeven12/opencadgraph.git", rev = "5c9b004" }
codec = { package = "opencadcodec", git = "https://github.com/HakanSeven12/opencadcodec.git", rev = "7c20aa7", features = ["serde"] }
kernel = { package = "opencadkernel", git = "https://github.com/HakanSeven12/opencadkernel.git", rev = "d71a828", features = ["acis", "offset"] }
kernel-constraints = { package = "opencadkernel-constraints", git = "https://github.com/HakanSeven12/opencadkernel.git", rev = "d71a828" }
graph = { package = "opencadgraph", git = "https://github.com/HakanSeven12/opencadgraph.git", rev = "1543a5a" }
dwg-thumbnailer = { path = "crates/dwg-thumbnailer" }
flate2 = "1"
image = { version = "0.25", default-features = false, features = ["png", "jpeg", "bmp", "tiff"] }
+2 -2
View File
@@ -15,7 +15,7 @@ serde_json = { version = "1", optional = true }
# Pulled in only by the `host` feature, which adds the `opencadcodec`-typed
# `HostApi` runtime surface. The default crate stays dependency-free so engine
# crates and external tooling can depend on the manifest/ribbon contract cheaply.
codec = { package = "opencadcodec", git = "https://github.com/HakanSeven12/opencadcodec.git", rev = "d6d534f", optional = true, features = ["serde"] }
codec = { package = "opencadcodec", git = "https://github.com/HakanSeven12/opencadcodec.git", rev = "7c20aa7", optional = true, features = ["serde"] }
# Runtime IPC and serialization (host feature only).
interprocess = { version = "2", optional = true }
@@ -39,7 +39,7 @@ serde_json = "1"
serde = { version = "1", features = ["derive"] }
cargo-lock = "11"
# opencadcodec is scanned at build time to generate the embedded type registry.
codec = { package = "opencadcodec", git = "https://github.com/HakanSeven12/opencadcodec.git", rev = "d6d534f", features = ["serde"] }
codec = { package = "opencadcodec", git = "https://github.com/HakanSeven12/opencadcodec.git", rev = "7c20aa7", features = ["serde"] }
[dev-dependencies]
serde_json = "1"
+1 -1
View File
@@ -8,7 +8,7 @@ publish = false
crate-type = ["cdylib"]
[dependencies]
codec = { package = "opencadcodec", git = "https://github.com/HakanSeven12/opencadcodec.git", rev = "d6d534f", features = ["serde"] }
codec = { package = "opencadcodec", git = "https://github.com/HakanSeven12/opencadcodec.git", rev = "7c20aa7", features = ["serde"] }
bincode = "1.3"
serde = { version = "1", features = ["derive"] }
console_error_panic_hook = "0.1"
+1 -1
View File
@@ -1265,7 +1265,7 @@ dependencies = [
[[package]]
name = "opencadcodec"
version = "0.5.5"
source = "git+https://github.com/HakanSeven12/opencadcodec.git?rev=d6d534f#d6d534fcfec5823e47ef5630668d8e16d62c1641"
source = "git+https://github.com/HakanSeven12/opencadcodec.git?rev=7c20aa7#7c20aa7fad405845c5bd5cdcc2a232cdc2a4687d"
dependencies = [
"ahash 0.8.12",
"anyhow",
+30
View File
@@ -8108,6 +8108,33 @@ impl Scene {
.unwrap_or(false)
}
/// Handles hidden inside content viewport `vp`: its VP-frozen layers plus
/// model-space references bound to another viewport (Inventor drawing
/// views overlap in model space; each is drawn only in its own viewport).
/// Entity and layer handles never collide, so both ride the same set and
/// its cache signature.
pub(super) fn viewport_hidden_handles(&self, vp: Handle) -> HashSet<Handle> {
let mut hidden: HashSet<Handle> = match self.document.get_entity(vp) {
Some(EntityType::Viewport(v)) => v.frozen_layers.iter().copied().collect(),
_ => HashSet::default(),
};
// ponytail: full entity scan per call, gated to drawings declaring the
// class; memoize per geometry epoch if large Inventor sheets show up.
if self.document.classes.get_by_name("ACIDBLOCKREFERENCE").is_some() {
let model = self.model_space_block_handle();
hidden.extend(self.document.entities().filter_map(|e| match e {
EntityType::Insert(i)
if i.common.owner_handle == model
&& i.view_rep_handle.is_some_and(|bound| bound != vp) =>
{
Some(i.common.handle)
}
_ => None,
}));
}
hidden
}
/// True when `layer`'s handle is in a content viewport's per-viewport
/// frozen-layer set (VP freeze). Mirrors the wire path's test in
/// [`Scene::resident_entity_visible`] so fills / images / meshes hide on the
@@ -10199,6 +10226,9 @@ impl Scene {
}
if let Some(frozen) = frozen_layers {
if !frozen.is_empty() {
if frozen.contains(&c.handle) {
return false;
}
if let Some(lh) = layer.map(|l| l.handle) {
if frozen.contains(&lh) {
return false;
+1 -7
View File
@@ -828,13 +828,7 @@ impl Scene {
// wheel tick whenever the drawing contained one annotative object.
// Explicit viewport annotation-scale changes still rebuild the resident
// set; PSLTSCALE is a viewport GPU uniform.
let frozen = match self.document.get_entity(vp_handle) {
Some(EntityType::Viewport(vp)) => {
let f: HSet<Handle> = vp.frozen_layers.iter().cloned().collect();
f
}
_ => HSet::default(),
};
let frozen: HSet<Handle> = self.viewport_hidden_handles(vp_handle);
let scale_handle = self.viewport_scale_handle(vp_handle);
self.resident_wires_for(
+2 -1
View File
@@ -612,7 +612,8 @@ impl<'a> RenderSceneGraph<'a> {
return false;
}
if self.frozen_layers.is_some_and(|frozen| {
layer.is_some_and(|layer| frozen.contains(&layer.handle))
frozen.contains(&common.handle)
|| layer.is_some_and(|layer| frozen.contains(&layer.handle))
}) {
return false;
}
+1 -4
View File
@@ -4537,10 +4537,7 @@ impl Scene {
&& inst.tile_idx.is_none()
&& inst.handle != codec::Handle::NULL
{
match self.document.get_entity(inst.handle) {
Some(EntityType::Viewport(vp)) => vp.frozen_layers.iter().cloned().collect(),
_ => rustc_hash::FxHashSet::default(),
}
self.viewport_hidden_handles(inst.handle)
} else {
rustc_hash::FxHashSet::default()
};