@@ -219,6 +219,27 @@ static bool LoadKTX2Image(tinygltf::Image* image,
219219 }
220220 return false ;
221221}
222+
223+ // Resolves the image index for a texture, falling back to the KHR_texture_basisu
224+ // extension's source when the core "source" property is absent (required for
225+ // KTX2-only textures, since core glTF only allows PNG/JPEG as the image mimeType).
226+ static int ResolveGltfImageIndex (const tinygltf::Model& gltfModel, const tinygltf::Texture& texture) {
227+ if (texture.source >= 0 && texture.source < static_cast <int >(gltfModel.images .size ())) {
228+ return texture.source ;
229+ }
230+ auto extIt = texture.extensions .find (" KHR_texture_basisu" );
231+ if (extIt != texture.extensions .end ()) {
232+ const tinygltf::Value& ext = extIt->second ;
233+ if (ext.Has (" source" ) && ext.Get (" source" ).IsInt ()) {
234+ int src = ext.Get (" source" ).Get <int >();
235+ if (src >= 0 && src < static_cast <int >(gltfModel.images .size ())) {
236+ return src;
237+ }
238+ }
239+ }
240+ return -1 ;
241+ }
242+
222243void ModelLoader::ProcessMaterials (const tinygltf::Model& gltfModel,
223244 const std::string& baseTexturePath,
224245 std::set<std::string>& loadedTextures) {
@@ -353,20 +374,7 @@ void ModelLoader::ProcessMaterials(const tinygltf::Model& gltfModel,
353374 int texIndex = diffObj.Get (" index" ).Get <int >();
354375 if (texIndex >= 0 && texIndex < static_cast <int >(gltfModel.textures .size ())) {
355376 const auto & texture = gltfModel.textures [texIndex];
356- int imageIndex = -1 ;
357- if (texture.source >= 0 && texture.source < static_cast <int >(gltfModel.images .size ())) {
358- imageIndex = texture.source ;
359- } else {
360- auto extBasis = texture.extensions .find (" KHR_texture_basisu" );
361- if (extBasis != texture.extensions .end ()) {
362- const tinygltf::Value& e = extBasis->second ;
363- if (e.Has (" source" ) && e.Get (" source" ).IsInt ()) {
364- int src = e.Get (" source" ).Get <int >();
365- if (src >= 0 && src < static_cast <int >(gltfModel.images .size ()))
366- imageIndex = src;
367- }
368- }
369- }
377+ int imageIndex = ResolveGltfImageIndex (gltfModel, texture);
370378 if (imageIndex >= 0 ) {
371379 const auto & image = gltfModel.images [imageIndex];
372380 std::string textureId = " gltf_baseColor_" + std::to_string (texIndex);
@@ -389,9 +397,10 @@ void ModelLoader::ProcessMaterials(const tinygltf::Model& gltfModel,
389397 int texIndex = sgObj.Get (" index" ).Get <int >();
390398 if (texIndex >= 0 && texIndex < static_cast <int >(gltfModel.textures .size ())) {
391399 const auto & texture = gltfModel.textures [texIndex];
392- if (texture.source >= 0 && texture.source < static_cast <int >(gltfModel.images .size ())) {
400+ int imageIndex = ResolveGltfImageIndex (gltfModel, texture);
401+ if (imageIndex >= 0 ) {
393402 std::string textureId = " gltf_specGloss_" + std::to_string (texIndex);
394- const auto & image = gltfModel.images [texture. source ];
403+ const auto & image = gltfModel.images [imageIndex ];
395404 if (!image.image .empty ()) {
396405 // Embedded image data (already decoded by tinygltf image loader)
397406 renderer->LoadTextureFromMemoryAsync (textureId, image.image .data (), image.width , image.height , image.component , false , material->alphaMode == " MASK" );
@@ -416,21 +425,7 @@ void ModelLoader::ProcessMaterials(const tinygltf::Model& gltfModel,
416425 int texIndex = gltfMaterial.pbrMetallicRoughness .baseColorTexture .index ;
417426 if (texIndex < gltfModel.textures .size ()) {
418427 const auto & texture = gltfModel.textures [texIndex];
419- int imageIndex = -1 ;
420- if (texture.source >= 0 && texture.source < gltfModel.images .size ()) {
421- imageIndex = texture.source ;
422- } else {
423- auto extIt = texture.extensions .find (" KHR_texture_basisu" );
424- if (extIt != texture.extensions .end ()) {
425- const tinygltf::Value& ext = extIt->second ;
426- if (ext.Has (" source" ) && ext.Get (" source" ).IsInt ()) {
427- int src = ext.Get (" source" ).Get <int >();
428- if (src >= 0 && src < static_cast <int >(gltfModel.images .size ())) {
429- imageIndex = src;
430- }
431- }
432- }
433- }
428+ int imageIndex = ResolveGltfImageIndex (gltfModel, texture);
434429 if (imageIndex >= 0 ) {
435430 std::string textureId = " gltf_baseColor_" + std::to_string (texIndex);
436431 material->albedoTexturePath = textureId;
@@ -458,12 +453,13 @@ void ModelLoader::ProcessMaterials(const tinygltf::Model& gltfModel,
458453 int texIndex = gltfMaterial.pbrMetallicRoughness .metallicRoughnessTexture .index ;
459454 if (texIndex < gltfModel.textures .size ()) {
460455 const auto & texture = gltfModel.textures [texIndex];
461- if (texture.source >= 0 && texture.source < gltfModel.images .size ()) {
456+ int imageIndex = ResolveGltfImageIndex (gltfModel, texture);
457+ if (imageIndex >= 0 ) {
462458 std::string textureId = " gltf_texture_" + std::to_string (texIndex);
463459 material->metallicRoughnessTexturePath = textureId;
464460
465461 // Load texture data (embedded or external)
466- const auto & image = gltfModel.images [texture. source ];
462+ const auto & image = gltfModel.images [imageIndex ];
467463 if (!image.image .empty ()) {
468464 // Load embedded texture data asynchronously
469465 renderer->LoadTextureFromMemoryAsync (textureId, image.image .data (), image.width , image.height , image.component );
@@ -484,21 +480,7 @@ void ModelLoader::ProcessMaterials(const tinygltf::Model& gltfModel,
484480 int texIndex = gltfMaterial.normalTexture .index ;
485481 if (texIndex < gltfModel.textures .size ()) {
486482 const auto & texture = gltfModel.textures [texIndex];
487- int imageIndex = -1 ;
488- if (texture.source >= 0 && texture.source < gltfModel.images .size ()) {
489- imageIndex = texture.source ;
490- } else {
491- auto extIt = texture.extensions .find (" KHR_texture_basisu" );
492- if (extIt != texture.extensions .end ()) {
493- const tinygltf::Value& ext = extIt->second ;
494- if (ext.Has (" source" ) && ext.Get (" source" ).IsInt ()) {
495- int src = ext.Get (" source" ).Get <int >();
496- if (src >= 0 && src < static_cast <int >(gltfModel.images .size ())) {
497- imageIndex = src;
498- }
499- }
500- }
501- }
483+ int imageIndex = ResolveGltfImageIndex (gltfModel, texture);
502484 if (imageIndex >= 0 ) {
503485 std::string textureId = " gltf_texture_" + std::to_string (texIndex);
504486 material->normalTexturePath = textureId;
@@ -525,12 +507,13 @@ void ModelLoader::ProcessMaterials(const tinygltf::Model& gltfModel,
525507 int texIndex = gltfMaterial.occlusionTexture .index ;
526508 if (texIndex < gltfModel.textures .size ()) {
527509 const auto & texture = gltfModel.textures [texIndex];
528- if (texture.source >= 0 && texture.source < gltfModel.images .size ()) {
510+ int imageIndex = ResolveGltfImageIndex (gltfModel, texture);
511+ if (imageIndex >= 0 ) {
529512 std::string textureId = " gltf_texture_" + std::to_string (texIndex);
530513 material->occlusionTexturePath = textureId;
531514
532515 // Load texture data (embedded or external)
533- const auto & image = gltfModel.images [texture. source ];
516+ const auto & image = gltfModel.images [imageIndex ];
534517 if (!image.image .empty ()) {
535518 // Schedule embedded texture upload
536519 renderer->LoadTextureFromMemoryAsync (textureId, image.image .data (), image.width , image.height , image.component );
@@ -551,12 +534,13 @@ void ModelLoader::ProcessMaterials(const tinygltf::Model& gltfModel,
551534 int texIndex = gltfMaterial.emissiveTexture .index ;
552535 if (texIndex < gltfModel.textures .size ()) {
553536 const auto & texture = gltfModel.textures [texIndex];
554- if (texture.source >= 0 && texture.source < gltfModel.images .size ()) {
537+ int imageIndex = ResolveGltfImageIndex (gltfModel, texture);
538+ if (imageIndex >= 0 ) {
555539 std::string textureId = " gltf_texture_" + std::to_string (texIndex);
556540 material->emissiveTexturePath = textureId;
557541
558542 // Load texture data (embedded or external)
559- const auto & image = gltfModel.images [texture. source ];
543+ const auto & image = gltfModel.images [imageIndex ];
560544 if (!image.image .empty ()) {
561545 // Schedule embedded texture upload
562546 renderer->LoadTextureFromMemoryAsync (textureId, image.image .data (), image.width , image.height , image.component );
@@ -600,20 +584,7 @@ void ModelLoader::ProcessMaterials(const tinygltf::Model& gltfModel,
600584 int texIndex = diffObj.Get (" index" ).Get <int >();
601585 if (texIndex >= 0 && texIndex < static_cast <int >(gltfModel.textures .size ())) {
602586 const auto & texture = gltfModel.textures [texIndex];
603- int imageIndex = -1 ;
604- if (texture.source >= 0 && texture.source < static_cast <int >(gltfModel.images .size ())) {
605- imageIndex = texture.source ;
606- } else {
607- auto extBasis = texture.extensions .find (" KHR_texture_basisu" );
608- if (extBasis != texture.extensions .end ()) {
609- const tinygltf::Value& e = extBasis->second ;
610- if (e.Has (" source" ) && e.Get (" source" ).IsInt ()) {
611- int src = e.Get (" source" ).Get <int >();
612- if (src >= 0 && src < static_cast <int >(gltfModel.images .size ()))
613- imageIndex = src;
614- }
615- }
616- }
587+ int imageIndex = ResolveGltfImageIndex (gltfModel, texture);
617588 if (imageIndex >= 0 ) {
618589 const auto & image = gltfModel.images [imageIndex];
619590 std::string texIdOrPath;
@@ -1392,21 +1363,7 @@ bool ModelLoader::ParseGLTF(const std::string& filename, Model* model) {
13921363 int texIndex = gltfMaterial.pbrMetallicRoughness .baseColorTexture .index ;
13931364 if (texIndex < gltfModel.textures .size ()) {
13941365 const auto & texture = gltfModel.textures [texIndex];
1395- int imageIndex = -1 ;
1396- if (texture.source >= 0 && texture.source < gltfModel.images .size ()) {
1397- imageIndex = texture.source ;
1398- } else {
1399- auto extIt = texture.extensions .find (" KHR_texture_basisu" );
1400- if (extIt != texture.extensions .end ()) {
1401- const tinygltf::Value& ext = extIt->second ;
1402- if (ext.Has (" source" ) && ext.Get (" source" ).IsInt ()) {
1403- int src = ext.Get (" source" ).Get <int >();
1404- if (src >= 0 && src < static_cast <int >(gltfModel.images .size ())) {
1405- imageIndex = src;
1406- }
1407- }
1408- }
1409- }
1366+ int imageIndex = ResolveGltfImageIndex (gltfModel, texture);
14101367 if (imageIndex >= 0 ) {
14111368 std::string textureId = " gltf_baseColor_" + std::to_string (texIndex);
14121369 materialMesh.baseColorTexturePath = textureId;
@@ -1468,12 +1425,13 @@ bool ModelLoader::ParseGLTF(const std::string& filename, Model* model) {
14681425 int texIndex = gltfMaterial.normalTexture .index ;
14691426 if (texIndex < gltfModel.textures .size ()) {
14701427 const auto & texture = gltfModel.textures [texIndex];
1471- if (texture.source >= 0 && texture.source < gltfModel.images .size ()) {
1428+ int imageIndex = ResolveGltfImageIndex (gltfModel, texture);
1429+ if (imageIndex >= 0 ) {
14721430 std::string textureId = " gltf_texture_" + std::to_string (texIndex);
14731431 materialMesh.normalTexturePath = textureId;
14741432
14751433 // Load texture data (embedded or external)
1476- const auto & image = gltfModel.images [texture. source ];
1434+ const auto & image = gltfModel.images [imageIndex ];
14771435 if (!image.image .empty ()) {
14781436 // Load embedded texture data
14791437 renderer->LoadTextureFromMemoryAsync (textureId, image.image .data (), image.width , image.height , image.component );
@@ -1515,12 +1473,13 @@ bool ModelLoader::ParseGLTF(const std::string& filename, Model* model) {
15151473 int texIndex = gltfMaterial.pbrMetallicRoughness .metallicRoughnessTexture .index ;
15161474 if (texIndex < gltfModel.textures .size ()) {
15171475 const auto & texture = gltfModel.textures [texIndex];
1518- if (texture.source >= 0 && texture.source < gltfModel.images .size ()) {
1476+ int imageIndex = ResolveGltfImageIndex (gltfModel, texture);
1477+ if (imageIndex >= 0 ) {
15191478 std::string textureId = " gltf_texture_" + std::to_string (texIndex);
15201479 materialMesh.metallicRoughnessTexturePath = textureId;
15211480
15221481 // Load texture data (embedded or external)
1523- const auto & image = gltfModel.images [texture. source ];
1482+ const auto & image = gltfModel.images [imageIndex ];
15241483 if (!image.image .empty ()) {
15251484 renderer->LoadTextureFromMemoryAsync (textureId, image.image .data (), image.width , image.height , image.component );
15261485 materialMesh.metallicRoughnessTexturePath = textureId;
@@ -1554,12 +1513,13 @@ bool ModelLoader::ParseGLTF(const std::string& filename, Model* model) {
15541513 int texIndex = gltfMaterial.occlusionTexture .index ;
15551514 if (texIndex < gltfModel.textures .size ()) {
15561515 const auto & texture = gltfModel.textures [texIndex];
1557- if (texture.source >= 0 && texture.source < gltfModel.images .size ()) {
1516+ int imageIndex = ResolveGltfImageIndex (gltfModel, texture);
1517+ if (imageIndex >= 0 ) {
15581518 std::string textureId = " gltf_texture_" + std::to_string (texIndex);
15591519 materialMesh.occlusionTexturePath = textureId;
15601520
15611521 // Load texture data (embedded or external)
1562- const auto & image = gltfModel.images [texture. source ];
1522+ const auto & image = gltfModel.images [imageIndex ];
15631523 if (!image.image .empty ()) {
15641524 if (renderer->LoadTextureFromMemory (textureId,
15651525 image.image .data (),
@@ -1605,12 +1565,13 @@ bool ModelLoader::ParseGLTF(const std::string& filename, Model* model) {
16051565 int texIndex = gltfMaterial.emissiveTexture .index ;
16061566 if (texIndex < gltfModel.textures .size ()) {
16071567 const auto & texture = gltfModel.textures [texIndex];
1608- if (texture.source >= 0 && texture.source < gltfModel.images .size ()) {
1568+ int imageIndex = ResolveGltfImageIndex (gltfModel, texture);
1569+ if (imageIndex >= 0 ) {
16091570 std::string textureId = " gltf_texture_" + std::to_string (texIndex);
16101571 materialMesh.emissiveTexturePath = textureId;
16111572
16121573 // Load texture data (embedded or external)
1613- const auto & image = gltfModel.images [texture. source ];
1574+ const auto & image = gltfModel.images [imageIndex ];
16141575 if (!image.image .empty ()) {
16151576 // Load embedded texture data
16161577 renderer->LoadTextureFromMemoryAsync (textureId, image.image .data (), image.width , image.height , image.component );
0 commit comments