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>
This commit is contained in:
parent
c04b7a331a
commit
fbf3e7fc2e
4 changed files with 1468 additions and 400 deletions
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue