Skip to content

Commit 0208475

Browse files
committed
add support for KHR_texture_basisu extension and fix bistro.gltf to have that extension required.
1 parent 0e0ff21 commit 0208475

1 file changed

Lines changed: 50 additions & 89 deletions

File tree

attachments/simple_engine/model_loader.cpp

Lines changed: 50 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
222243
void 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

Comments
 (0)