* Claim #15862: interference and booleans of a loft against a mirrored box Co-Authored-By: Claude Code <noreply@anthropic.com> * solidcore-ops: test a box mirrored into an opening of a spline loft (#15862) A box extruded from a rectangle, read back from its record and mirrored across x = 0 sits 0.2 mm clear of a loft through two cubic splines. On main the loft minus the box is nothing, the loft and the box intersect in the whole loft, and their union is refused, because the mirror turns every straight edge into the degree 1 B-spline of the whole line. Co-Authored-By: Claude Code <noreply@anthropic.com> * solidcore: a mirrored line stays a line (#15862) Mirroring a body (SmBrep::Mirror, and SmBrep::Transform with a left-handed matrix) turned each straight edge into the plain degree 1 B-spline of the line's NURB. A line read from a record is infinite, so that B-spline ran over knots -1234567..1234567 with control points some 1.8e7 mm out. A boolean of such a body with a spline face it does not touch took the wrong side: a box mirrored into an opening of a spline loft, 0.2 mm clear, cut the whole loft away, intersected it in the whole loft, and its union was refused (1001). Line::create_mirror_curve mirrors the line's point and unit vector and keeps its domain, scale and sides; an existing NURB is mirrored with it, so each parameter maps to the mirror of the same point and edge intervals stay valid. Recorded as WR-784. Golden topology.brep_mirror blessed: 147 of 341 cases move, none in status, topology (graph) or the geometry digest. - 133 mirror and mirror-matrix cases: each straight edge's curve is now a line; every record block drops by a whole multiple of 23 (the B-spline type code minus the line's), e.g. Solids_box_smb_* by 12 lines, the cylinder's seam by 1 (gen0017/0030/0033/0036/0077, mat0027/0045 within 1e-9 besides: the old samples came from control points near 1e7). - 14 matrix cases with a reflection and an unequal scale (box, cylinder and cone mirror_rotated_scaled; mat0003/0004/0009/0017/0029/0036/0049/0050/0056/0057/ 0090): the scale turns the edges into NURBS as before, now over the edge's own interval instead of the whole line, so the record is shorter and the uses keep no stored UV trims, exactly as main gives for an unequal scale without a reflection (Solids_box_smb_non_uniform_2_1_1). Measured on box, cylinder, cone, extrusion, l_shape_with_boss and OffsetBoxCylOnCorner with that matrix: valid at CheckLevel::All and the same volume to the last bit on main and with this change. Co-Authored-By: Claude Code <noreply@anthropic.com> --------- Co-authored-by: Claude Code <noreply@anthropic.com>
solidcore is developed inside SolidCraft, at
solidcore/. The tangency-labs/solidcore repository is an automatic, read-only mirror of that folder. Open issues and pull requests in tangency-labs/solidcraft: kernel-only work against thekernelbranch.
solidcore
📊 Live progress: tangency-labs.github.io/solidcore: every unit's port status, the upstream-issues log, and the surface/surface intersection corpus scores, regenerated on every merge.
solidcore is a boundary-representation (B-rep) solid modeling kernel in safe Rust. It is based
on NVIDIA's SMLib (from USD BRep, Apache-2.0)
and goes its own way from there: it started as a port, and its new constructions, such as the
generic rolling-ball blend (docs/generic-blend.md), are designed and built
here as clean, procedural constructions that replace the code they supersede. Contributing:
CONTRIBUTING.md. Design discussion: the
#solidcore-dev channel on Discord.
Solids are exact: shells, faces, loops, edges and vertices bound to analytic and NURBS curves and surfaces. solidcore's first consumer is SolidCraft.
Scope
In scope: the SMLib kernel and the SM_API operation layer of upstream — NURBS
math, curve and surface geometry, B-rep topology, intersections, booleans, fillets and
chamfers, offset/shell, sweeps and skins, primitives, healing/stitching, mass
properties and queries.
Out of scope: upstream's OCCT translators, USD/Hydra integration and Python bindings. See ATTRIBUTION.md.
Goals: no unsafe in the kernel, no panics on bad input, deterministic results, no
global state (one Kernel per thread), builds for wasm32-unknown-unknown, and exact or
certified geometry. The gate is its own tests, SolidCraft's operation cases and the goldens:
every unit's cases checked against their committed expected outputs (AGENTS.md §1).
Status
Every SMLib kernel module has a Rust counterpart, and primitive construction is exercised end to end. Integration remains in progress: deferred paths still limit coverage. The API is experimental (0.0.x).
Use the live unit results
for each unit's status and blockers, and the
primitive checks for whole-solid
results. Per-unit plans and notes live in plan/units/; the generated
checklist is PROGRESS.md on the site, with handoff notes in
plan/STATUS.md. The progress site is built by
site/build.py (python3 site/build.py -> bin/site/).
Reference docs
How the kernel's constructions work, the theory behind them and the invariants they keep, with schematics. Start with the first; each ends with "If you're stuck".
| Doc | What it covers |
|---|---|
| Definitions and certificates | A surface is its definition and its B-spline a certified approximation; the certificate; exactness classes; the exact extension; the invariants every construction keeps |
| The generic blend | Fillets, chamfers, corners and setbacks |
| The procedural sweep | Swept surfaces, their rotation-minimizing frames, threads |
| Surface-surface intersection | The SSI pipeline, its exact classes, and what the boolean takes from it |
| Layers | Which layer each job lives in |
Layout
| Path | Contents |
|---|---|
crates/solidcore |
The kernel library |
crates/goldens |
Every unit's cases, checked against their goldens |
crates/diagnostics |
solidcore-diag: a shaded picture and a tolerance report of one .smb body |
plan/ |
Unit list, port order, status, findings |
site/ |
Generator for the GitHub Pages progress site |
upstream/ |
Local clone of usd-brep v1.0.1 at 3fd5b95, read only (gitignored) |
bin/ |
All build output (gitignored) |
Building
Requires the stable toolchain (pinned by rust-toolchain.toml, which also installs
rustfmt, clippy and the wasm32-unknown-unknown target). Cargo output goes to
bin/ (see .cargo/config.toml).
cargo build -p solidcore
cargo test -p solidcore
cargo fmt --all --check
cargo clippy --workspace --all-targets -- -D warnings
cargo check -p solidcore --target wasm32-unknown-unknown # wasm check
Optional: export RUSTC_WRAPPER=sccache to share compilation caches.
WebAssembly stack size
On wasm32-unknown-unknown the Rust stack lives in linear memory without a guard
page, so an overflow corrupts memory instead of aborting. solidcore bounds
input-driven recursion, but kernel algorithms (subdivision, intersection, filleting)
still recurse legitimately. Link wasm consumers with a larger stack than the ~1 MB
default, e.g. in the consumer's .cargo/config.toml:
[target.wasm32-unknown-unknown]
rustflags = ["-C", "link-arg=-zstack-size=8388608"] # 8 MiB, as a native main thread
Goldens
Every unit's cases (fixtures/<unit>/, upstream's TestFiles, seeded generators) run on
solidcore and are checked against the unit's golden, crates/goldens/expected/<unit>.jsonl:
the outputs recorded when it was blessed. CI fails on any changed, added, missing or broken
case. Many cases read upstream's test files, so clone upstream/ first:
git clone https://github.com/NVIDIA-Omniverse/usd-brep upstream
git -C upstream checkout 3fd5b95 # v1.0.1; the pin is in scripts/upstream-pin.env
cargo run --profile goldens -p goldens -- --all --goldens --jobs 0 # every unit (CI)
cargo run --profile goldens -p goldens -- --unit <unit id> --goldens # one unit
cargo run --profile goldens -p goldens -- --unit <unit id> --bless # record a change on purpose
A golden proves a result unchanged, not correct. A change that moves one is blessed and justified in its pull request: the cases that changed, their numbers, and pictures for geometry (crates/goldens/README.md). upstream's C++ is a reading reference only: nothing here builds, links or runs it.
Contributing
Contributions go through pull requests, and AI agents are welcome. Useful work includes connecting ported units, resolving deferred cases, adding operation regressions and fixing bugs.
- Check the live unit results, open issues and open PRs. Choose an unclaimed unit or a specific completion task: a missing function, back-edge, exact import, coverage gap or bug. A passing golden does not prove every branch is exercised.
- Search PR titles and bodies for the unit, symbols and paths. Claim the specific
work in a draft PR; initial ports use
port: <unit id>. A claim covers its stated scope, leaving independent tasks in the same unit available. Coordinate overlapping functions or shared interfaces in the existing PR before editing them. - Describe the intended behavior, affected paths, related PRs and validation, and list independent follow-ups others can take. Check the affected units against their goldens and justify every golden you bless. CI is the merge gate. See AGENTS.md §4 for the claim template, handoffs and inactivity rules.
To keep parallel PRs from conflicting: edit only your unit's plan/units/<unit id>.toml,
and put each finding or upstream issue
in its own new file under plan/findings/ or plan/upstream-issues/ (never append to a
shared file). A branch started before the per-unit
split migrates with git fetch origin && git merge origin/main; scripts/units-migrate-branch.sh && git commit --no-edit.
The full rules, style and step-by-step workflow are in AGENTS.md (point your agent at it).
Releasing
solidcore is published to crates.io from CI: bump version in
crates/solidcore/Cargo.toml in a PR, merge it, then push a tag
solidcore-v<version> (.github/workflows/release.yml, needs the
CARGO_REGISTRY_TOKEN repository secret). Only solidcore is published;
goldens is test-only. It stays at 0.0.x until it is usable end
to end.
Sponsors
solidcore's continuous integration runs on Blacksmith, which sponsors its CI minutes.
Licence
Apache-2.0. See LICENSE, NOTICE and ATTRIBUTION.md. solidcore is an independent project, not affiliated with or endorsed by NVIDIA.
