CSG Mesh Path
PHITS cell expressions are the geometry truth. The viewport mesh is generated inspection data and never a second geometry model.
Ownership
geometry.odin owns PHITS surfaces, cells, materials, expression terms, and
geometry revision. It does not own render meshes.
csg_mesh.odin owns signed-distance evaluation, expression compilation, bounds,
and Marching Cubes extraction. csg_mesh_cache.odin owns CPU/disk cache state;
preview_mesh_job.odin owns asynchronous preview work; and
cell_diagnostic_cache.odin owns cached cell diagnostics.
App_State owns the active CSG settings, cache, preview job, and diagnostic
cache. editor_geometry.odin owns the shared cached mesh, diagnostic, bounds,
and picking queries. renderer.odin, renderer_cells.odin, and
renderer_preview.odin own GPU scene data and upload preparation. Cache
identity includes cell identity, geometry revision, and CSG settings.
Expression semantics
cell_expression_signed_distance evaluates the same expression represented by
the PHITS cell:
- inside-surface terms use the surface signed distance;
- outside-surface terms negate it;
- outside-cell terms recursively evaluate the cutter cell and negate it; and
- the cell distance is the maximum of the active constraints.
Raw PHITS cells remain preserved/exportable. They are meshed only when reduced to RAMAL-editable terms. Construction surfaces are not final-cell geometry.
Extraction path
csg_mesh_build_cell first emits exact planar faces for an untransformed RPP
cell and for a closed RPP shell whose coextensive cutter slabs merge into one
rectangular cavity. These meshes are independent of viewport quality. Other
cells compile their expressions and #cell references once, sample a bounded
signed-distance grid, and use the literal 256-case Marching Cubes table. That
path uses a dense grid-edge cache, finite-difference normals from sampled
values, and geometry/grid-normal checks for triangle rejection and orientation.
PHITS TRCL transforms are reduced to the canonical affine mapping; surfaces
are not baked into a separate model.
The active settings are resolution, complex_resolution,
padding_fraction, and min_padding. Changing them clears the CPU cache and
invalidates renderer CSG models. For multi-term RPP expressions, a thin axis is
sampled more densely when a participating RPP feature would otherwise fall
between slices, up to the selected resolution cap. This protects small features
in expressions that cannot use the exact planar path while leaving the PHITS
expression unchanged.
Current guarantees and limits
The current tests cover thin curved cuts, tangent curved cutters, nested
#cell cutters, near-plane clipping, empty-volume rejection, and the converted
source-head envelope's exact outer and inner RPP faces at every 36/48/72/96
viewport-quality preset. The exact path also rejects invalid/non-finite RPP
bounds, non-coextensive cutter cross-sections, and real gaps between cutter
slabs rather than merging them because the surrounding scene is large. The code
also contains an opt-in cold-extraction benchmark:
RAMAL_CSG_BENCH=1 odin test . -define:ODIN_TEST_THREADS=1
RAMAL_CSG_BENCH=1 RAMAL_CSG_BENCH_EXTERIOR=1 odin test . -define:ODIN_TEST_THREADS=1
Open robustness work supported by the current extraction/tests is limited to extraction quality: more sliver and boundary stress cases, explicit saddle-case ambiguity handling, broader topology checks, adaptive sampling around sign changes, and keeping PHITS diagnostics/export rules aligned. These are robustness issues in the generated inspection mesh, not reasons to add another geometry truth source.
Resolved converted-head Cell 13 viewport failure
On 2026-08-27, converted-head envelope Cell 13 appeared smooth in Fast and
Balanced but showed tilted diamond-shaped holes and serrated faces in High. The
PHITS expression was valid; the defect was limited to the inspection mesh.
Marching Cubes sampled the thin, coextensive cutter slabs at quality-dependent
positions, so the visible approximation changed with resolution. After the
exact planar RPP-shell path was added, the on-disk mesh cache could still serve
the earlier High mesh because its representation identity had not changed.
The repair has two required parts:
- eligible RPP shells emit exact outer and inner planar faces, independent of viewport quality; and
- the disk-cache format identity is advanced whenever a mesh-representation change would make older cached geometry invalid.
Regression coverage requires the same exact converted-head shell at every
36/48/72/96 preset and separately rejects false cutter merges. If a future
quality preset shows different topology, first determine whether the Cell used
the exact or sampled path and whether a stale disk entry was loaded. Never
modify the PHITS Cell expression to conceal a viewport-only defect.
Hard-cut rules
- Do not restore primitive preview meshes as the final-cell view.
- Do not pick final cells from construction-surface bounds.
- Do not bypass expression exclusions or keep an old compatibility loader.
- Keep construction surfaces as authoring aids and final regions on the CSG expression path.