fix(importer): import glTF primitives that have no index accessor #840

Merged
SakulFlee merged 1 commit from fix/gltf-non-indexed-primitives into main 2026-09-30 01:30:48 +00:00
Owner

A glTF primitive is allowed to omit its index accessor, in which case the spec defines its vertices as implicitly indexed 0..N in order. The importer treated a missing accessor as fatal for the primitive and continued, so every such primitive was dropped from the import with nothing but a "Primitive has no indices" log line. Several exporters emit unindexed primitives, so this could silently empty a model.

Keeps the accessor as an Option and resolves the implicit case once positions_vec is known, so the synthesized 0..N list feeds the same normal calculation and winding flip an explicit accessor feeds. A vertex count that isn't a whole number of triangles now logs the trailing vertices the winding flip drops.

Adds a regression test on a primitive with no NORMAL attribute and no index accessor, so the normals it asserts can only come from the synthesized indices reaching the triangle-geometry path. Verified the test fails without the fix (0 models instead of 1).

A glTF primitive is allowed to omit its index accessor, in which case the spec defines its vertices as implicitly indexed 0..N in order. The importer treated a missing accessor as fatal for the primitive and continued, so every such primitive was dropped from the import with nothing but a "Primitive has no indices" log line. Several exporters emit unindexed primitives, so this could silently empty a model. Keeps the accessor as an Option and resolves the implicit case once positions_vec is known, so the synthesized 0..N list feeds the same normal calculation and winding flip an explicit accessor feeds. A vertex count that isn't a whole number of triangles now logs the trailing vertices the winding flip drops. Adds a regression test on a primitive with no NORMAL attribute and no index accessor, so the normals it asserts can only come from the synthesized indices reaching the triangle-geometry path. Verified the test fails without the fix (0 models instead of 1).
perf(importer): read each primitive's glTF indices once instead of twice
All checks were successful
Lint / lint (pull_request) Successful in 4m12s
a87f1048ac
`parse_models` asked the primitive reader for indices twice per
primitive: once to build `indices_vec` for the normal-calculation path,
and again later through the `indices` binding for the winding flip. The
second read re-decodes the index accessor out of the buffer and throws
the result away after the flip loop re-derives an already-known order.

Collect the indices once and reuse that vector for both the normal
calculation and the winding flip.

There is no behaviour change here. `Reader::read_indices` takes `&self`
and builds a fresh iterator from the primitive's immutable JSON on every
call, so both reads yielded identical data. An earlier revision of this
change claimed the second call returned `None` and that `indices_vec`
came out empty, which would have disabled index-driven normal
calculation; that premise was wrong, no data was ever missing, and no
rendered output depends on it.
fix(importer): import glTF primitives that have no index accessor
All checks were successful
Lint / lint (pull_request) Successful in 4m13s
afe4e025a4
A glTF primitive is allowed to omit its index accessor, in which case
the spec defines its vertices as implicitly indexed 0..N in order. The
importer instead treated a missing accessor as fatal for the primitive
and `continue`d, so every such primitive was dropped from the import
with nothing but a "Primitive has no indices" log line to show for it.
Several exporters emit unindexed primitives, so this could silently
empty a model.

Keep the accessor as an `Option` and resolve the implicit case once
`positions_vec` is known, so the synthesized 0..N list feeds the same
normal calculation and winding flip that an explicit accessor feeds.
A vertex count that is not a whole number of triangles now logs the
trailing vertices the winding flip will drop instead of discarding them
without comment.

Adds a regression test built on a primitive with no `NORMAL` attribute
and no index accessor, so the normals it asserts can only come from the
synthesized indices reaching the triangle-geometry path.

`mode` is still ignored, so TRIANGLE_STRIP and TRIANGLE_FAN primitives
remain mis-imported. That is pre-existing, independent of whether an
accessor is present, and left for a separate change.
SakulFlee deleted branch fix/gltf-non-indexed-primitives 2026-09-30 01:30:48 +00:00
Sign in to join this conversation.
No description provided.