Repository navigation
[M2-SPRITE-03] Atlas UV frame animation hook - #74
Merged
Merged
Conversation
Atlas sheet frame layout (SpriteFrameLayout: frame size, row/col, inter-frame spacing + sheet-edge margin, all texels) + the pure frame-index -> UV sub-rect computation (spriteFrameUv): O(1), zero allocation, float-exact at atlas dimensions <= 2^24 (the documented u1 > u0, v1 > v0 invariant); out-of-range frame -> InvalidArgument, never wrap (the layout is untrusted asset metadata — validated first-failure-wins, with the u64 overflow guard before the col·stride multiplication). SpriteItem gains the animation frame index (frameIndex — caller-set, carried through the batcher untouched; uv is what the renderer draws). This is the data-driven hook M3 animation drives. Docs: docs/api/sprite_frames.md (new), sprite_batcher.md (SpriteItem row + 76 B/slot), coordinates.md §4.8 + §5 table row, docs/README index, module README. laige-api.json regenerated (1221 symbols / 38 headers). ctest entry sprite_frames (11 tests / 4 suites, no GL); all six local trees warning-clean + full ctest green; api / include / determinism lints green. No standalone budgets.json entry (composite 50k render-CPU budget measured at M2-PERF-01).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Scope (M2-SPRITE-03, nothing else)
The atlas UV frame animation hook — the data-driven half of FR-2.1's "atlas UV animation (sheet frames)":
src/laige-render/include/laige/render/sprite_frames.h(header-only, pure math):SpriteFrameLayout— the atlas sheet frame layout in texels:frameWidth/frameHeight,columns/rows,frameSpacing(gap between adjacent frames),sheetBorder(sheet-edge margin). Plain value, no ownership; the documented sheet model: row-major, frame 0 at the top-left, tight sheet2·border + cols·fw + (cols−1)·spacing.kSpriteFrameMaxAtlasTexels(2^24) — the float-exact atlas domain.spriteFrameUv(frameIndex, layout, atlasWidth, atlasHeight) → Result<SpriteUvRect>— O(1), zero allocation, no logging, no GL; the UV corners are the exactly-roundedk/Wvalues; the invariantu1 > u0, v1 > v0holds exactly in the domain.[1, 2^24]/frameIndex >= columns·rows(never wraps silently — the documented out-of-range error) / frame rect beyond the atlas →InvalidArgument. The layout is caller-owned, untrusted asset metadata (SCALE-004); an adversarial stride is rejected before thecol·stridemultiplication can wrap u64 (CPP-004).SpriteItemgainsframeIndex(the declared animation frame — the caller sets it and setsuvto the frame's rect viaspriteFrameUv; the batcher carries the index through untouched —uvis what the M2-SPRITE-02 renderer draws; M3 animation drives the frame advance on top of this same layout).SpriteItem+1 u32 (76 B/slot, ~136 B/capacity slot, 6.8 MB at the 50k stress budget) — pure-integer bookkeeping unchanged.Additive only: no existing symbol's signature or meaning changed; new public API is
SpriteFrameLayout/spriteFrameUv/kSpriteFrameMaxAtlasTexels+SpriteItem.frameIndex.Docs (same change, CORE-006)
docs/api/sprite_frames.md— full contract: sheet model + margins, v-axis convention (v = 0 is the sheet's top row — the M2-SPRITE-02GL_NEARESTrow-0 contract), failure table, the float-exact domain, the M3 hook, Performance (DOC-004), misuse warnings.docs/api/sprite_batcher.md(SpriteItem table row + 76 B/slot + Related),docs/concepts/coordinates.md(§4.8 UV bullet + §5 conversion-table row + Related),docs/README.md(API index), module README status paragraph.laige-api.jsonregenerated: 1221 symbols / 38 headers (+10 / +1).Verification
tests/laige-render/sprite_frames_tests.cpp— new CTest entrysprite_frames(the step's Verify command), 11 tests / 4 suites, no GL required:SpriteFrameUvGolden— hand-computed UVs for documented layouts (packed 4×4, tight 82×82 margin sheet, non-square 12×8 frames with spacing, single column/row, idempotent call).SpriteFrameErrors— out-of-range at count / beyond / u32 top with the no-wrap pin, zero-extent layouts, the atlas domain (incl. the exact 2^24 top), the fit failures (one-texel-short spacing, the exact boundary, the adversarial stride).SpriteFrameProperty— 2 000 seeded random tight sheets vs the documented formula + the float-exact invariants + the row/col adjacency rule + the 1 000-conversion zero-allocation proof (non-sanitizer trees, the iso_picking/depth_sort precedent).SpriteFrameItemPassThrough— theframeIndex+uvpair survives the batcher's add/build/get (the M3 entry point).ctest -R sprite_framesgreen in each).api-real-tree/api-check-fresh,include-lint(38 public headers),determinism-lint— all green.budgets.jsonentry (the per-frame conversion cost is part of the composite 50k render-CPU budget,sprites_50k_cpu, measured with M2-PERF-01).Roadmap
M2-SPRITE-03 box checked; Progress Board M2 15/33, total 61/194; Change Log row.
Scope note: the implementation exceeds the roadmap's "~100 lines" sanity note for the same documented-contract reason as M2-SORT-01/M2-SPRITE-01 (the header preamble + the API doc are part of the implementation per CORE-006/DOC-004).