Skip to content

fix(geometry): recover RTC offset when the IfcSite placement is forward-referenced#1338

Merged
louistrue merged 1 commit into
mainfrom
fix/rtc-late-placement-collapse
Jun 24, 2026
Merged

fix(geometry): recover RTC offset when the IfcSite placement is forward-referenced#1338
louistrue merged 1 commit into
mainfrom
fix/rtc-late-placement-collapse

Conversation

@louistrue

Copy link
Copy Markdown
Collaborator

Problem

Georeferenced models on national-grid coordinates (geometry baked at multi-megametre absolute positions) can render as f32-quantized noise — surfaces shatter into speckle and the model "jitters" on orbit/zoom. It is not a recent regression; it's a long-standing, data-dependent precision bug that only surfaces on the streaming-parallel load path (larger files). The same model loaded under the size threshold (serial path, full index) renders fine, which is why some discipline models in a set looked correct while others did not, and why federating a "good" model rescued a "bad" one.

Root cause

The streaming prepass detects the RTC (relative-to-center) offset from the first ~50 geometry elements' placement chains, resolved against a partial, file-head entity index. When a model emits the IfcSite entity early but its IfcAxis2Placement3D location (the point carrying the world offset) as a high, late express id, the element → … → site chain can't resolve from the partial index, so detect_rtc_offset_from_jobs returns None.

The full-index re-detect that would recover the offset was gated on site_position.is_none() alone — so it was skipped whenever the site entity had already been scanned, even though the site placement hadn't. Detection then fell through to scan_placement_bounds().rtc_offset(), whose AABB centroid (min+max)/2 averages the many near-origin relative placements against the lone far anchor and lands at roughly half the true offset. Half is still > the 10 km shift threshold, so needsShift is true and a shift is applied — but it leaves vertices at ~half the world magnitude, still far outside f32's safe range → collapse.

Fix

Re-detect against the full index whenever no usable placement samples resolved at all (!detection_succeeded), independent of site scan order:

if !is_large(rtc_offset) && (site_position.is_none() || !detection_succeeded) {

The full index resolves the forward-referenced …→site chain, so the placement-resolved median yields the true full-magnitude offset and the broken centroid fallback is no longer reached for these models. No public API change.

Verification

Ran the rebuilt wasm streaming prepass headlessly on the affected models:

before after
detected RTC ~½ the model's world magnitude → still collapses full magnitude → vertices land near origin, f32-precise
  • New self-contained regression test (early IfcSite entity + forward-referenced site placement) — pins partial-index miss / full-index recovery; no external fixture.
  • Existing late-site regression test (ISSUE_129) still passes.

🤖 Generated with Claude Code

…rd-referenced

On the streaming-parallel prepass the RTC (relative-to-center) offset is
detected from the first ~50 geometry elements' placement chains against a
partial, file-head entity index. When a georeferenced model emits the IfcSite
*entity* early but its IfcAxis2Placement3D *location* — the point carrying the
national-grid offset — as a high (late) express id, the element -> ... -> site
chain can't resolve from the partial index and detection returns None.

The full-index re-detect that recovers it was gated on `site_position.is_none()`
alone, so it was skipped whenever the site entity had already been scanned. The
path then fell to `scan_placement_bounds().rtc_offset()`, whose AABB centroid
averages the near-origin relative placements against the lone far anchor and
lands at ~half the true offset — large enough to pass the >10km shift gate but
not enough to bring vertices into f32 range, so geometry shatters into
sub-metre quantization noise.

Re-detect against the full index whenever no placement samples resolved at all
(`!detection_succeeded`), independent of site scan order. Verified end-to-end:
affected georeferenced models now report the full-magnitude RTC instead of half.

Adds a self-contained regression test (early IfcSite entity + forward-referenced
site placement) that pins the partial-index miss / full-index recovery.
@vercel

vercel Bot commented Jun 24, 2026

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
ifc-lite Ready Ready Preview, Comment Jun 24, 2026 6:30am
2 Skipped Deployments
Project Deployment Actions Updated (UTC)
ifc-lite-dev Ignored Ignored Jun 24, 2026 6:30am
ifc-lite-viewer-embed Ignored Ignored Jun 24, 2026 6:30am

@coderabbitai

coderabbitai Bot commented Jun 24, 2026

Copy link
Copy Markdown

Warning

Review limit reached

@louistrue, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 41 minutes and 5 seconds. Learn how PR review limits work.

Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable the review add-on in the billing tab to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file).

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based credits.

🚦 How do rate limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: e6d586dc-459a-424e-85ac-03b197064937

📥 Commits

Reviewing files that changed from the base of the PR and between e1d283c and e0220b3.

📒 Files selected for processing (2)
  • rust/geometry/tests/streaming_rtc_early_site_late_placement.rs
  • rust/wasm-bindings/src/api/gpu_meshes.rs
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/rtc-late-placement-collapse

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@louistrue louistrue merged commit 9cb2a56 into main Jun 24, 2026
24 checks passed
@louistrue louistrue deleted the fix/rtc-late-placement-collapse branch June 24, 2026 06:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant