Skip to content

Commit 641e02e

Browse files
AssetLoader: expose GLTF texture sources from Document
1 parent d496a9c commit 641e02e

3 files changed

Lines changed: 128 additions & 0 deletions

File tree

AssetLoader/interface/GLTFLoader.hpp

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -769,6 +769,28 @@ struct DocumentLoadInfo
769769
bool DecodeImages = true;
770770
};
771771

772+
/// Resolved texture source referenced by a GLTF texture.
773+
struct TextureSourceInfo
774+
{
775+
/// Index in tinygltf::Model::textures.
776+
Uint32 TextureIndex = 0;
777+
778+
/// Index in tinygltf::Model::images.
779+
int ImageIndex = -1;
780+
781+
/// Index in tinygltf::Model::samplers.
782+
int SamplerIndex = -1;
783+
784+
/// Resolved external image URI. Empty for embedded image data.
785+
std::string URI;
786+
787+
/// Pointer to encoded image data for embedded buffer-view or data URI images.
788+
const void* pData = nullptr;
789+
790+
/// Size of encoded image data in bytes.
791+
Uint64 DataSize = 0;
792+
};
793+
772794
/// Parsed GLTF document.
773795
class Document
774796
{
@@ -784,6 +806,16 @@ class Document
784806
const tinygltf::Model& GetModel() const noexcept;
785807
const std::string& GetBaseDir() const noexcept;
786808

809+
/// Returns the number of textures in the document.
810+
Uint32 GetTextureCount() const;
811+
812+
/// Resolves a GLTF texture to either an external URI or an embedded encoded-data span.
813+
///
814+
/// Embedded buffer-view spans are owned by the document buffers. Embedded data URI
815+
/// spans are owned by tinygltf::Image::image. In both cases the returned pointer
816+
/// remains valid only while the document is alive and unchanged.
817+
bool GetTextureSourceInfo(Uint32 TextureIndex, TextureSourceInfo& Source) const;
818+
787819
private:
788820
std::string m_FileName;
789821
std::string m_BaseDir;

AssetLoader/src/GLTFLoader.cpp

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -905,6 +905,69 @@ int GetTextureImageIndex(const tinygltf::Model& gltf_model,
905905
return DDSSource >= 0 ? DDSSource : gltf_tex.source;
906906
}
907907

908+
Uint32 Document::GetTextureCount() const
909+
{
910+
const tinygltf::Model& gltf_model = GetModel();
911+
DEV_CHECK_ERR(gltf_model.textures.size() <= (std::numeric_limits<Uint32>::max)(),
912+
"Too many textures in GLTF document");
913+
return static_cast<Uint32>(gltf_model.textures.size());
914+
}
915+
916+
bool Document::GetTextureSourceInfo(Uint32 TextureIndex, TextureSourceInfo& Source) const
917+
{
918+
const tinygltf::Model& gltf_model = GetModel();
919+
if (TextureIndex >= gltf_model.textures.size())
920+
return false;
921+
922+
const tinygltf::Texture& gltf_tex = gltf_model.textures[TextureIndex];
923+
const int ImageIdx = GetTextureImageIndex(gltf_model, gltf_tex);
924+
if (ImageIdx < 0 || ImageIdx >= static_cast<int>(gltf_model.images.size()))
925+
return false;
926+
927+
const tinygltf::Image& gltf_image = gltf_model.images[ImageIdx];
928+
929+
Source = {};
930+
Source.TextureIndex = TextureIndex;
931+
Source.ImageIndex = ImageIdx;
932+
Source.SamplerIndex = gltf_tex.sampler;
933+
934+
if (gltf_image.bufferView >= 0)
935+
{
936+
if (gltf_image.bufferView >= static_cast<int>(gltf_model.bufferViews.size()))
937+
return false;
938+
939+
const tinygltf::BufferView& BufferView = gltf_model.bufferViews[static_cast<size_t>(gltf_image.bufferView)];
940+
if (BufferView.buffer < 0 || static_cast<size_t>(BufferView.buffer) >= gltf_model.buffers.size())
941+
return false;
942+
943+
const tinygltf::Buffer& Buffer = gltf_model.buffers[static_cast<size_t>(BufferView.buffer)];
944+
if (BufferView.byteOffset > Buffer.data.size() ||
945+
BufferView.byteLength > Buffer.data.size() - BufferView.byteOffset)
946+
{
947+
return false;
948+
}
949+
950+
Source.pData = Buffer.data.data() + BufferView.byteOffset;
951+
Source.DataSize = static_cast<Uint64>(BufferView.byteLength);
952+
return true;
953+
}
954+
955+
if (!gltf_image.image.empty())
956+
{
957+
Source.pData = gltf_image.image.data();
958+
Source.DataSize = static_cast<Uint64>(gltf_image.image.size());
959+
return true;
960+
}
961+
962+
if (!gltf_image.uri.empty())
963+
{
964+
Source.URI = GetImagePath(GetBaseDir(), gltf_image.uri);
965+
return !Source.URI.empty();
966+
}
967+
968+
return false;
969+
}
970+
908971
struct GLTFTextureSource
909972
{
910973
Uint32 TextureIndex = 0;

Tests/DiligentToolsTest/src/GLTFLoaderTest.cpp

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,17 @@ TEST(Tools_GLTFLoader, DocumentKeepsEmbeddedImageDataInBufferWhenDecodeImagesIsF
243243
EXPECT_EQ(std::vector<unsigned char>(BufferData.begin() + BufferView.byteOffset,
244244
BufferData.begin() + BufferView.byteOffset + BufferView.byteLength),
245245
(std::vector<unsigned char>{'D', 'D', 'S', ' '}));
246+
247+
EXPECT_EQ(Document.GetTextureCount(), 1u);
248+
249+
GLTF::TextureSourceInfo TextureSource;
250+
ASSERT_TRUE(Document.GetTextureSourceInfo(0, TextureSource));
251+
EXPECT_EQ(TextureSource.TextureIndex, 0u);
252+
EXPECT_EQ(TextureSource.ImageIndex, 0);
253+
EXPECT_EQ(TextureSource.SamplerIndex, -1);
254+
EXPECT_TRUE(TextureSource.URI.empty());
255+
EXPECT_EQ(TextureSource.pData, BufferData.data() + BufferView.byteOffset);
256+
EXPECT_EQ(TextureSource.DataSize, BufferView.byteLength);
246257
}
247258

248259
TEST(Tools_GLTFLoader, DocumentKeepsExternalImageUriWhenDecodeImagesIsFalse)
@@ -285,6 +296,17 @@ TEST(Tools_GLTFLoader, DocumentKeepsExternalImageUriWhenDecodeImagesIsFalse)
285296
EXPECT_EQ(Image.width, -1);
286297
EXPECT_EQ(Image.height, -1);
287298
EXPECT_FALSE(Files.WasRead("external.png"));
299+
300+
EXPECT_EQ(Document.GetTextureCount(), 1u);
301+
302+
GLTF::TextureSourceInfo TextureSource;
303+
ASSERT_TRUE(Document.GetTextureSourceInfo(0, TextureSource));
304+
EXPECT_EQ(TextureSource.TextureIndex, 0u);
305+
EXPECT_EQ(TextureSource.ImageIndex, 0);
306+
EXPECT_EQ(TextureSource.SamplerIndex, -1);
307+
EXPECT_TRUE(HasSuffix(TextureSource.URI, "external.png"));
308+
EXPECT_EQ(TextureSource.pData, nullptr);
309+
EXPECT_EQ(TextureSource.DataSize, 0u);
288310
}
289311

290312
TEST(Tools_GLTFLoader, DocumentCopiesDataUriImageBytesWhenDecodeImagesIsFalse)
@@ -326,6 +348,17 @@ TEST(Tools_GLTFLoader, DocumentCopiesDataUriImageBytesWhenDecodeImagesIsFalse)
326348
EXPECT_TRUE(Image.uri.empty());
327349
EXPECT_EQ(Image.image,
328350
(std::vector<unsigned char>{0x89u, 'P', 'N', 'G', '\r', '\n', 0x1Au, '\n'}));
351+
352+
EXPECT_EQ(Document.GetTextureCount(), 1u);
353+
354+
GLTF::TextureSourceInfo TextureSource;
355+
ASSERT_TRUE(Document.GetTextureSourceInfo(0, TextureSource));
356+
EXPECT_EQ(TextureSource.TextureIndex, 0u);
357+
EXPECT_EQ(TextureSource.ImageIndex, 0);
358+
EXPECT_EQ(TextureSource.SamplerIndex, -1);
359+
EXPECT_TRUE(TextureSource.URI.empty());
360+
EXPECT_EQ(TextureSource.pData, Image.image.data());
361+
EXPECT_EQ(TextureSource.DataSize, Image.image.size());
329362
}
330363

331364
} // namespace

0 commit comments

Comments
 (0)