Skip to content

feat(procedural-items): revolve shapes (AK-03c) - #952

Closed
Aymericr wants to merge 3 commits into
fidelity/ak-03b-extrudefrom
fidelity/ak-03c-revolve
Closed

Aymericr wants to merge 3 commits into
fidelity/ak-03b-extrudefrom
fidelity/ak-03c-revolve

Conversation

@Aymericr

@Aymericr Aymericr commented Sep 27, 2026 •

Copy link
Copy Markdown
Contributor

AK-03c: revolve shapes

Stacked on #951 (AK-03b) → … → #945. Review the top commit only. This is part 3 of AK-03; sweep is deferred to B-05 (see Seam).

What. A v2 revolve shape: { primitive: 'revolve', profile: [[radius, height], …], segments?, arc?, position, rotation?, slot }.

  • Profile. 2–64 points, and each coordinate may be an expression. The profile turns about local Y, starting from +Z toward +X like the cylinder. segments (default 24) and arc (default 2π) are the cylinder fields.
  • Closed or open.
    • The shape is a closed solid when the profile meets the axis at both ends over a full turn. The builder orients the profile so the solid's normals face outward.
    • Otherwise it is an open surface, such as a lamp shade, and it also draws its back face. Materials are front-sided because WebGPU MRT forces DoubleSide to FrontSide.
    • The same rule is added to feat(procedural-items): cylinder segments, open, inner and arc (AK-03a) #950: an open solid cylinder now draws both wall faces (separate commit on that branch).
  • Evaluation.
    • Points that collapse onto the previous one are dropped, so a select-driven feature can shrink to zero length.
    • The profile is re-centred vertically in its box, which keeps the oriented-box invariant.
    • revolveIsClosed() is exported for the builder and the tests.
  • Triangles are analytic: 2 · segments · (points − 1), doubled for open surfaces, which matches LatheGeometry's index.

Why. Audit limit #1: +3.5 % of /next (256 elements) needs lathe: pool details, openings, devices, pendants, balusters. It is also trial blocker 6: an ellipsoid only approximates E7's bell shade, and E8's turned balusters had to be boxes.

Failing case first. Before the fix, core/src/procedural-items/revolve.test.ts failed 5 of 5 tests (scratch/AK-CORE/03c-failing-before.txt).

Proof. The trial's own recipes are built with this builder and scored with the trial's compare.py against the /next source meshes (scratch/AK-CORE/proofs/e7-e8.out, e8-balusters.out).

Element Candidate R@2 mm R@5 mm R@2 cm P@2 cm Triangles
E7 five-drop pendant (whole element) ellipsoid shades (before) 0.444 0.689 0.895 0.914 8,172
revolved measured bell 0.795 1.000 1.000 1.000 7,932
E8 turned balusters (baluster region) boxes (before) 0.190 0.287 1.00 1.00 192
revolve, 12 segments 0.434 0.775 1.00 1.00 4,932
  • E8 authoring. Each baluster is one revolve: a foot, two beads and the shaft. Each baluster's foot, bead offsets and length come from select(index, …) over values read from the source occurrences (e8-baluster-params.json), the way a converter would read them. At 2 cm both E8 candidates are already perfect, so the gain shows only at 2–5 mm.
  • Tests.
    • nodes geometry.test.ts: closed baluster, reversed baluster, open shade, half-turn shade, quarter-turn solid. Built triangles equal the evaluated count, the height matches the box, and every side-wall normal on a closed solid points outward.
    • core: box and centring, open versus closed counts, expression points, collapse, validation.
  • bun test src (core): 3017 pass. bun test src/procedural-item (nodes): 53 pass. turbo check-types for core, nodes and editor: pass. bun run check: clean.

Seam for B-05 (sweep, deferred). core/procedural-items/section.ts (#951) turns any resolved F1 section into rings. A future sweep shape takes { section, path: [Vec3], ends?: [SweepEndSpec, SweepEndSpec] }, evaluates the section exactly as extrude does, and emits the same rings along the path. Its triangle count follows from rings × path edges. Nothing in this PR constrains that shape.

House effect: no change. The /next scenes have no procedural-item nodes; the E7 and E8 gains land when converters write v2.

Rule Check
R1 Additive primitive. segments and arc now also apply to revolve
R2 LatheGeometry runs once per (recipe, params) and is cached (0.25 ms at 64×40, CHALLENGE lpb)
R5 Oriented-box invariant, so handles, bounds, paint and surfaces are unchanged
R3, R4, R6–R9 Not touched

Local preview

Shared setup for the whole stack: previews/AK.md (preview.sh start AK-PV previews/AK/ak-after.json serves on :3301).
Setup is in previews/AK.md.

What you will notice

  • The balusters are turned, with a foot, two beads and a shaft. Before, they were square boxes.
  • The pendant shades are bell shapes revolved from the measured /next profile. Before, they were ellipsoids.
  • The counter's steel basin is revolved.

Where to look

Pose 5-balusters; poses 1-overview and 2-ceiling for the pendant.

Before / after

previews/AK/before-5-balusters.png / after-5-balusters.png, and before-1-overview.png / after-1-overview.png.

Checked by me: the static renders at the listed poses (captured from :3100 and :3301). I did not click through the interactive steps in a browser; unit tests cover them.

Known limits

  • A revolve that does not close on its axis draws both faces; materials are front-sided.

For Wassim to review:

  1. The closed-versus-open rule and back faces.
  2. Dropping coincident points rather than refusing them.
  3. [radius, height] point order: radius first, like three's Vector2(x = r, y).

🤖 Generated with Claude Code


Note

Medium Risk
New v2 geometry path touches recipe validation, bounds/footprints, triangle budgets, and mesh winding; behavior is covered by tests but affects procedural item authoring and rendering.

Overview
Adds a recipe version 2 revolve shape: authors supply a 2–64 point profile of [radius, height] pairs (expressions allowed), optional segments and arc like cylinders, spun about local Y.

Core (recipe.ts). The primitive joins the shape union with validation (v2-only, no support surfaces, segments/arc on revolve). Evaluation resolves the profile, drops coincident points, centres it vertically in the oriented box, and exports revolveIsClosed() for closed solids (axis at both ends + full turn). Triangle counts, footprints (for ceiling cuts / motion), and v2 feature detection are extended accordingly.

Rendering (geometry.ts). Builds meshes with LatheGeometry, fixes profile winding for outward normals on closed solids, and duplicates flipped geometry for open or partial surfaces so front-sided materials still show both sides. Revolves use v2 world-scale UVs; flipped() is adjusted for already non-indexed geometry.

Tests. New revolve.test.ts covers evaluation, validation, and review fixes; geometry.test.ts checks built triangles vs budget, normals, and profile fidelity.

Reviewed by Cursor Bugbot for commit 0dddbbe. Bugbot is set up for automated code reviews on this repo. Configure here.

Codex review round (rev-952-a)

Failing test first: test(... AK-03c, failing), then the fix.

  • Revolve footprints follow their rings, so they fit a circle cut.
  • A revolve rejects a stray radius (strict per-primitive schema).
  • There is one LatheGeometry per revolve. Open surfaces reuse it flipped for back faces.
  • UVs are face-frame and world-scale. Vertices match the profile exactly.

@pascal

pascal Bot commented Sep 27, 2026

Copy link
Copy Markdown

I hit an error while handling your request (Model unavailable on AI Gateway free tier: Free tier users do not have access to this model. Upgrade to paid credits at https://vercel.com/d?to=%2F%5Bteam%5D%2F%7E%2Fai%3Fmodal%3Dtop-up for unrestricted…).

Please try again, rephrase, or reach out if it keeps failing.

Error id: 0872f387-67a0-4dc1-8a2a-4748540b9be0

@Aymericr
Aymericr force-pushed the fidelity/ak-03b-extrude branch from faf6efe to 14a1676 Compare September 27, 2026 02:13
@Aymericr
Aymericr force-pushed the fidelity/ak-03c-revolve branch from d547465 to 2fb7193 Compare September 27, 2026 02:13
@Aymericr
Aymericr force-pushed the fidelity/ak-03b-extrude branch from 14a1676 to a39be0a Compare September 27, 2026 02:32
@Aymericr
Aymericr force-pushed the fidelity/ak-03c-revolve branch from 2fb7193 to 11f4879 Compare September 27, 2026 02:32
@Aymericr
Aymericr force-pushed the fidelity/ak-03b-extrude branch from a39be0a to 93fe544 Compare September 27, 2026 02:33
@Aymericr
Aymericr force-pushed the fidelity/ak-03c-revolve branch 2 times, most recently from 8879032 to fd9aaa2 Compare September 27, 2026 02:34
@Aymericr
Aymericr force-pushed the fidelity/ak-03b-extrude branch from e5aad07 to bf12a8a Compare September 27, 2026 22:27
@Aymericr
Aymericr force-pushed the fidelity/ak-03c-revolve branch from fd9aaa2 to 97673ca Compare September 27, 2026 22:27
Aymericr and others added 3 commits September 27, 2026 20:46
A v2 'revolve' shape turns a [radius, height] profile (2-64 points, each
an expression) about local Y, with the cylinder's segments and arc. It is
a closed solid where the profile meets the axis at both ends over a full
turn; otherwise it is an open surface that also draws its back face, since
materials are front-sided. Evaluation drops points that collapse onto the
previous one and re-centres the profile in its box. Triangles are analytic
(two per segment per profile edge, doubled for open surfaces). The builder
uses LatheGeometry and orients the profile so solids face outward.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…us, profile-exact vertices (AK-03c, failing)

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…he per revolve; face-frame revolve UVs (AK-03c)

- Ceiling-cut containment reads each profile point's ring as rendered, so a
  revolve fits a circle cut of its own diameter.
- An open revolve mirrors its one LatheGeometry for the back face.
- Revolves take world-scale face-frame UVs, like extrusions and v2 cylinders.
- The strict shape union refuses a stray radius on a revolve.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@Aymericr

Copy link
Copy Markdown
Contributor Author

Landed on main via #971 (merge commit cf874a1), which contains this branch's commits and history.

@Aymericr Aymericr closed this Sep 28, 2026
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