Skip to content

A straight prim gets one quad per profile edge, and rows its parameters collapse emit no triangles - #557

Merged
RyeMutt merged 5 commits into
rye/prim-normalsfrom
rye/prim-vertex-reduction
Oct 25, 2026
Merged

RyeMutt merged 5 commits into
rye/prim-normalsfrom
rye/prim-vertex-reduction

Conversation

@RyeMutt

@RyeMutt RyeMutt commented Oct 23, 2026 •

Copy link
Copy Markdown
Member

LLVolume::generate splits every profile edge into detail * 0.66 pieces, and gives a straight path at least split + 2 rings. That gave vertex lighting more vertices to interpolate across. Under per-pixel lighting, a straight path with no twist and no taper makes only flat or straight-ruled faces, so those extra vertices sit on the surface and change nothing. This PR stops making them, and stops emitting triangles that have no area.

This is part 2 of a stack of 7. Merge them in order: each PR is based on the one before it and shows only its own commits.

  1. Prim normals point straight out of their surfaces, caps face out, and a flexible prim rebuilds in place #556 prim normals
  2. A straight prim gets one quad per profile edge, and rows its parameters collapse emit no triangles #557 vertex reduction ← this PR
  3. A prim every LOD builds alike is generated once, and its LOD changes rebuild nothing #558 LOD-invariant prims
  4. Mesh and GLTF tangents come from meshoptimizer's MikkTSpace mode, welded and ordered in one pass #559 mesh tangents
  5. Prims, sculpts, GLTF primitives and avatar meshes are ordered for the vertex cache #560 vertex cache order
  6. Planar texgen maps a face that faces one way as one plane, and its normal map takes the planar frame #561 planar texgen
  7. The uploader's LODs and normals come from meshoptimizer's attribute-aware simplifier #562 uploader LODs and normals

Changes

  • Straight prims: on a straight path with no twist and no taper, split is 0 and the path has 2 rings.

    prim LOD vertices / triangles before after
    default box 3 96 / 108 24 / 12 (at every LOD)
    cylinder 3 152 / 192 102 / 96

    The uncut cube cap is a single quad. Twisted, tapered, circular and flexible paths keep their split. So does a square hole pulled in to its wall, which isn't straight between its corners.

  • Flat inner sides: a square or triangle hole's inner side now copies only the hole's corners, which are its creases. Before, it also copied every split point, which faceted the inner side of twisted or circular hollow prims strip by strip, and each copy added a quad of zero width. Those quads now emit no triangles. That is decided from the column layout, never from positions, so a flexible prim's topology still depends only on its parameters.

    • A hollow box is 52 / 32 at every LOD.
    • A twisted hollow box at LOD 3 has 500 vertices instead of 612.
  • Collapsed rows and columns: a shared volume now emits no triangles where its parameters collapse a row or a column: a taper to a point, or a sphere's poles. The vertices stay, because each column carries its own UV and normal. A sphere at LOD 3 has 528 triangles instead of 576. The index loop is a template, so the common case runs the loop it always did.

  • Hollow sphere: its inner side now takes its strip's normal at both ends. The pole override used to shade half of that side with a 45-degree gradient.

ARC and streaming cost read parameter-based counts. Those counts are unchanged, so land impact doesn't move.

Testing

  • llmath_tests, shuffled: 409 cases. 408 pass and 1 is skipped.
  • Kept and removed vertices: positions and UVs at kept vertices match the old build within 7e-7. Every removed vertex lies on the new surface, with the UV it had.
  • Viewer: not yet checked. To check: a twisted box, a pyramid, a hollow box with a square hole, and a torus at 1.5 revolutions.

🤖 Generated with Claude Code

@coderabbitai

coderabbitai Bot commented Oct 23, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: Repository UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 81933207-d487-4a47-865f-c363c8c77cb9
📥 Commits

Reviewing files that changed from the base of the PR and between 8dc82e9 and 327b53f.

📒 Files selected for processing: 3
  • indra/llmath/llvolume.cpp
  • indra/llmath/llvolume.h
  • indra/llmath/tests/llvolume_test.cpp

Included review availability: This review used your included allowance. Your plan provides up to 1 included review per hour; 0 remain after this review.

📝 Summary

Summary by CodeRabbit

  • Bug Fixes
    • Improved rendering of hollow and flat-sided 3D shapes, including corners that meet or extend beyond the outer wall.
    • Fixed mesh shading and lighting on shapes with collapsed or overlapping sections.
    • Corrected triangle generation for shapes with reduced or degenerate dimensions, helping prevent visual artifacts across supported shape types and detail levels.

Volume profile generation now tracks flat-hole corners and adjusts profile splitting when holes touch the wall. Side-face generation retains grid vertices while omitting zero-area triangles at collapsed boundaries, and flat inner faces copy corner columns. Tests cover counts, corner boundaries, and collapsed geometry.

Changes: Volume mesh generation

Layer / File(s) Summary
Profile splits and hole corners
indra/llmath/llvolume.h, indra/llmath/llvolume.cpp, indra/llmath/tests/llvolume_test.cpp
Profile generation reports whether it emitted a begin-cut point. Flat-hole faces record corner intervals. Straight, untapered, untwisted line paths suppress profile splits, and profiles are regenerated with the saved lighting split when a hole touches the wall. Tests check profile counts and path behavior.
Collapsed grid triangles
indra/llmath/llvolume.cpp, indra/llmath/tests/llvolume_test.cpp
Grid generation detects collapsed boundaries and omits the corresponding zero-area triangles while retaining vertices. Tangent generation accepts sparse grid indices. Tests validate triangle layout, shared-versus-unique faces, and collapsed geometry.
Flat inner-face corner columns
indra/llmath/llvolume.cpp, indra/llmath/tests/llvolume_test.cpp
Flat inner faces add copied columns at profile corners and use those columns when building face indices and normals. Tests derive strip boundaries from matching positions and UVs and check corner copies and hard edges.

Priority: ➖ Normal

Estimated code review effort: 4 (Complex) | ~60 minutes

Change: Other

Possibly related PRs

Suggested reviewers: akleshchev

Merge Risk: ⚪ Minimal · up to 327b5

The geometry reduction has no established merge-blocking defect in the supplied evidence. Complete normal build and viewer checks before merging.

Pre-merge checks: Passed 4 · Failed 1

Failed Failed checks: 1 warning

Check name Status Explanation Resolution
Docstring Coverage Warning Docstring coverage is 43.48% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 23 functions across 3 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
Passed Passed checks: 4 passed
Check name Status Explanation
Title check Passed The title identifies the two main changes: reduced geometry for straight prims and omission of triangles when parameters collapse. The wording is slightly awkward, but the title is concise and related…
Description check Passed The description provides clear motivation, implementation details, examples, testing results, and known gaps. It does not include the template's Related Issues, Checklist, or Additional Notes headings…
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
Full details: Title check

Explanation

The title identifies the two main changes: reduced geometry for straight prims and omission of triangles when parameters collapse. The wording is slightly awkward, but the title is concise and related to the changes.

Full details: Description check

Explanation

The description provides clear motivation, implementation details, examples, testing results, and known gaps. It does not include the template's Related Issues, Checklist, or Additional Notes headings, but the core description is complete and directly addresses the pull request changes.

  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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

A rabbit checks the profile line,
And counts each corner copy fine.
Where rows collapse, the triangles part,
The grid keeps every vertex heart.
The hollow mesh hops cleanly through,
With tests to count each corner too.

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

RyeMutt and others added 4 commits October 23, 2026 09:04
LLVolume::generate split every profile edge into detail * 0.66 pieces,
and gave a straight path at least split + 2 rings, so that vertex
lighting and texture interpolation had more vertices across stretched
triangles. A default box at LOD 3 carried 96 vertices and 108 triangles
where 24 and 12 describe it exactly.

On a straight path with no twist and no taper, every side quad is a
parallelogram and every face is flat or ruled straight along the path,
so the extra points sit on the surface and affine UV interpolation is
exact without them. There, split is 0 and the path has 2 rings: a box is
24 / 12 at every LOD, a cylinder 102 / 96 at LOD 3 instead of 152 / 192,
and the uncut cube cap a single quad. Twisted, tapered, circular and
flexible paths keep their split.

A square hole pulled in to its wall is not straight between its corners,
so its profile keeps the split points that shape it.

Positions and UVs at kept vertices match within 7e-7, and every removed
vertex lies on the new surface with the UV it had.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A square or triangle hole's inner side is one face, and createSide
copied every profile point after the first so each strip got its own
normals, split points included, plus a closing column. The copies at the
hole's corners are its creases; the ones at split points made the inner
side of a twisted or circular hollow prim faceted strip by strip while
its outer sides are smooth, and each pair added a zero-width quad.

The profile now records which points are the hole's corners, and the
inner side copies those alone, so it is smooth from corner to corner as
the outer sides are. The zero-width quads emit no triangles, decided
from the column layout, never from positions, so flexible prims keep a
topology fixed by their parameters. A hole pulled in to its wall counts
every point as a corner. The hollow box is 52 / 32 at every LOD, a
twisted hollow box at LOD 3 500 vertices instead of 612.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…w or column

A prim tapered to a point puts a whole row of vertices at its apex, and
a sphere puts a whole column at each pole; half the triangles touching
them have no area. A shared volume (not unique, not a sculpt) now emits
none there. Which rows and columns collapse is decided from the
parameters alone: a straight path scaled to 0 at an end it reaches, a
circular path tapered by 1, and a half circle on a circle path with a
hole size of 1 in y, no skew, no x taper and a constant twist in whole
half turns. The vertices stay, since each column carries its own UV and
normal, and no face is left empty. A sphere at LOD 3 is 325 / 528
instead of 325 / 576.

The index loop is a template over whether a face has collapsed rows, so
the common case runs the loop it always did.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The sphere pole override gave the first point of a hollow sphere's flat
inner side the axis as its normal, while the last point kept its
strip's, which shaded half of that side with a 45-degree gradient. Both
ends now keep their strip's normal.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@RyeMutt
RyeMutt force-pushed the rye/prim-vertex-reduction branch from 4a697b4 to 5eb8b96 Compare October 23, 2026 13:10
@RyeMutt
RyeMutt merged commit 5fe299a into develop Oct 25, 2026
23 checks passed
@RyeMutt
RyeMutt deleted the rye/prim-vertex-reduction branch October 25, 2026 06:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant