Commit graph Crafter.Asset/interfaces
Author SHA1 Message Date
fbf3e7fc2e
fix(glb): the code review's findings, and morph targets
Images (Crafter.Asset:Texture):
- LoadPNGFromMemory reads an image's size from its header before decoding
  and refuses more than 65535 a side or 2^28 pixels: stb's 16-bit PNG path
  sized its buffer in 32 bits and overflowed the heap from 2^29. LoadPNG
  reads its file and goes the same way. SizeFromMemory is public.
- A failure stb gives no reason for no longer passes NULL to std::string,
  and the reason is cleared before each decode, so it is never an older one.
- LoadPNG throws std::runtime_error for a file that doesn't load, which
  crafter-build's try/catch reports per file; without exceptions it is Fatal.

Bounds (Crafter.Asset:GLB):
- Load takes an optional decodeLimit, by default 1 GiB plus 64 bytes for
  each byte of the file. Vertices, indices and pixels are paid for before
  they are allocated, so primitives or images naming the same data can't
  exhaust memory.
- extras are written without recursion: deep nesting overflowed the stack.
- The skinned-joint check is O(vertices + nodes), not O(nodes x vertices).
- Load(path) reads the 12-byte header before the rest, and says why a path
  doesn't open.
- Chunk arithmetic is in 32 bits, as the header's is, ordered so that it
  can't wrap round.

Correctness:
- Indices are range-checked before they are narrowed to 32 bits, and whole
  numbers written as 24.0 read as integers.
- Missing tangents come from the UV set the normal texture samples, and a
  zero normal no longer makes them NaN.
- A file that requires an extension the loader doesn't implement is an
  error.
- Only PNG and JPEG are decoded; other formats (WebP, KTX2) stay empty, and
  no texture may use one. An image repeating another's bufferView is copied.
- Strips and fans become lists; points and lines come back empty.
- texCoord is 0 or 1, and every primitive whose material samples it has it.
- JOINTS_n and WEIGHTS_n pair up, the four heaviest influences are kept, a
  vertex without weight goes to its first joint, and a skinned node's mesh
  has joints in every primitive.
- The default scene exists, and its roots are distinct root nodes.
- Sampler enums are glTF's.

New:
- TEXCOORD_1, as uv1.
- Morph targets with the mesh's and nodes' weights; sparse accessors and
  ones without a bufferView; the meshes' extras; the BIN chunk.
- Images are TextureAsset<Vector<std::uint8_t, 4, 4>>; GlbRGBA8 is gone.

Tests: each of the above. The deep chain is timed against one a quarter as
deep instead of a 2 s clock, which flaked in debug builds; the byteStride
and chunk-length tests now fail when the check they test is removed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-31 03:25:12 +01:00
c04b7a331a
feat(glb): a loader for binary glTF, and images decoded from memory
- Crafter.Asset:GLB. GlbAsset::Load reads a .glb from a file or a buffer:
  - nodes, with their parents;
  - every mesh's primitives: positions, normals, UV0, tangents (computed
    when absent), joints, weights (normalized), u32 indices;
  - skins with their inverse-bind matrices;
  - materials: PBR, emissive strength, transmission, ior, alpha mode;
  - images decoded to RGBA8, and samplers;
  - cameras and KHR_lights_punctual lights;
  - the raw JSON, and the extras of the scene, nodes, materials and lights.
  nlohmann/json 3.12.0 is vendored in lib/; only the implementation sees it.
- A broken file comes back as an error rather than a crash:
  - bad magic, truncation, a sparse accessor;
  - a chunk, view or accessor past its bounds, checked so that nothing
    wraps round, with 32-bit size_t too;
  - a stride outside 4..252, or one its elements overlap in;
  - a reference to something that doesn't exist, or children that form a
    cycle (found stepping through each node once, however deep);
  - a path that isn't a file;
  - an image larger than a texture's 65535 a side.
- TextureAsset::LoadPNGFromMemory decodes an image already in memory.
  LoadPNG refuses images over 65535 a side instead of truncating their size
  (in its float path, past the end of the pixels).
- Tests: GLB.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-20 19:46:43 +02:00
dfd7f899cf SPDX license update
Canonical LGPL-3.0-only text, GPL-3.0 companion, SPDX headers on all
first-party sources. Vendored lib/ (GDeflate, libdeflate) untouched.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-22 18:16:25 +02:00
765cf33069 wasm 2026-05-18 22:31:28 +02:00
30a283c1b3 asset compression 2026-05-11 18:37:30 +02:00
3aaffcd2e2 fix 2026-04-11 13:53:53 +02:00
c6cad0cb45 rename 2026-04-11 13:49:30 +02:00
2306f24e42 load into buffer 2026-04-11 13:27:15 +02:00
09475ed28f F16 tex fix 2026-04-01 08:36:12 +02:00
95ad5625a9 F16 tex 2026-04-01 07:30:26 +02:00
fc85c5318b opaque texture check 2026-03-10 19:01:01 +01:00
00a5704653 texture fix 2026-02-24 04:28:16 +01:00
057e7b94d7 rewrite 2026-02-19 03:00:13 +01:00