STEP assemblies: mesh a repeated part once and place it for its instances (#1152)
The reader converts each item once, but every instance made its own display mesh (tessellation, seam and tangent flags), the most expensive step of opening a large assembly. A later instance of an item now shows its first instance's mesh, placed by the difference of the two placements. Only rigid placements share; split lines and any operation drop the link. Measurements and export read each instance's own geometry, so eval output is unchanged. Generated assemblies: mesh phase 2,215 -> 139 ms (901 bodies) and 1,028 -> 85 ms (5,401 bodies), with the same triangle counts. Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
764fcaa5a8
commit
9b0f028f13
8 files changed
+135
No files matched your search
@@ -248,6 +248,9 @@ struct Reader<'a> {
|
||||
/// Items the file converts exactly once (see `index`): keeping their solids would hold a
|
||||
/// second copy of the whole import for nothing.
|
||||
once: HashSet<u64>,
|
||||
/// An item placed more than once: its first instance's display, shared by the later ones
|
||||
/// (with the placement that first instance had), so the part is meshed once.
|
||||
shown: HashMap<u64, (Arc<crate::body::SharedDisplay>, mt::Matrix4)>,
|
||||
used_items: HashSet<u64>,
|
||||
/// Items already instanced for the product being read.
|
||||
node_items: HashSet<u64>,
|
||||
@@ -280,6 +283,7 @@ impl<'a> Reader<'a> {
|
||||
opacity: HashMap::new(),
|
||||
solids: HashMap::new(),
|
||||
once: HashSet::new(),
|
||||
shown: HashMap::new(),
|
||||
used_items: HashSet::new(),
|
||||
node_items: HashSet::new(),
|
||||
visits: 0,
|
||||
@@ -680,6 +684,16 @@ impl<'a> Reader<'a> {
|
||||
.map(|face| Some(crate::FaceSource::Imported { item, face: *face, payload_sha256: None, producer: None }))
|
||||
.collect();
|
||||
let body = body.with_face_sources(Some(std::sync::Arc::new(identities)));
|
||||
// A later instance of an item shows its first instance's mesh, placed.
|
||||
let body = match self.shown.get(&item) {
|
||||
Some((shared, first)) => body.with_display_of(shared.clone(), to_array(&mat_mul(m, &rigid_inverse(first)))),
|
||||
None => {
|
||||
if !self.once.contains(&item) {
|
||||
self.shown.insert(item, (Arc::new(crate::body::SharedDisplay::new(body.clone())), *m));
|
||||
}
|
||||
body
|
||||
}
|
||||
};
|
||||
self.bodies.push(ImportedBody {
|
||||
name,
|
||||
body,
|
||||
|
||||
Reference in new issue
Block a user