From a283a255a584283f30a6b94e47ee7d944164a0e3 Mon Sep 17 00:00:00 2001 From: Malcolm Tyrrell Date: Wed, 6 Oct 2021 13:41:45 +0100 Subject: [PATCH 01/10] Allow schema checking of glTF2 file. --- code/AssetLib/glTF2/glTF2Asset.h | 13 ++++- code/AssetLib/glTF2/glTF2Asset.inl | 77 +++++++++++++++++++++------ code/AssetLib/glTF2/glTF2Importer.cpp | 25 ++++----- code/AssetLib/glTF2/glTF2Importer.h | 4 ++ code/Common/Importer.cpp | 20 +++++++ code/Common/Importer.h | 8 ++- include/assimp/Importer.hpp | 15 ++++++ include/assimp/config.h.in | 9 ++++ 8 files changed, 139 insertions(+), 32 deletions(-) diff --git a/code/AssetLib/glTF2/glTF2Asset.h b/code/AssetLib/glTF2/glTF2Asset.h index 9a50ede99..862fb861d 100644 --- a/code/AssetLib/glTF2/glTF2Asset.h +++ b/code/AssetLib/glTF2/glTF2Asset.h @@ -74,6 +74,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include +#include #if (__GNUC__ == 8 && __GNUC_MINOR__ >= 0) # pragma GCC diagnostic pop @@ -1066,6 +1067,7 @@ class Asset { private: IOSystem *mIOSystem; + rapidjson::IRemoteSchemaDocumentProvider *mSchemaDocumentProvider; std::string mCurrentAssetDir; @@ -1125,8 +1127,9 @@ public: Ref scene; public: - Asset(IOSystem *io = nullptr) : + Asset(IOSystem *io = nullptr, rapidjson::IRemoteSchemaDocumentProvider *schemaDocumentProvider = nullptr) : mIOSystem(io), + mSchemaDocumentProvider(schemaDocumentProvider), asset(), accessors(*this, "accessors"), animations(*this, "animations"), @@ -1149,6 +1152,9 @@ public: //! Main function void Load(const std::string &file, bool isBinary = false); + //! Parse the AssetMetadata and check that the version is 2. + bool CanRead(const std::string &pFile, bool isBinary = false); + //! Enables binary encoding on the asset void SetAsBinary(); @@ -1160,6 +1166,11 @@ public: private: void ReadBinaryHeader(IOStream &stream, std::vector &sceneData); + //! Obtain a JSON document from the stream. + // \param second argument is a buffer used by the document. It must be kept + // alive while the document is in use. + Document ReadDocument(IOStream& stream, bool isBinary, std::vector& sceneData); + void ReadExtensionsUsed(Document &doc); void ReadExtensionsRequired(Document &doc); diff --git a/code/AssetLib/glTF2/glTF2Asset.inl b/code/AssetLib/glTF2/glTF2Asset.inl index 4832995cc..b531b5a98 100644 --- a/code/AssetLib/glTF2/glTF2Asset.inl +++ b/code/AssetLib/glTF2/glTF2Asset.inl @@ -1777,28 +1777,16 @@ inline void Asset::ReadBinaryHeader(IOStream &stream, std::vector &sceneDa } } -inline void Asset::Load(const std::string &pFile, bool isBinary) { +inline rapidjson::Document Asset::ReadDocument(IOStream &stream, bool isBinary, std::vector &sceneData) +{ ASSIMP_LOG_DEBUG("Loading GLTF2 asset"); - mCurrentAssetDir.clear(); - /*int pos = std::max(int(pFile.rfind('/')), int(pFile.rfind('\\'))); - if (pos != int(std::string::npos)) */ - - if (0 != strncmp(pFile.c_str(), AI_MEMORYIO_MAGIC_FILENAME, AI_MEMORYIO_MAGIC_FILENAME_LENGTH)) { - mCurrentAssetDir = glTFCommon::getCurrentAssetDir(pFile); - } - - shared_ptr stream(OpenFile(pFile.c_str(), "rb", true)); - if (!stream) { - throw DeadlyImportError("GLTF: Could not open file for reading"); - } // is binary? then read the header - std::vector sceneData; if (isBinary) { SetAsBinary(); // also creates the body buffer - ReadBinaryHeader(*stream, sceneData); + ReadBinaryHeader(stream, sceneData); } else { - mSceneLength = stream->FileSize(); + mSceneLength = stream.FileSize(); mBodyLength = 0; // read the scene data @@ -1806,7 +1794,7 @@ inline void Asset::Load(const std::string &pFile, bool isBinary) { sceneData.resize(mSceneLength + 1); sceneData[mSceneLength] = '\0'; - if (stream->Read(&sceneData[0], 1, mSceneLength) != mSceneLength) { + if (stream.Read(&sceneData[0], 1, mSceneLength) != mSceneLength) { throw DeadlyImportError("GLTF: Could not read the file contents"); } } @@ -1826,6 +1814,42 @@ inline void Asset::Load(const std::string &pFile, bool isBinary) { throw DeadlyImportError("GLTF: JSON document root must be a JSON object"); } + return doc; +} + +inline void Asset::Load(const std::string &pFile, bool isBinary) +{ + mCurrentAssetDir.clear(); + /*int pos = std::max(int(pFile.rfind('/')), int(pFile.rfind('\\'))); + if (pos != int(std::string::npos)) */ + + if (0 != strncmp(pFile.c_str(), AI_MEMORYIO_MAGIC_FILENAME, AI_MEMORYIO_MAGIC_FILENAME_LENGTH)) { + mCurrentAssetDir = glTFCommon::getCurrentAssetDir(pFile); + } + + shared_ptr stream(OpenFile(pFile.c_str(), "rb", true)); + if (!stream) { + throw DeadlyImportError("GLTF: Could not open file for reading"); + } + + std::vector sceneData; + rapidjson::Document doc = ReadDocument(*stream, isBinary, sceneData); + + // If a schemaDocumentProvider is available, see if the glTF schema is present. + // If so, use it to validate the document. + if (mSchemaDocumentProvider) { + if (const rapidjson::SchemaDocument *gltfSchema = mSchemaDocumentProvider->GetRemoteDocument("glTF.schema.json", 16)) { + rapidjson::SchemaValidator validator(*gltfSchema); + if (!doc.Accept(validator)) { + rapidjson::StringBuffer pathBuffer; + validator.GetInvalidSchemaPointer().StringifyUriFragment(pathBuffer); + rapidjson::StringBuffer argumentBuffer; + validator.GetInvalidDocumentPointer().StringifyUriFragment(argumentBuffer); + throw DeadlyImportError("GLTF: The JSON document did not satisfy the glTF2 schema. Schema keyword: ", validator.GetInvalidSchemaKeyword(), ", document path: ", pathBuffer.GetString(), ", argument: ", argumentBuffer.GetString()); + } + } + } + // Fill the buffer instance for the current file embedded contents if (mBodyLength > 0) { if (!mBodyBuffer->LoadFromStream(*stream, mBodyLength, mBodyOffset)) { @@ -1882,6 +1906,25 @@ inline void Asset::Load(const std::string &pFile, bool isBinary) { } } +inline bool Asset::CanRead(const std::string &pFile, bool isBinary) +{ + try + { + shared_ptr stream(OpenFile(pFile.c_str(), "rb", true)); + if (!stream) { + return false; + } + std::vector sceneData; + rapidjson::Document doc = ReadDocument(*stream, isBinary, sceneData); + asset.Read(doc); + } + catch (...) + { + return false; + } + return true; +} + inline void Asset::SetAsBinary() { if (!mBodyBuffer) { mBodyBuffer = buffers.Create("binary_glTF"); diff --git a/code/AssetLib/glTF2/glTF2Importer.cpp b/code/AssetLib/glTF2/glTF2Importer.cpp index 6c92bdc87..02f07a935 100644 --- a/code/AssetLib/glTF2/glTF2Importer.cpp +++ b/code/AssetLib/glTF2/glTF2Importer.cpp @@ -111,19 +111,16 @@ const aiImporterDesc *glTF2Importer::GetInfo() const { return &desc; } -bool glTF2Importer::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /* checkSig */) const { - const std::string &extension = GetExtension(pFile); +bool glTF2Importer::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig ) const { + const std::string &extension = GetExtension(pFile); - if (extension != "gltf" && extension != "glb") { - return false; - } + if (!checkSig && (extension != "gltf") && (extension != "glb")) + return false; - if (pIOHandler) { - glTF2::Asset asset(pIOHandler); - asset.Load(pFile, extension == "glb"); - std::string version = asset.asset.version; - return !version.empty() && version[0] == '2'; - } + if (pIOHandler) { + glTF2::Asset asset(pIOHandler); + return asset.CanRead(pFile, extension == "glb"); + } return false; } @@ -1587,7 +1584,7 @@ void glTF2Importer::InternReadFile(const std::string &pFile, aiScene *pScene, IO this->mScene = pScene; // read the asset file - glTF2::Asset asset(pIOHandler); + glTF2::Asset asset(pIOHandler, static_cast(mSchemaDocumentProvider)); asset.Load(pFile, GetExtension(pFile) == "glb"); if (asset.scene) { pScene->mName = asset.scene->name; @@ -1613,4 +1610,8 @@ void glTF2Importer::InternReadFile(const std::string &pFile, aiScene *pScene, IO } } +void glTF2Importer::SetupProperties(const Importer *pImp) { + mSchemaDocumentProvider = static_cast(pImp->GetPropertyPointer(AI_CONFIG_IMPORT_SCHEMA_DOCUMENT_PROVIDER)); +} + #endif // ASSIMP_BUILD_NO_GLTF_IMPORTER diff --git a/code/AssetLib/glTF2/glTF2Importer.h b/code/AssetLib/glTF2/glTF2Importer.h index e586dc6cc..23830c0eb 100644 --- a/code/AssetLib/glTF2/glTF2Importer.h +++ b/code/AssetLib/glTF2/glTF2Importer.h @@ -65,6 +65,7 @@ public: protected: const aiImporterDesc *GetInfo() const override; void InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler) override; + virtual void SetupProperties(const Importer *pImp) override; private: void ImportEmbeddedTextures(glTF2::Asset &a); @@ -80,6 +81,9 @@ private: std::vector meshOffsets; std::vector embeddedTexIdxs; aiScene *mScene; + + /// An instance of rapidjson::IRemoteSchemaDocumentProvider + void *mSchemaDocumentProvider = nullptr; }; } // namespace Assimp diff --git a/code/Common/Importer.cpp b/code/Common/Importer.cpp index d0ed3c788..41b73fd12 100644 --- a/code/Common/Importer.cpp +++ b/code/Common/Importer.cpp @@ -1072,6 +1072,18 @@ bool Importer::SetPropertyMatrix(const char* szName, const aiMatrix4x4& value) { return existing; } +// ------------------------------------------------------------------------------------------------ +// Set a configuration property +bool Importer::SetPropertyPointer(const char* szName, void* value) { + ai_assert(nullptr != pimpl); + + bool existing; + ASSIMP_BEGIN_EXCEPTION_REGION(); + existing = SetGenericProperty(pimpl->mPointerProperties, szName,value); + ASSIMP_END_EXCEPTION_REGION(bool); + return existing; +} + // ------------------------------------------------------------------------------------------------ // Get a configuration property int Importer::GetPropertyInteger(const char* szName, int iErrorReturn /*= 0xffffffff*/) const { @@ -1104,6 +1116,14 @@ aiMatrix4x4 Importer::GetPropertyMatrix(const char* szName, const aiMatrix4x4& i return GetGenericProperty(pimpl->mMatrixProperties,szName,iErrorReturn); } +// ------------------------------------------------------------------------------------------------ +// Get a configuration property +void* Importer::GetPropertyPointer(const char* szName, void* iErrorReturn /*= nullptr*/) const { + ai_assert(nullptr != pimpl); + + return GetGenericProperty(pimpl->mPointerProperties,szName,iErrorReturn); +} + // ------------------------------------------------------------------------------------------------ // Get the memory requirements of a single node inline diff --git a/code/Common/Importer.h b/code/Common/Importer.h index 0e04f9452..f79b38214 100644 --- a/code/Common/Importer.h +++ b/code/Common/Importer.h @@ -73,12 +73,12 @@ public: // Data type to store the key hash typedef unsigned int KeyType; - // typedefs for our four configuration maps. - // We don't need more, so there is no need for a generic solution + // typedefs for our configuration maps. typedef std::map IntPropertyMap; typedef std::map FloatPropertyMap; typedef std::map StringPropertyMap; typedef std::map MatrixPropertyMap; + typedef std::map PointerPropertyMap; /** IO handler to use for all file accesses. */ IOSystem* mIOHandler; @@ -116,6 +116,9 @@ public: /** List of Matrix properties */ MatrixPropertyMap mMatrixProperties; + /** List of pointer properties */ + PointerPropertyMap mPointerProperties; + /** Used for testing - extra verbose mode causes the ValidateDataStructure-Step * to be executed before and after every single post-process step */ bool bExtraVerbose; @@ -142,6 +145,7 @@ ImporterPimpl::ImporterPimpl() AI_NO_EXCEPT : mFloatProperties(), mStringProperties(), mMatrixProperties(), + mPointerProperties(), bExtraVerbose( false ), mPPShared( nullptr ) { // empty diff --git a/include/assimp/Importer.hpp b/include/assimp/Importer.hpp index 09b5b6883..6ce327c4f 100644 --- a/include/assimp/Importer.hpp +++ b/include/assimp/Importer.hpp @@ -245,6 +245,12 @@ public: */ bool SetPropertyMatrix(const char *szName, const aiMatrix4x4 &sValue); + // ------------------------------------------------------------------- + /** Set a pointer configuration property. + * @see SetPropertyInteger() + */ + bool SetPropertyPointer(const char *szName, void *sValue); + // ------------------------------------------------------------------- /** Get a configuration property. * @param szName Name of the property. All supported properties @@ -297,6 +303,15 @@ public: aiMatrix4x4 GetPropertyMatrix(const char *szName, const aiMatrix4x4 &sErrorReturn = aiMatrix4x4()) const; + // ------------------------------------------------------------------- + /** Get a pointer configuration property + * + * The return value remains valid until the property is modified. + * @see GetPropertyInteger() + */ + void* GetPropertyPointer(const char *szName, + void *sErrorReturn = nullptr) const; + // ------------------------------------------------------------------- /** Supplies a custom IO handler to the importer to use to open and * access files. If you need the importer to use custom IO logic to diff --git a/include/assimp/config.h.in b/include/assimp/config.h.in index a89d4e837..bf0076572 100644 --- a/include/assimp/config.h.in +++ b/include/assimp/config.h.in @@ -547,6 +547,15 @@ enum aiComponent // Various stuff to fine-tune the behaviour of specific importer plugins. // ########################################################################### +// --------------------------------------------------------------------------- +/** @brief Importers which parse JSON may use this to obtain a pointer to a + * rapidjson::IRemoteSchemaDocumentProvider. + * + * The default value is nullptr + * Property type: void* + */ +#define AI_CONFIG_IMPORT_SCHEMA_DOCUMENT_PROVIDER \ + "IMPORT_SCHEMA_DOCUMENT_PROVIDER" // --------------------------------------------------------------------------- /** @brief Set whether the fbx importer will merge all geometry layers present From 7788c1a04ea6500f97aae257f80ff8bcb5230b1f Mon Sep 17 00:00:00 2001 From: Malcolm Tyrrell Date: Wed, 6 Oct 2021 15:46:48 +0100 Subject: [PATCH 02/10] Add a unit test for json schemas. --- test/CMakeLists.txt | 13 ++ .../glTF2/SchemaFailures/CesiumLogoFlat.png | Bin 0 -> 2433 bytes .../glTF2/SchemaFailures/sceneWrongType.gltf | 181 ++++++++++++++++++ test/unit/utglTF2ImportExport.cpp | 58 ++++++ 4 files changed, 252 insertions(+) create mode 100644 test/models/glTF2/SchemaFailures/CesiumLogoFlat.png create mode 100644 test/models/glTF2/SchemaFailures/sceneWrongType.gltf diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 6f28d4183..9c2cf3000 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -223,6 +223,19 @@ else() target_sources(unit PUBLIC ${Assimp_SOURCE_DIR}/contrib/gtest/src/gtest-all.cc) endif() +# RapidJSON +IF(ASSIMP_HUNTER_ENABLED) + hunter_add_package(RapidJSON) + find_package(RapidJSON CONFIG REQUIRED) +ELSE() + INCLUDE_DIRECTORIES("../contrib/rapidjson/include") + ADD_DEFINITIONS( -DRAPIDJSON_HAS_STDSTRING=1) + option( ASSIMP_RAPIDJSON_NO_MEMBER_ITERATOR "Suppress rapidjson warning on MSVC (NOTE: breaks android build)" ON ) + if(ASSIMP_RAPIDJSON_NO_MEMBER_ITERATOR) + ADD_DEFINITIONS( -DRAPIDJSON_NOMEMBERITERATORCLASS ) + endif() +ENDIF() + IF (ASSIMP_BUILD_DRACO) ADD_DEFINITIONS( -DASSIMP_ENABLE_DRACO ) ENDIF() diff --git a/test/models/glTF2/SchemaFailures/CesiumLogoFlat.png b/test/models/glTF2/SchemaFailures/CesiumLogoFlat.png new file mode 100644 index 0000000000000000000000000000000000000000..45d502ed2610974189307ad542b05b70df14abd4 GIT binary patch literal 2433 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 #include +#include #include @@ -772,3 +773,60 @@ TEST_F(utglTF2ImportExport, wrongTypes) { } } +namespace { + /// This class provides a fake schema to the GLTF importer. + /// It just checks that the file has a top-level "scene" property which is an integer. + class FakeSchemaProvider : public rapidjson::IRemoteSchemaDocumentProvider + { + public: + FakeSchemaProvider(const char* schemaName) : + m_schemaName(schemaName) + { + rapidjson::Document schemaDoc; + schemaDoc.Parse(R"==({"properties":{"scene" : { "type" : "integer" }}, "required": [ "scene" ]})=="); + EXPECT_FALSE(schemaDoc.HasParseError()); + m_schema = std::make_unique(schemaDoc, m_schemaName.c_str(), static_cast(m_schemaName.size()), this); + } + + const rapidjson::SchemaDocument* GetRemoteDocument(const char* uri, rapidjson::SizeType) override { + if (m_schemaName == uri) { + return m_schema.get(); + } + return nullptr; + } + + private: + std::string m_schemaName; + std::unique_ptr m_schema; + }; +} + +TEST_F(utglTF2ImportExport, schemaCheckPass) { + FakeSchemaProvider schemaProvider("glTF.schema.json"); + Assimp::Importer importer; + importer.SetPropertyPointer(AI_CONFIG_IMPORT_SCHEMA_DOCUMENT_PROVIDER, &schemaProvider); + const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/gltf2/BoxTextured-glTF/BoxTextured.gltf", aiProcess_ValidateDataStructure); + EXPECT_NE(scene, nullptr); + EXPECT_STREQ(importer.GetErrorString(), ""); +} + +TEST_F(utglTF2ImportExport, schemaCheckFail) { + FakeSchemaProvider schemaProvider("glTF.schema.json"); + Assimp::Importer importer; + importer.SetPropertyPointer(AI_CONFIG_IMPORT_SCHEMA_DOCUMENT_PROVIDER, &schemaProvider); + const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/gltf2/SchemaFailures/sceneWrongType.gltf", aiProcess_ValidateDataStructure); + EXPECT_EQ(scene, nullptr); + const std::string errorString = importer.GetErrorString(); + EXPECT_NE(errorString.find("The JSON document did not satisfy the glTF2 schema"), std::string::npos); +} + +TEST_F(utglTF2ImportExport, noSchemaFound) { + // More than one importer might make use the provider, but not all schemas might be present. + // Check that the glTF importer handles the case when an non-null provider returns null when asked for schemas. + FakeSchemaProvider schemaProvider("missingSchema.json"); + Assimp::Importer importer; + importer.SetPropertyPointer(AI_CONFIG_IMPORT_SCHEMA_DOCUMENT_PROVIDER, &schemaProvider); + const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/gltf2/BoxTextured-glTF/BoxTextured.gltf", aiProcess_ValidateDataStructure); + EXPECT_NE(scene, nullptr); + EXPECT_STREQ(importer.GetErrorString(), ""); +} From ceddfe19d89efdc0e10ecc459ed10d556d46b089 Mon Sep 17 00:00:00 2001 From: Malcolm Tyrrell Date: Wed, 6 Oct 2021 15:49:49 +0100 Subject: [PATCH 03/10] Add comment with link to schema repo. --- code/AssetLib/glTF2/glTF2Asset.inl | 1 + 1 file changed, 1 insertion(+) diff --git a/code/AssetLib/glTF2/glTF2Asset.inl b/code/AssetLib/glTF2/glTF2Asset.inl index b531b5a98..1dec86c0e 100644 --- a/code/AssetLib/glTF2/glTF2Asset.inl +++ b/code/AssetLib/glTF2/glTF2Asset.inl @@ -1839,6 +1839,7 @@ inline void Asset::Load(const std::string &pFile, bool isBinary) // If so, use it to validate the document. if (mSchemaDocumentProvider) { if (const rapidjson::SchemaDocument *gltfSchema = mSchemaDocumentProvider->GetRemoteDocument("glTF.schema.json", 16)) { + // The schemas are found here: https://github.com/KhronosGroup/glTF/tree/main/specification/2.0/schema rapidjson::SchemaValidator validator(*gltfSchema); if (!doc.Accept(validator)) { rapidjson::StringBuffer pathBuffer; From 5a1bcc6aa5b89d5ed7b9d94032bdd85627771208 Mon Sep 17 00:00:00 2001 From: Malcolm Tyrrell Date: Thu, 7 Oct 2021 09:29:56 +0100 Subject: [PATCH 04/10] Fix build and test --- test/unit/utglTF2ImportExport.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/unit/utglTF2ImportExport.cpp b/test/unit/utglTF2ImportExport.cpp index ed4c23547..288fa01a6 100644 --- a/test/unit/utglTF2ImportExport.cpp +++ b/test/unit/utglTF2ImportExport.cpp @@ -785,7 +785,7 @@ namespace { rapidjson::Document schemaDoc; schemaDoc.Parse(R"==({"properties":{"scene" : { "type" : "integer" }}, "required": [ "scene" ]})=="); EXPECT_FALSE(schemaDoc.HasParseError()); - m_schema = std::make_unique(schemaDoc, m_schemaName.c_str(), static_cast(m_schemaName.size()), this); + m_schema.reset(new rapidjson::SchemaDocument(schemaDoc, m_schemaName.c_str(), static_cast(m_schemaName.size()), this)); } const rapidjson::SchemaDocument* GetRemoteDocument(const char* uri, rapidjson::SizeType) override { @@ -805,7 +805,7 @@ TEST_F(utglTF2ImportExport, schemaCheckPass) { FakeSchemaProvider schemaProvider("glTF.schema.json"); Assimp::Importer importer; importer.SetPropertyPointer(AI_CONFIG_IMPORT_SCHEMA_DOCUMENT_PROVIDER, &schemaProvider); - const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/gltf2/BoxTextured-glTF/BoxTextured.gltf", aiProcess_ValidateDataStructure); + const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/glTF2/BoxTextured-glTF/BoxTextured.gltf", aiProcess_ValidateDataStructure); EXPECT_NE(scene, nullptr); EXPECT_STREQ(importer.GetErrorString(), ""); } @@ -814,7 +814,7 @@ TEST_F(utglTF2ImportExport, schemaCheckFail) { FakeSchemaProvider schemaProvider("glTF.schema.json"); Assimp::Importer importer; importer.SetPropertyPointer(AI_CONFIG_IMPORT_SCHEMA_DOCUMENT_PROVIDER, &schemaProvider); - const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/gltf2/SchemaFailures/sceneWrongType.gltf", aiProcess_ValidateDataStructure); + const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/glTF2/SchemaFailures/sceneWrongType.gltf", aiProcess_ValidateDataStructure); EXPECT_EQ(scene, nullptr); const std::string errorString = importer.GetErrorString(); EXPECT_NE(errorString.find("The JSON document did not satisfy the glTF2 schema"), std::string::npos); @@ -826,7 +826,7 @@ TEST_F(utglTF2ImportExport, noSchemaFound) { FakeSchemaProvider schemaProvider("missingSchema.json"); Assimp::Importer importer; importer.SetPropertyPointer(AI_CONFIG_IMPORT_SCHEMA_DOCUMENT_PROVIDER, &schemaProvider); - const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/gltf2/BoxTextured-glTF/BoxTextured.gltf", aiProcess_ValidateDataStructure); + const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/glTF2/BoxTextured-glTF/BoxTextured.gltf", aiProcess_ValidateDataStructure); EXPECT_NE(scene, nullptr); EXPECT_STREQ(importer.GetErrorString(), ""); } From 145f972d76eaf3cd947a92789ecefb4cc1b78765 Mon Sep 17 00:00:00 2001 From: Alex Rebert Date: Sat, 30 Oct 2021 13:43:41 -0400 Subject: [PATCH 05/10] Fix out-of-bounds read in RemoveLineComments Follow up to 6f07e89fdfb, which was not sufficient to fix the bug. Fix https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=24553 --- code/Common/RemoveComments.cpp | 22 +++++++--------------- 1 file changed, 7 insertions(+), 15 deletions(-) diff --git a/code/Common/RemoveComments.cpp b/code/Common/RemoveComments.cpp index 9974e985a..2de9666de 100644 --- a/code/Common/RemoveComments.cpp +++ b/code/Common/RemoveComments.cpp @@ -65,27 +65,19 @@ void CommentRemover::RemoveLineComments(const char* szComment, len = lenBuffer; } - char *szCurrent = szBuffer; - while (*szCurrent) { - + for(size_t i = 0; i < lenBuffer; i++) { // skip over quotes - if (*szCurrent == '\"' || *szCurrent == '\'') - while (*szCurrent++ && *szCurrent != '\"' && *szCurrent != '\''); + if (szBuffer[i] == '\"' || szBuffer[i] == '\'') + while (++i < lenBuffer && szBuffer[i] != '\"' && szBuffer[i] != '\''); - size_t lenRemaining = lenBuffer - (szCurrent - szBuffer); - if(lenRemaining < len) { + if(lenBuffer - i < len) { break; } - if (!strncmp(szCurrent,szComment,len)) { - while (!IsLineEnd(*szCurrent)) - *szCurrent++ = chReplacement; - - if (!*szCurrent) { - break; - } + if (!strncmp(szBuffer + i,szComment,len)) { + while (i < lenBuffer && !IsLineEnd(szBuffer[i])) + szBuffer[i++] = chReplacement; } - ++szCurrent; } } From 3b2a9d1543987354af2e88d7f83e0755a5fa726f Mon Sep 17 00:00:00 2001 From: kovacsv Date: Mon, 1 Nov 2021 08:09:16 +0100 Subject: [PATCH 06/10] Add assimpjs link. --- Readme.md | 1 + 1 file changed, 1 insertion(+) diff --git a/Readme.md b/Readme.md index 949d60966..09f9af7fa 100644 --- a/Readme.md +++ b/Readme.md @@ -42,6 +42,7 @@ Take a look into the https://github.com/assimp/assimp/blob/master/Build.md file. * [.NET](https://bitbucket.org/Starnick/assimpnet/src/master/) * [Pascal](port/AssimpPascal/Readme.md) * [Javascript (Alpha)](https://github.com/makc/assimp2json) +* [Javascript/Node.js Interface](https://github.com/kovacsv/assimpjs) * [Unity 3d Plugin](https://ricardoreis.net/trilib-2/) * [JVM](https://github.com/kotlin-graphics/assimp) Full jvm port (current [status](https://github.com/kotlin-graphics/assimp/wiki/Status)) * [HAXE-Port](https://github.com/longde123/assimp-haxe) The Assimp-HAXE-port. From ee19ce60219ed6b7604b89c3af4b09bff35e84bd Mon Sep 17 00:00:00 2001 From: RichardTea <31507749+RichardTea@users.noreply.github.com> Date: Mon, 8 Nov 2021 11:06:15 +0000 Subject: [PATCH 07/10] 3DS Export: Add support for aiShadingMode_PBR_BRDF Export as Phong. If no Diffuse texture, export the PBR base color instead, --- code/AssetLib/3DS/3DSExporter.cpp | 14 ++++++++++---- code/AssetLib/3DS/3DSExporter.h | 2 +- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/code/AssetLib/3DS/3DSExporter.cpp b/code/AssetLib/3DS/3DSExporter.cpp index d1059ae43..ea92fa12c 100644 --- a/code/AssetLib/3DS/3DSExporter.cpp +++ b/code/AssetLib/3DS/3DSExporter.cpp @@ -330,6 +330,7 @@ void Discreet3DSExporter::WriteMaterials() { case aiShadingMode_Blinn: case aiShadingMode_CookTorrance: case aiShadingMode_Fresnel: + case aiShadingMode_PBR_BRDF: // Possibly should be Discreet3DS::Metal in some cases but this is undocumented shading_mode_out = Discreet3DS::Phong; break; @@ -356,7 +357,10 @@ void Discreet3DSExporter::WriteMaterials() { writer.PutI2(1); } - WriteTexture(mat, aiTextureType_DIFFUSE, Discreet3DS::CHUNK_MAT_TEXTURE); + // Fallback to BASE_COLOR if no DIFFUSE + if (!WriteTexture(mat, aiTextureType_DIFFUSE, Discreet3DS::CHUNK_MAT_TEXTURE)) + WriteTexture(mat, aiTextureType_BASE_COLOR, Discreet3DS::CHUNK_MAT_TEXTURE); + WriteTexture(mat, aiTextureType_HEIGHT, Discreet3DS::CHUNK_MAT_BUMPMAP); WriteTexture(mat, aiTextureType_OPACITY, Discreet3DS::CHUNK_MAT_OPACMAP); WriteTexture(mat, aiTextureType_SHININESS, Discreet3DS::CHUNK_MAT_MAT_SHINMAP); @@ -367,20 +371,21 @@ void Discreet3DSExporter::WriteMaterials() { } // ------------------------------------------------------------------------------------------------ -void Discreet3DSExporter::WriteTexture(const aiMaterial &mat, aiTextureType type, uint16_t chunk_flags) { +// returns true if the texture existed +bool Discreet3DSExporter::WriteTexture(const aiMaterial &mat, aiTextureType type, uint16_t chunk_flags) { aiString path; aiTextureMapMode map_mode[2] = { aiTextureMapMode_Wrap, aiTextureMapMode_Wrap }; ai_real blend = 1.0; if (mat.GetTexture(type, 0, &path, nullptr, nullptr, &blend, nullptr, map_mode) != AI_SUCCESS || !path.length) { - return; + return false; } // TODO: handle embedded textures properly if (path.data[0] == '*') { ASSIMP_LOG_ERROR("Ignoring embedded texture for export: ", path.C_Str()); - return; + return false; } ChunkWriter chunk(writer, chunk_flags); @@ -402,6 +407,7 @@ void Discreet3DSExporter::WriteTexture(const aiMaterial &mat, aiTextureType type writer.PutU2(val); } // TODO: export texture transformation (i.e. UV offset, scale, rotation) + return true; } // ------------------------------------------------------------------------------------------------ diff --git a/code/AssetLib/3DS/3DSExporter.h b/code/AssetLib/3DS/3DSExporter.h index c48ecb2fc..8ac3da98c 100644 --- a/code/AssetLib/3DS/3DSExporter.h +++ b/code/AssetLib/3DS/3DSExporter.h @@ -73,7 +73,7 @@ public: private: void WriteMeshes(); void WriteMaterials(); - void WriteTexture(const aiMaterial& mat, aiTextureType type, uint16_t chunk_flags); + bool WriteTexture(const aiMaterial& mat, aiTextureType type, uint16_t chunk_flags); void WriteFaceMaterialChunk(const aiMesh& mesh); int WriteHierarchy(const aiNode& node, int level, int sibling_level); void WriteString(const std::string& s); From 97b8e41997160f2113e1e6fcde230ccb857167af Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Fri, 12 Nov 2021 09:56:45 +0100 Subject: [PATCH 08/10] Fix formatting --- code/Common/RemoveComments.cpp | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/code/Common/RemoveComments.cpp b/code/Common/RemoveComments.cpp index 2de9666de..e9e2a6ade 100644 --- a/code/Common/RemoveComments.cpp +++ b/code/Common/RemoveComments.cpp @@ -4,7 +4,6 @@ Open Asset Import Library (assimp) Copyright (c) 2006-2021, assimp team - All rights reserved. Redistribution and use of this software in source and binary forms, @@ -40,20 +39,19 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ---------------------------------------------------------------------- */ -/** @file RemoveComments.cpp +/** + * @file RemoveComments.cpp * @brief Defines the CommentRemover utility class */ #include #include -namespace Assimp { +namespace Assimp { // ------------------------------------------------------------------------------------------------ // Remove line comments from a file -void CommentRemover::RemoveLineComments(const char* szComment, - char* szBuffer, char chReplacement /* = ' ' */) -{ +void CommentRemover::RemoveLineComments(const char* szComment, char* szBuffer, char chReplacement /* = ' ' */) { // validate parameters ai_assert(nullptr != szComment); ai_assert(nullptr != szBuffer); @@ -75,8 +73,9 @@ void CommentRemover::RemoveLineComments(const char* szComment, } if (!strncmp(szBuffer + i,szComment,len)) { - while (i < lenBuffer && !IsLineEnd(szBuffer[i])) + while (i < lenBuffer && !IsLineEnd(szBuffer[i])) { szBuffer[i++] = chReplacement; + } } } } @@ -84,9 +83,8 @@ void CommentRemover::RemoveLineComments(const char* szComment, // ------------------------------------------------------------------------------------------------ // Remove multi-line comments from a file void CommentRemover::RemoveMultiLineComments(const char* szCommentStart, - const char* szCommentEnd,char* szBuffer, - char chReplacement) -{ + const char* szCommentEnd,char* szBuffer, + char chReplacement) { // validate parameters ai_assert(nullptr != szCommentStart); ai_assert(nullptr != szCommentEnd); @@ -99,18 +97,20 @@ void CommentRemover::RemoveMultiLineComments(const char* szCommentStart, while (*szBuffer) { // skip over quotes - if (*szBuffer == '\"' || *szBuffer == '\'') + if (*szBuffer == '\"' || *szBuffer == '\'') { while (*szBuffer++ && *szBuffer != '\"' && *szBuffer != '\''); + } if (!strncmp(szBuffer,szCommentStart,len2)) { while (*szBuffer) { if (!::strncmp(szBuffer,szCommentEnd,len)) { - for (unsigned int i = 0; i < len;++i) + for (unsigned int i = 0; i < len;++i) { *szBuffer++ = chReplacement; + } break; } - *szBuffer++ = chReplacement; + *szBuffer++ = chReplacement; } continue; } From 157e032bde9bb0e079c69760a5dc1f401522e7b5 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Fri, 12 Nov 2021 11:08:19 +0100 Subject: [PATCH 09/10] Fix small findings - Merge anonymous functions into one block. - Some reformattings --- code/AssetLib/glTF2/glTF2Asset.inl | 186 +++++++++++++---------------- 1 file changed, 84 insertions(+), 102 deletions(-) diff --git a/code/AssetLib/glTF2/glTF2Asset.inl b/code/AssetLib/glTF2/glTF2Asset.inl index c649708f3..242553031 100644 --- a/code/AssetLib/glTF2/glTF2Asset.inl +++ b/code/AssetLib/glTF2/glTF2Asset.inl @@ -90,7 +90,6 @@ namespace { // // JSON Value reading helpers // - inline CustomExtension ReadExtensions(const char *name, Value &obj) { CustomExtension ret; ret.name = name; @@ -127,6 +126,80 @@ inline CustomExtension ReadExtensions(const char *name, Value &obj) { return ret; } +inline void CopyData(size_t count, const uint8_t *src, size_t src_stride, + uint8_t *dst, size_t dst_stride) { + if (src_stride == dst_stride) { + memcpy(dst, src, count * src_stride); + return; + + size_t sz = std::min(src_stride, dst_stride); + for (size_t i = 0; i < count; ++i) { + memcpy(dst, src, sz); + if (sz < dst_stride) { + memset(dst + sz, 0, dst_stride - sz); + } + src += src_stride; + dst += dst_stride; + } +} + +void SetVector(vec4 &v, const float (&in)[4]) { + v[0] = in[0]; + v[1] = in[1]; + v[2] = in[2]; + v[3] = in[3]; +} + +void SetVector(vec3 &v, const float (&in)[3]) { + v[0] = in[0]; + v[1] = in[1]; + v[2] = in[2]; +} + +template +inline int Compare(const char *attr, const char (&str)[N]) { + return (strncmp(attr, str, N - 1) == 0) ? N - 1 : 0; +} + +#if _MSC_VER +#pragma warning(push) +#pragma warning(disable : 4706) +#endif // _MSC_VER + +inline bool GetAttribVector(Mesh::Primitive &p, const char *attr, Mesh::AccessorList *&v, int &pos) { + if ((pos = Compare(attr, "POSITION"))) { + v = &(p.attributes.position); + } else if ((pos = Compare(attr, "NORMAL"))) { + v = &(p.attributes.normal); + } else if ((pos = Compare(attr, "TANGENT"))) { + v = &(p.attributes.tangent); + } else if ((pos = Compare(attr, "TEXCOORD"))) { + v = &(p.attributes.texcoord); + } else if ((pos = Compare(attr, "COLOR"))) { + v = &(p.attributes.color); + } else if ((pos = Compare(attr, "JOINT"))) { + v = &(p.attributes.joint); + } else if ((pos = Compare(attr, "JOINTMATRIX"))) { + v = &(p.attributes.jointmatrix); + } else if ((pos = Compare(attr, "WEIGHT"))) { + v = &(p.attributes.weight); + } else + return false; + return true; +} + +inline bool GetAttribTargetVector(Mesh::Primitive &p, const int targetIndex, const char *attr, Mesh::AccessorList *&v, int &pos) { + if ((pos = Compare(attr, "POSITION"))) { + v = &(p.targets[targetIndex].position); + } else if ((pos = Compare(attr, "NORMAL"))) { + v = &(p.targets[targetIndex].normal); + } else if ((pos = Compare(attr, "TANGENT"))) { + v = &(p.targets[targetIndex].tangent); + } else + return false; + return true; +} + } // namespace inline Value *Object::FindString(Value &val, const char *memberId) { @@ -456,7 +529,6 @@ Ref LazyDict::Create(const char *id) { // // glTF dictionary objects methods // - inline Buffer::Buffer() : byteLength(0), type(Type_arraybuffer), @@ -865,27 +937,6 @@ inline size_t Accessor::GetMaxByteSize() { return (bufferView ? bufferView->byteLength : sparse->data.size()); } -namespace { -inline void CopyData(size_t count, - const uint8_t *src, size_t src_stride, - uint8_t *dst, size_t dst_stride) { - if (src_stride == dst_stride) { - memcpy(dst, src, count * src_stride); - } else { - size_t sz = std::min(src_stride, dst_stride); - for (size_t i = 0; i < count; ++i) { - memcpy(dst, src, sz); - if (sz < dst_stride) { - memset(dst + sz, 0, dst_stride - sz); - } - src += src_stride; - dst += dst_stride; - } - } -} - -} // namespace - template void Accessor::ExtractData(T *&outData) { uint8_t *data = GetPointer(); @@ -959,11 +1010,12 @@ inline void Accessor::WriteSparseIndices(size_t _count, const void *src_idx, siz ai_assert(indices_dst + _count * indices_dst_stride <= indices_buffer_ptr + sparse->indices->buffer->byteLength); CopyData(_count, indices_src, src_idxStride, indices_dst, indices_dst_stride); } + inline Accessor::Indexer::Indexer(Accessor &acc) : - accessor(acc), - data(acc.GetPointer()), - elemSize(acc.GetElementSize()), - stride(acc.GetStride()) { + accessor(acc), + data(acc.GetPointer()), + elemSize(acc.GetElementSize()), + stride(acc.GetStride()) { } //! Accesses the i-th value as defined by the accessor @@ -1241,21 +1293,6 @@ inline void Material::Read(Value &material, Asset &r) { } } -namespace { -void SetVector(vec4 &v, const float (&in)[4]) { - v[0] = in[0]; - v[1] = in[1]; - v[2] = in[2]; - v[3] = in[3]; -} - -void SetVector(vec3 &v, const float (&in)[3]) { - v[0] = in[0]; - v[1] = in[1]; - v[2] = in[2]; -} -} // namespace - inline void Material::SetDefaults() { //pbr materials SetVector(pbrMetallicRoughness.baseColorFactor, defaultBaseColor); @@ -1294,53 +1331,6 @@ inline void MaterialIOR::SetDefaults() { ior = 1.5f; } -namespace { - -template -inline int Compare(const char *attr, const char (&str)[N]) { - return (strncmp(attr, str, N - 1) == 0) ? N - 1 : 0; -} - -#if _MSC_VER -#pragma warning(push) -#pragma warning(disable : 4706) -#endif // _MSC_VER - -inline bool GetAttribVector(Mesh::Primitive &p, const char *attr, Mesh::AccessorList *&v, int &pos) { - if ((pos = Compare(attr, "POSITION"))) { - v = &(p.attributes.position); - } else if ((pos = Compare(attr, "NORMAL"))) { - v = &(p.attributes.normal); - } else if ((pos = Compare(attr, "TANGENT"))) { - v = &(p.attributes.tangent); - } else if ((pos = Compare(attr, "TEXCOORD"))) { - v = &(p.attributes.texcoord); - } else if ((pos = Compare(attr, "COLOR"))) { - v = &(p.attributes.color); - } else if ((pos = Compare(attr, "JOINT"))) { - v = &(p.attributes.joint); - } else if ((pos = Compare(attr, "JOINTMATRIX"))) { - v = &(p.attributes.jointmatrix); - } else if ((pos = Compare(attr, "WEIGHT"))) { - v = &(p.attributes.weight); - } else - return false; - return true; -} - -inline bool GetAttribTargetVector(Mesh::Primitive &p, const int targetIndex, const char *attr, Mesh::AccessorList *&v, int &pos) { - if ((pos = Compare(attr, "POSITION"))) { - v = &(p.targets[targetIndex].position); - } else if ((pos = Compare(attr, "NORMAL"))) { - v = &(p.targets[targetIndex].normal); - } else if ((pos = Compare(attr, "TANGENT"))) { - v = &(p.targets[targetIndex].tangent); - } else - return false; - return true; -} -} // namespace - inline void Mesh::Read(Value &pJSON_Object, Asset &pAsset_Root) { Value *curName = FindMember(pJSON_Object, "name"); if (nullptr != curName && curName->IsString()) { @@ -1811,8 +1801,7 @@ inline void Asset::ReadBinaryHeader(IOStream &stream, std::vector &sceneDa } } -inline rapidjson::Document Asset::ReadDocument(IOStream &stream, bool isBinary, std::vector &sceneData) -{ +inline rapidjson::Document Asset::ReadDocument(IOStream &stream, bool isBinary, std::vector &sceneData) { ASSIMP_LOG_DEBUG("Loading GLTF2 asset"); // is binary? then read the header @@ -1863,9 +1852,6 @@ inline rapidjson::Document Asset::ReadDocument(IOStream &stream, bool isBinary, inline void Asset::Load(const std::string &pFile, bool isBinary) { mCurrentAssetDir.clear(); - /*int pos = std::max(int(pFile.rfind('/')), int(pFile.rfind('\\'))); - if (pos != int(std::string::npos)) */ - if (0 != strncmp(pFile.c_str(), AI_MEMORYIO_MAGIC_FILENAME, AI_MEMORYIO_MAGIC_FILENAME_LENGTH)) { mCurrentAssetDir = glTFCommon::getCurrentAssetDir(pFile); } @@ -1950,10 +1936,8 @@ inline void Asset::Load(const std::string &pFile, bool isBinary) } } -inline bool Asset::CanRead(const std::string &pFile, bool isBinary) -{ - try - { +inline bool Asset::CanRead(const std::string &pFile, bool isBinary) { + try { shared_ptr stream(OpenFile(pFile.c_str(), "rb", true)); if (!stream) { return false; @@ -1961,9 +1945,7 @@ inline bool Asset::CanRead(const std::string &pFile, bool isBinary) std::vector sceneData; rapidjson::Document doc = ReadDocument(*stream, isBinary, sceneData); asset.Read(doc); - } - catch (...) - { + } catch (...) { return false; } return true; @@ -2069,7 +2051,7 @@ inline std::string Asset::FindUniqueID(const std::string &str, const char *suffi } #if _MSC_VER -#pragma warning(pop) +# pragma warning(pop) #endif // _MSC_VER } // namespace glTF2 From e2ccd174949e350103e343ee5ba0f49a0a47ff19 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Fri, 12 Nov 2021 11:20:22 +0100 Subject: [PATCH 10/10] Fix typo --- code/AssetLib/glTF2/glTF2Asset.inl | 1 + 1 file changed, 1 insertion(+) diff --git a/code/AssetLib/glTF2/glTF2Asset.inl b/code/AssetLib/glTF2/glTF2Asset.inl index 242553031..b570fc8e6 100644 --- a/code/AssetLib/glTF2/glTF2Asset.inl +++ b/code/AssetLib/glTF2/glTF2Asset.inl @@ -131,6 +131,7 @@ inline void CopyData(size_t count, const uint8_t *src, size_t src_stride, if (src_stride == dst_stride) { memcpy(dst, src, count * src_stride); return; + } size_t sz = std::min(src_stride, dst_stride); for (size_t i = 0; i < count; ++i) {