CNA-GAP-035: Models built to .xnb carry no cameras, because an XNA Model has no camera storage

CNA snapshot 3b43bd86  ·  Known Issues › Functional gaps  ·  source links pinned to 3b43bd86

✓

Evidence basis: source-verified at the pinned commit; tests exist (not executed for this page). Claims on this page were checked by reading the CNA source at commit 3b43bd86; unless a sentence says otherwise, nothing here was built or executed. Nothing on this page was executed unless the Evidence section says so.

A glTF compiled to .xnb drops its cameras with a build warning, so the model loads with an empty CamerasEXT; the direct glTF, .cnj and .cnb routes carry them, and Model.hpp still documents the property as empty for every other content path.

Identifier
CNA-GAP-035
Category
Functional gap
Subsystem
Models & glTF
Status
Narrowed (partially fixed; describes only what survives)
Verified against
CNA 3b43bd86 (3b43bd8687ed46523d873f9bec4b32bd8481dcb5)
Evidence basis
Source-verified: read at TARGET, not executed
Tests touching this area
Yes: see Current tests
Affected contract
Model::getCamerasEXTProperty() on models loaded through .xnb, .cnj and .cnb; the XNB model output of the content build

Expected behaviour

A camera authored in the glTF source should survive whichever CNA route the model takes, as the other imported data (bones, clips, materials) does, or the route should say that it cannot carry it.

Actual behaviour at TARGET

The direct glTF route fills Model::CamerasEXT (MakeModelCameraEXT in ContentModelLoaders.cpp). Since 1beef880d (CNA-DEMOS-ISSUE-023) gltf_to_cnj writes the cameras into the Model .cnj, the .cnj reader carries them into CnbModelData::cameras, an optional MCAM chunk stores them in the .cnb, and both loaders build each camera through the same MakeModelCameraEXT. An .xnb model cannot hold them: XNA's Model has no camera member, so XnbOutputContentPipeline.cpp drops them with the warning “camera(s) are not written: an XNA Model has no camera storage”, and such a model loads with an empty CamerasEXT.

CNA closed ISSUE-023 on a complete checkpoint (6c8b042c4, 2026-10-24). Model.hpp still documents the property as “Empty for every model built by any other content path”, which reads as if only the direct glTF route filled it.

Source locations

Evidence

Checked by reading and grepping at 3b43bd86 for setCamerasEXTProperty; not executed.

Re-verified at c6dec91f: 1beef880d adds the .cnj and .cnb camera carriers and the XNB warning; setCamerasEXTProperty is now called by the runtime glTF, .cnj and .cnb Model loaders in ContentModelLoaders.cpp. CNA_DEMOS_REPAIR_MATRIX.json lists ISSUE-023 as PENDING_VERIFICATION. Not executed.

Re-verified at 3b43bd86: the camera carriers and the XNB warning are unchanged (ContentModelLoaders.cpp changed only in comments; XnbOutputContentPipeline.cpp, gltf_to_cnj.cpp and Model.hpp are unchanged), and CNA_DEMOS_REPAIR_MATRIX.json now lists ISSUE-023 as FIXED_VALIDATED, accepted at 1beef880d and closed on the complete checkpoint. Not executed.

Focused reproduction

No focused reproduction is known. Nothing has been invented here; the evidence above is what exists.

Current tests

GltfCameraTests.cpp covers extraction on the direct glTF route. Since 1beef880d: GltfToCnjToolTest.ACnjModelCarriesTheSceneCamerasExactly, CnbModelCodecTest.CamerasRoundTripInAChunkOlderReadersSkip, ModelContentPipelineTest.ACompiledModelHasTheSameCamerasAsTheRunTimeImport and XnbModelSourceRouteTest.ACameraTheXnaModelCannotHoldIsNamed (XnbOutputContentPipelineTests.cpp). None was run for this entry.

Regression test

The tests above cover the round trip. The .xnb limit is XNA's format and has no fix; the Model.hpp sentence needs correcting.

Blast radius

Applications that compile glTF to .xnb and expect its cameras (none arrive). Direct glTF loads and the .cnj and .cnb routes are unaffected.

Workaround

Load the .gltf/.glb directly, or compile to .cnb rather than .xnb, when the cameras are needed.

The same subject is explained at several altitudes. These are the neighbouring pages at each one.