// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. See LICENSE in the project root for license information. #include "pch.h" #include #include "GLTFSDK/IStreamWriter.h" #include "GLTFSDK/Constants.h" #include "GLTFSDK/Deserialize.h" #include "GLTFSDK/GLBResourceWriter.h" #include "GLTFSDK/GLBResourceReader.h" #include "GLTFSDK/GLTFResourceWriter.h" #include "SerializeBinary.h" #include "Helpers/TestUtils.h" #include "Helpers/WStringUtils.h" #include "Helpers/StreamMock.h" using namespace Microsoft::VisualStudio::CppUnitTestFramework; using namespace Microsoft::glTF; using namespace Microsoft::glTF::Toolkit; namespace Microsoft::glTF::Toolkit::Test { class InMemoryStream : public Microsoft::glTF::IStreamWriter { public: InMemoryStream(std::shared_ptr stream) : m_stream(stream) { } std::shared_ptr GetOutputStream(const std::string&) const { return m_stream; } private: std::shared_ptr m_stream; }; TEST_CLASS(GLBSerializerTests) { static std::string ReadLocalJson(const char * relativePath) { auto input = TestUtils::ReadLocalAsset(TestUtils::GetAbsolutePath(relativePath)); auto json = std::string(std::istreambuf_iterator(*input), std::istreambuf_iterator()); return json; } static std::shared_ptr ImportGLB(const std::shared_ptr& streamReader, const std::shared_ptr& glbStream) { GLBResourceReader resourceReader(streamReader, glbStream); auto json = resourceReader.GetJson(); auto doc = Deserialize(json); return std::make_shared(doc); } static std::shared_ptr ImportGLTF(const std::shared_ptr& streamReader, const std::shared_ptr& stream) { GLTFResourceReader resourceReader(streamReader); auto json = std::string(std::istreambuf_iterator(*stream), std::istreambuf_iterator()); auto doc = Deserialize(json); return std::make_shared(doc); } const char* c_waterBottleJson = "Resources\\gltf\\WaterBottle\\WaterBottle.gltf"; TEST_METHOD(GLBSerializerTests_RoundTrip_Simple) { auto data = ReadLocalJson(c_waterBottleJson); auto input = std::make_shared(data); try { // Deserialize input json auto inputJson = std::string(std::istreambuf_iterator(*input), std::istreambuf_iterator()); auto doc = Deserialize(inputJson); // Serialize Document to GLB auto streamReader = std::make_shared(TestUtils::GetAbsolutePath(c_waterBottleJson)); auto stream = std::make_shared(std::ios_base::app | std::ios_base::binary | std::ios_base::in | std::ios_base::out); SerializeBinary(doc, streamReader, std::make_shared(stream)); // Deserialize the GLB again auto glbReader = std::make_unique(streamReader, stream); auto outputJson = glbReader->GetJson(); auto outputDoc = Deserialize(outputJson); // Check some structural elements Assert::AreEqual(doc.nodes.Size(), outputDoc.nodes.Size()); Assert::AreEqual(doc.images.Size(), outputDoc.images.Size()); // There must be only one buffer, and it can't have a URI Assert::AreEqual(static_cast(1), outputDoc.buffers.Size()); auto glbBuffer = outputDoc.buffers.Elements()[0]; Assert::IsTrue(glbBuffer.uri.empty()); // Check that the images that were stored as URI are now bufferViews for (auto image : outputDoc.images.Elements()) { // Images in GLB don't have a URI Assert::IsTrue(image.uri.empty()); // Images in GLB are stored in a buffer Assert::IsFalse(image.bufferViewId.empty()); // Images in original GLTF have a URI Assert::IsFalse(doc.images.Get(image.id).uri.empty()); } // All buffer views must point to the GLB buffer for (auto bufferView : outputDoc.bufferViews.Elements()) { Assert::IsTrue(bufferView.bufferId == glbBuffer.id); } // Read one of the images and check it's identical auto gltfReader = std::make_unique(streamReader); std::vector gltfImage = gltfReader->ReadBinaryData(doc, doc.images.Elements()[0]); std::vector glbImage = glbReader->ReadBinaryData(outputDoc, outputDoc.images.Elements()[0]); Assert::IsTrue(gltfImage == glbImage); // Vector comparison } catch (std::exception ex) { std::stringstream ss; ss << "Received exception was unexpected. Got: " << ex.what(); Assert::Fail(WStringUtils::ToWString(ss).c_str()); } } }; }