CNA-GAP-035: Models built to .xnb carry no cameras, because an XNA Model has no camera storage
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
modules/content/src/Xna/ContentModelLoaders.cpp— MakeModelCameraEXT and the setCamerasEXTProperty calls of the glTF, .cnj and .cnb Model loadersmodules/content/src/Pipeline/XnbOutputContentPipeline.cpp— the XNB model output drops cameras with a warningmodules/graphics/include/Microsoft/Xna/Framework/Graphics/Model.hpp— getCamerasEXTProperty documentation: empty for every other content pathtools/gltf_to_cnj/gltf_to_cnj.cpp— writes the scene cameras into the Model .cnj since 1beef880d
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.
Related pages
The same subject is explained at several altitudes. These are the neighbouring pages at each one.
- User guide
- Model loading: glTF to .cnj
- Deep dives
- .cnj toolchain: routes · glTF import: the import report
- Known issues
- Functional gap index