diff --git a/.github/workflows/sanitizer.yml b/.github/workflows/sanitizer.yml index b23f4520f..483ee8fc1 100644 --- a/.github/workflows/sanitizer.yml +++ b/.github/workflows/sanitizer.yml @@ -46,7 +46,7 @@ jobs: CC: clang - name: configure and build - uses: lukka/run-cmake@v2 + uses: lukka/run-cmake@v3 with: cmakeListsOrSettingsJson: CMakeListsTxtAdvanced cmakeListsTxtPath: '${{ github.workspace }}/CMakeLists.txt' diff --git a/CMakeLists.txt b/CMakeLists.txt index 224f6e48f..dfaa2b791 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -286,9 +286,9 @@ IF ((CMAKE_C_COMPILER_ID MATCHES "GNU") AND NOT MINGW) ELSEIF(MSVC) # enable multi-core compilation with MSVC IF(CMAKE_CXX_COMPILER_ID MATCHES "Clang" ) # clang-cl - ADD_COMPILE_OPTIONS(/bigobj /W4 /WX ) + ADD_COMPILE_OPTIONS(/bigobj) ELSE() # msvc - ADD_COMPILE_OPTIONS(/MP /bigobj /W4 /WX) + ADD_COMPILE_OPTIONS(/MP /bigobj) ENDIF() # disable "elements of array '' will be default initialized" warning on MSVC2013 diff --git a/code/AssetLib/FBX/FBXConverter.cpp b/code/AssetLib/FBX/FBXConverter.cpp index 51ec79583..498da43ca 100644 --- a/code/AssetLib/FBX/FBXConverter.cpp +++ b/code/AssetLib/FBX/FBXConverter.cpp @@ -93,6 +93,8 @@ FBXConverter::FBXConverter(aiScene *out, const Document &doc, bool removeEmptyBo mSceneOut(out), doc(doc), mRemoveEmptyBones(removeEmptyBones) { + + // animations need to be converted first since this will // populate the node_anim_chain_bits map, which is needed // to determine which nodes need to be generated. @@ -427,12 +429,26 @@ void FBXConverter::ConvertCamera(const Camera &cam, const std::string &orig_name out_camera->mLookAt = aiVector3D(1.0f, 0.0f, 0.0f); out_camera->mUp = aiVector3D(0.0f, 1.0f, 0.0f); - out_camera->mHorizontalFOV = AI_DEG_TO_RAD(cam.FieldOfView()); + // NOTE: Some software (maya) does not put FieldOfView in FBX, so we compute + // mHorizontalFOV from FocalLength and FilmWidth with unit conversion. - out_camera->mClipPlaneNear = cam.NearPlane(); - out_camera->mClipPlaneFar = cam.FarPlane(); + // TODO: This is not a complete solution for how FBX cameras can be stored. + // TODO: Incorporate non-square pixel aspect ratio. + // TODO: FBX aperture mode might be storing vertical FOV in need of conversion with aspect ratio. + + float fov_deg = cam.FieldOfView(); + // If FOV not specified in file, compute using FilmWidth and FocalLength. + if (fov_deg == kFovUnknown) { + float film_width_inches = cam.FilmWidth(); + float focal_length_mm = cam.FocalLength(); + ASSIMP_LOG_VERBOSE_DEBUG("FBX FOV unspecified. Computing from FilmWidth (", film_width_inches, "inches) and FocalLength (", focal_length_mm, "mm)."); + double half_fov_rad = std::atan2(film_width_inches * 25.4 * 0.5, focal_length_mm); + out_camera->mHorizontalFOV = static_cast(half_fov_rad); + } else { + // FBX fov is full-view degrees. We want half-view radians. + out_camera->mHorizontalFOV = AI_DEG_TO_RAD(fov_deg) * 0.5f; + } - out_camera->mHorizontalFOV = AI_DEG_TO_RAD(cam.FieldOfView()); out_camera->mClipPlaneNear = cam.NearPlane(); out_camera->mClipPlaneFar = cam.FarPlane(); } diff --git a/code/AssetLib/FBX/FBXDocument.h b/code/AssetLib/FBX/FBXDocument.h index e229eef52..3af757a19 100644 --- a/code/AssetLib/FBX/FBXDocument.h +++ b/code/AssetLib/FBX/FBXDocument.h @@ -55,9 +55,14 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define _AI_CONCAT(a,b) a ## b #define AI_CONCAT(a,b) _AI_CONCAT(a,b) + namespace Assimp { namespace FBX { +// Use an 'illegal' default FOV value to detect if the FBX camera has set the FOV. +static const float kFovUnknown = -1.0f; + + class Parser; class Object; struct ImportSettings; @@ -247,7 +252,7 @@ public: fbx_simple_property(FilmAspectRatio, float, 1.0f) fbx_simple_property(ApertureMode, int, 0) - fbx_simple_property(FieldOfView, float, 1.0f) + fbx_simple_property(FieldOfView, float, kFovUnknown) fbx_simple_property(FocalLength, float, 1.0f) }; diff --git a/code/AssetLib/FBX/FBXParser.cpp b/code/AssetLib/FBX/FBXParser.cpp index c7b579665..955e811cb 100644 --- a/code/AssetLib/FBX/FBXParser.cpp +++ b/code/AssetLib/FBX/FBXParser.cpp @@ -211,7 +211,7 @@ Scope::Scope(Parser& parser,bool topLevel) elements.insert(ElementMap::value_type(str, element)); return; } - delete element; + delete_Element(element); ParseError("unexpected end of file",parser.LastToken()); } else { elements.insert(ElementMap::value_type(str, element)); diff --git a/code/AssetLib/MDL/MDLLoader.cpp b/code/AssetLib/MDL/MDLLoader.cpp index 098b53e76..7b2ec7115 100644 --- a/code/AssetLib/MDL/MDLLoader.cpp +++ b/code/AssetLib/MDL/MDLLoader.cpp @@ -271,10 +271,16 @@ void MDLImporter::InternReadFile(const std::string &pFile, } } +// ------------------------------------------------------------------------------------------------ +// Check whether we're still inside the valid file range +bool MDLImporter::IsPosValid(const void *szPos) const { + return szPos && (const unsigned char *)szPos <= this->mBuffer + this->iFileSize && szPos >= this->mBuffer; +} + // ------------------------------------------------------------------------------------------------ // Check whether we're still inside the valid file range void MDLImporter::SizeCheck(const void *szPos) { - if (!szPos || (const unsigned char *)szPos > this->mBuffer + this->iFileSize || szPos < this->mBuffer) { + if (!IsPosValid(szPos)) { throw DeadlyImportError("Invalid MDL file. The file is too small " "or contains invalid data."); } @@ -284,7 +290,7 @@ void MDLImporter::SizeCheck(const void *szPos) { // Just for debugging purposes void MDLImporter::SizeCheck(const void *szPos, const char *szFile, unsigned int iLine) { ai_assert(nullptr != szFile); - if (!szPos || (const unsigned char *)szPos > mBuffer + iFileSize) { + if (!IsPosValid(szPos)) { // remove a directory if there is one const char *szFilePtr = ::strrchr(szFile, '\\'); if (!szFilePtr) { diff --git a/code/AssetLib/MDL/MDLLoader.h b/code/AssetLib/MDL/MDLLoader.h index 433100938..44ff21e3e 100644 --- a/code/AssetLib/MDL/MDLLoader.h +++ b/code/AssetLib/MDL/MDLLoader.h @@ -150,6 +150,7 @@ protected: */ void SizeCheck(const void* szPos); void SizeCheck(const void* szPos, const char* szFile, unsigned int iLine); + bool IsPosValid(const void* szPos) const; // ------------------------------------------------------------------- /** Validate the header data structure of a game studio MDL7 file diff --git a/code/AssetLib/NDO/NDOLoader.cpp b/code/AssetLib/NDO/NDOLoader.cpp index bf2fa113d..edccc1624 100644 --- a/code/AssetLib/NDO/NDOLoader.cpp +++ b/code/AssetLib/NDO/NDOLoader.cpp @@ -52,6 +52,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include +#include using namespace Assimp; @@ -160,6 +161,9 @@ void NDOImporter::InternReadFile( const std::string& pFile, temp = file_format >= 12 ? reader.GetU4() : reader.GetU2(); head = (const char*)reader.GetPtr(); + if (std::numeric_limits::max() - 76 < temp) { + throw DeadlyImportError("Invalid name length"); + } reader.IncPtr(temp + 76); /* skip unknown stuff */ obj.name = std::string(head, temp); diff --git a/code/AssetLib/glTF2/glTF2Asset.inl b/code/AssetLib/glTF2/glTF2Asset.inl index 227f3878c..53ffdaf31 100644 --- a/code/AssetLib/glTF2/glTF2Asset.inl +++ b/code/AssetLib/glTF2/glTF2Asset.inl @@ -45,6 +45,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include +#include +#include +#include // clang-format off #ifdef ASSIMP_ENABLE_DRACO diff --git a/code/AssetLib/glTF2/glTF2Exporter.cpp b/code/AssetLib/glTF2/glTF2Exporter.cpp index f7fa9cd42..d4568fa31 100644 --- a/code/AssetLib/glTF2/glTF2Exporter.cpp +++ b/code/AssetLib/glTF2/glTF2Exporter.cpp @@ -730,7 +730,7 @@ bool glTF2Exporter::GetMatSpecGloss(const aiMaterial &mat, glTF2::PbrSpecularGlo bool glTF2Exporter::GetMatSpecular(const aiMaterial &mat, glTF2::MaterialSpecular &specular) { // Specular requires either/or, default factors of zero disables specular, so do not export - if (GetMatColor(mat, specular.specularColorFactor, AI_MATKEY_COLOR_SPECULAR) != AI_SUCCESS || mat.Get(AI_MATKEY_SPECULAR_FACTOR, specular.specularFactor) != AI_SUCCESS) { + if (GetMatColor(mat, specular.specularColorFactor, AI_MATKEY_COLOR_SPECULAR) != AI_SUCCESS && mat.Get(AI_MATKEY_SPECULAR_FACTOR, specular.specularFactor) != AI_SUCCESS) { return false; } // The spec states that the default is 1.0 and [1.0, 1.0, 1.0]. We if both are 0, which should disable specular. Otherwise, if one is 0, set to 1.0 diff --git a/code/AssetLib/glTF2/glTF2Importer.cpp b/code/AssetLib/glTF2/glTF2Importer.cpp index 86fd0ab7e..0fed11cef 100644 --- a/code/AssetLib/glTF2/glTF2Importer.cpp +++ b/code/AssetLib/glTF2/glTF2Importer.cpp @@ -234,7 +234,8 @@ inline void SetMaterialTextureProperty(std::vector &embeddedTexIdxs, Asset SetMaterialTextureProperty(embeddedTexIdxs, r, (glTF2::TextureInfo)prop, mat, texType, texSlot); if (prop.texture && prop.texture->source) { - mat->AddProperty(&prop.strength, 1, AI_MATKEY_GLTF_TEXTURE_STRENGTH(texType, texSlot)); + std::string textureStrengthKey = std::string(_AI_MATKEY_TEXTURE_BASE) + "." + "strength"; + mat->AddProperty(&prop.strength, 1, textureStrengthKey.c_str(), texType, texSlot); } } diff --git a/code/CMakeLists.txt b/code/CMakeLists.txt index f7aa847bc..08a79ef19 100644 --- a/code/CMakeLists.txt +++ b/code/CMakeLists.txt @@ -1418,25 +1418,29 @@ if(MSVC AND ASSIMP_INSTALL_PDB) COMPILE_PDB_NAME assimp${LIBRARY_SUFFIX} COMPILE_PDB_NAME_DEBUG assimp${LIBRARY_SUFFIX}${CMAKE_DEBUG_POSTFIX} ) - ENDIF() - IF(CMAKE_GENERATOR MATCHES "^Visual Studio") - install(FILES ${Assimp_BINARY_DIR}/code/Debug/assimp${LIBRARY_SUFFIX}${CMAKE_DEBUG_POSTFIX}.pdb - DESTINATION ${ASSIMP_LIB_INSTALL_DIR} - CONFIGURATIONS Debug - ) - install(FILES ${Assimp_BINARY_DIR}/code/RelWithDebInfo/assimp${LIBRARY_SUFFIX}.pdb - DESTINATION ${ASSIMP_LIB_INSTALL_DIR} - CONFIGURATIONS RelWithDebInfo - ) + IF(GENERATOR_IS_MULTI_CONFIG) + install(FILES ${Assimp_BINARY_DIR}/code/Debug/assimp${LIBRARY_SUFFIX}${CMAKE_DEBUG_POSTFIX}.pdb + DESTINATION ${ASSIMP_LIB_INSTALL_DIR} + CONFIGURATIONS Debug + ) + install(FILES ${Assimp_BINARY_DIR}/code/RelWithDebInfo/assimp${LIBRARY_SUFFIX}.pdb + DESTINATION ${ASSIMP_LIB_INSTALL_DIR} + CONFIGURATIONS RelWithDebInfo + ) + ELSE() + install(FILES ${Assimp_BINARY_DIR}/code/assimp${LIBRARY_SUFFIX}${CMAKE_DEBUG_POSTFIX}.pdb + DESTINATION ${ASSIMP_LIB_INSTALL_DIR} + CONFIGURATIONS Debug + ) + install(FILES ${Assimp_BINARY_DIR}/code/assimp${LIBRARY_SUFFIX}.pdb + DESTINATION ${ASSIMP_LIB_INSTALL_DIR} + CONFIGURATIONS RelWithDebInfo + ) + ENDIF() ELSE() - install(FILES ${Assimp_BINARY_DIR}/code/assimp${LIBRARY_SUFFIX}${CMAKE_DEBUG_POSTFIX}.pdb + install(FILES $ DESTINATION ${ASSIMP_LIB_INSTALL_DIR} - CONFIGURATIONS Debug - ) - install(FILES ${Assimp_BINARY_DIR}/code/assimp${LIBRARY_SUFFIX}.pdb - DESTINATION ${ASSIMP_LIB_INSTALL_DIR} - CONFIGURATIONS RelWithDebInfo ) ENDIF() ENDIF () diff --git a/code/Common/BaseImporter.cpp b/code/Common/BaseImporter.cpp index 87b385268..a169c8a10 100644 --- a/code/Common/BaseImporter.cpp +++ b/code/Common/BaseImporter.cpp @@ -59,6 +59,31 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include +namespace { +// Checks whether the passed string is a gcs version. +bool IsGcsVersion(const std::string &s) { + if (s.empty()) return false; + return std::all_of(s.cbegin(), s.cend(), [](const char c) { + // gcs only permits numeric characters. + return std::isdigit(static_cast(c)); + }); +} + +// Removes a possible version hash from a filename, as found for example in +// gcs uris (e.g. `gs://bucket/model.glb#1234`), see also +// https://github.com/GoogleCloudPlatform/gsutil/blob/c80f329bc3c4011236c78ce8910988773b2606cb/gslib/storage_url.py#L39. +std::string StripVersionHash(const std::string &filename) { + const std::string::size_type pos = filename.find_last_of('#'); + // Only strip if the hash is behind a possible file extension and the part + // behind the hash is a version string. + if (pos != std::string::npos && pos > filename.find_last_of('.') && + IsGcsVersion(filename.substr(pos + 1))) { + return filename.substr(0, pos); + } + return filename; +} +} // namespace + using namespace Assimp; // ------------------------------------------------------------------------------------------------ @@ -158,7 +183,7 @@ void BaseImporter::GetExtensionList(std::set &extensions) { std::size_t numTokens, unsigned int searchBytes /* = 200 */, bool tokensSol /* false */, - bool noAlphaBeforeTokens /* false */) { + bool noGraphBeforeTokens /* false */) { ai_assert(nullptr != tokens); ai_assert(0 != numTokens); ai_assert(0 != searchBytes); @@ -207,8 +232,9 @@ void BaseImporter::GetExtensionList(std::set &extensions) { continue; } // We need to make sure that we didn't accidentally identify the end of another token as our token, - // e.g. in a previous version the "gltf " present in some gltf files was detected as "f " - if (noAlphaBeforeTokens && (r != buffer && isalpha(static_cast(r[-1])))) { + // e.g. in a previous version the "gltf " present in some gltf files was detected as "f ", or a + // Blender-exported glb file containing "Khronos glTF Blender I/O " was detected as "o " + if (noGraphBeforeTokens && (r != buffer && isgraph(static_cast(r[-1])))) { continue; } // We got a match, either we don't care where it is, or it happens to @@ -229,33 +255,38 @@ void BaseImporter::GetExtensionList(std::set &extensions) { const char *ext0, const char *ext1, const char *ext2) { - std::string::size_type pos = pFile.find_last_of('.'); - - // no file extension - can't read - if (pos == std::string::npos) { - return false; + std::set extensions; + for (const char* ext : {ext0, ext1, ext2}) { + if (ext == nullptr) continue; + extensions.emplace(ext); } + return HasExtension(pFile, extensions); +} - const char *ext_real = &pFile[pos + 1]; - if (!ASSIMP_stricmp(ext_real, ext0)) { - return true; +// ------------------------------------------------------------------------------------------------ +// Check for file extension +/*static*/ bool BaseImporter::HasExtension(const std::string &pFile, const std::set &extensions) { + const std::string file = StripVersionHash(pFile); + // CAUTION: Do not just search for the extension! + // GetExtension() returns the part after the *last* dot, but some extensions + // have dots inside them, e.g. ogre.mesh.xml. Compare the entire end of the + // string. + for (const std::string& ext : extensions) { + // Yay for C++<20 not having std::string::ends_with() + const std::string dotExt = "." + ext; + if (dotExt.length() > file.length()) continue; + // Possible optimization: Fetch the lowercase filename! + if (0 == ASSIMP_stricmp(file.c_str() + file.length() - dotExt.length(), dotExt.c_str())) { + return true; + } } - - // check for other, optional, file extensions - if (ext1 && !ASSIMP_stricmp(ext_real, ext1)) { - return true; - } - - if (ext2 && !ASSIMP_stricmp(ext_real, ext2)) { - return true; - } - return false; } // ------------------------------------------------------------------------------------------------ // Get file extension from path -std::string BaseImporter::GetExtension(const std::string &file) { +std::string BaseImporter::GetExtension(const std::string &pFile) { + const std::string file = StripVersionHash(pFile); std::string::size_type pos = file.find_last_of('.'); // no file extension at all @@ -281,12 +312,7 @@ std::string BaseImporter::GetExtension(const std::string &file) { if (!pIOHandler) { return false; } - union { - const char *magic; - const uint16_t *magic_u16; - const uint32_t *magic_u32; - }; - magic = reinterpret_cast(_magic); + const char *magic = reinterpret_cast(_magic); std::unique_ptr pStream(pIOHandler->Open(pFile)); if (pStream) { @@ -308,15 +334,15 @@ std::string BaseImporter::GetExtension(const std::string &file) { // that's just for convenience, the chance that we cause conflicts // is quite low and it can save some lines and prevent nasty bugs if (2 == size) { - uint16_t rev = *magic_u16; - ByteSwap::Swap(&rev); - if (data_u16[0] == *magic_u16 || data_u16[0] == rev) { + uint16_t magic_u16; + memcpy(&magic_u16, magic, 2); + if (data_u16[0] == magic_u16 || data_u16[0] == ByteSwap::Swapped(magic_u16)) { return true; } } else if (4 == size) { - uint32_t rev = *magic_u32; - ByteSwap::Swap(&rev); - if (data_u32[0] == *magic_u32 || data_u32[0] == rev) { + uint32_t magic_u32; + memcpy(&magic_u32, magic, 4); + if (data_u32[0] == magic_u32 || data_u32[0] == ByteSwap::Swapped(magic_u32)) { return true; } } else { diff --git a/code/Common/Importer.cpp b/code/Common/Importer.cpp index b66059397..bdf64ac8f 100644 --- a/code/Common/Importer.cpp +++ b/code/Common/Importer.cpp @@ -637,24 +637,10 @@ const aiScene* Importer::ReadFile( const char* _pFile, unsigned int pFlags) { std::set extensions; pimpl->mImporter[a]->GetExtensionList(extensions); - // CAUTION: Do not just search for the extension! - // GetExtension() returns the part after the *last* dot, but some extensions have dots - // inside them, e.g. ogre.mesh.xml. Compare the entire end of the string. - for (std::set::const_iterator it = extensions.cbegin(); it != extensions.cend(); ++it) { - - // Yay for C++<20 not having std::string::ends_with() - std::string extension = "." + *it; - if (extension.length() <= pFile.length()) { - // Possible optimization: Fetch the lowercase filename! - if (0 == ASSIMP_stricmp(pFile.c_str() + pFile.length() - extension.length(), extension.c_str())) { - ImporterAndIndex candidate = { pimpl->mImporter[a], a }; - possibleImporters.push_back(candidate); - break; - } - } - + if (BaseImporter::HasExtension(pFile, extensions)) { + ImporterAndIndex candidate = { pimpl->mImporter[a], a }; + possibleImporters.push_back(candidate); } - } // If just one importer supports this extension, pick it and close the case. diff --git a/contrib/openddlparser/CMakeLists.txt b/contrib/openddlparser/CMakeLists.txt index 51f18077c..28f3d5986 100644 --- a/contrib/openddlparser/CMakeLists.txt +++ b/contrib/openddlparser/CMakeLists.txt @@ -15,9 +15,11 @@ option( DDL_STATIC_LIBRARY "Deprecated, use BUILD_SHARED_LIBS instead." # for backwards compatibility use DDL_STATIC_LIBRARY as initial value for cmake variable BUILD_SHARED_LIBS # https://cmake.org/cmake/help/latest/variable/BUILD_SHARED_LIBS.html if ( DDL_STATIC_LIBRARY ) - set ( build_shared_libs_default OFF ) + message("Building shared lib.") + set ( build_shared_libs_default OFF ) else() - set ( build_shared_libs_default ON ) + message("Building static lib.") + set ( build_shared_libs_default ON ) endif() option( DDL_BUILD_SHARED_LIBS "Set to ON to build shared libary of OpenDDL Parser." ${build_shared_libs_default} ) option( COVERALLS "Generate coveralls data" OFF ) @@ -36,6 +38,7 @@ endif() add_definitions( -D_VARIADIC_MAX=10 ) add_definitions( -DGTEST_HAS_PTHREAD=0 ) if ( DDL_DEBUG_OUTPUT ) + message("Enable debug output.") add_definitions( -DDDL_DEBUG_HEADER_NAME) endif() @@ -62,10 +65,12 @@ if (COVERALLS) include(Coveralls) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -O0 -fprofile-arcs -ftest-coverage") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g -O0 -fprofile-arcs -ftest-coverage") + message("Enable coveralls.") endif() # Include the doc component. if(DDL_DOCUMENTATION) + message("Generate doxygen documentation.") find_package(Doxygen REQUIRED) CONFIGURE_FILE( doc/openddlparser_doc.in doc/doxygenfile @ONLY ) add_custom_target(doc ALL diff --git a/contrib/openddlparser/README.md b/contrib/openddlparser/README.md index a48ea1be0..78db2a310 100644 --- a/contrib/openddlparser/README.md +++ b/contrib/openddlparser/README.md @@ -5,13 +5,15 @@ The OpenDDL-Parser is a small and easy to use library for OpenDDL-file-format-pa Build status ============ -Linux build status: [![Build Status](https://travis-ci.org/kimkulling/openddl-parser.png)](https://travis-ci.org/kimkulling/openddl-parser) + +Linux build status: [![Build Status](https://travis-ci.com/kimkulling/openddl-parser.svg?branch=master)](https://travis-ci.com/kimkulling/openddl-parser) Current coverity check status: Coverity Scan Build Status Current test coverage:[![Coverage Status](https://coveralls.io/repos/github/kimkulling/openddl-parser/badge.svg?branch=master)](https://coveralls.io/github/kimkulling/openddl-parser?branch=cpp_coveralls) + Get the source code =================== You can get the code from our git repository, which is located at GitHub. You can clone the repository with the following command: @@ -57,11 +59,11 @@ USE_ODDLPARSER_NS; int main( int argc, char *argv[] ) { if( argc < 3 ) { - return 1; + return Error; } char *filename( nullptr ); - if( 0 == strncmp( FileOption, argv[ 1 ], strlen( FileOption ) ) ) { + if( 0 == strncmp( FileOption, argv[1], strlen( FileOption ) ) ) { filename = argv[ 2 ]; } std::cout << "file to import: " << filename << std::endl; @@ -73,24 +75,27 @@ int main( int argc, char *argv[] ) { FILE *fileStream = fopen( filename, "r+" ); if( NULL == filename ) { std::cerr << "Cannot open file " << filename << std::endl; - return 1; + return Error; } // obtain file size: fseek( fileStream, 0, SEEK_END ); - const size_t size( ftell( fileStream ) ); + const size_t size = ftell( fileStream ); rewind( fileStream ); if( size > 0 ) { char *buffer = new char[ size ]; - const size_t readSize( fread( buffer, sizeof( char ), size, fileStream ) ); + const size_t readSize = fread( buffer, sizeof( char ), size, fileStream ); assert( readSize == size ); + + // Set the memory buffer OpenDDLParser theParser; theParser.setBuffer( buffer, size ); - const bool result( theParser.parse() ); - if( !result ) { + if( !theParser.parse() ) { std::cerr << "Error while parsing file " << filename << "." << std::endl; + return Error; } } + return 0; } @@ -106,9 +111,9 @@ theParser.setBuffer( buffer, size ); const bool result( theParser.parse() ); if ( result ) { DDLNode *root = theParser.getRoot(); - DDLNode::DllNodeList childs = root->getChildNodeList(); - for ( size_t i=0; igetChildNodeList(); + for ( size_t i=0; igetProperty(); // to get properties std::string type = child->getType(); // to get the node type Value *values = child->getValue(); // to get the data; diff --git a/contrib/openddlparser/code/OpenDDLExport.cpp b/contrib/openddlparser/code/OpenDDLExport.cpp index 8768ca64f..f8d33c48d 100644 --- a/contrib/openddlparser/code/OpenDDLExport.cpp +++ b/contrib/openddlparser/code/OpenDDLExport.cpp @@ -134,9 +134,10 @@ bool OpenDDLExport::writeToStream(const std::string &statement) { } bool OpenDDLExport::writeNode(DDLNode *node, std::string &statement) { + bool success(true); writeNodeHeader(node, statement); if (node->hasProperties()) { - writeProperties(node, statement); + success = writeProperties(node, statement); } writeLineEnd(statement); @@ -160,7 +161,7 @@ bool OpenDDLExport::writeNode(DDLNode *node, std::string &statement) { writeToStream(statement); - return true; + return success; } bool OpenDDLExport::writeNodeHeader(DDLNode *node, std::string &statement) { diff --git a/contrib/openddlparser/code/OpenDDLParser.cpp b/contrib/openddlparser/code/OpenDDLParser.cpp index fe9d23ab5..3d7dce45e 100644 --- a/contrib/openddlparser/code/OpenDDLParser.cpp +++ b/contrib/openddlparser/code/OpenDDLParser.cpp @@ -30,7 +30,10 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include #ifdef _WIN32 -#include +# ifndef WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN +# endif +# include #endif // _WIN32 BEGIN_ODDLPARSER_NS @@ -71,7 +74,7 @@ const char *getTypeToken(Value::ValueType type) { return Grammar::PrimitiveTypeToken[(size_t)type]; } -static void logInvalidTokenError(char *in, const std::string &exp, OpenDDLParser::logCallback callback) { +static void logInvalidTokenError(const char *in, const std::string &exp, OpenDDLParser::logCallback callback) { if (callback) { std::string full(in); std::string part(full.substr(0, 50)); @@ -338,20 +341,25 @@ char *OpenDDLParser::parseStructure(char *in, char *end) { bool error(false); in = lookForNextToken(in, end); - if (*in == *Grammar::OpenBracketToken) { - // loop over all children ( data and nodes ) - do { - in = parseStructureBody(in, end, error); - if (in == nullptr) { - return nullptr; + if (in != end) { + if (*in == *Grammar::OpenBracketToken) { + // loop over all children ( data and nodes ) + do { + in = parseStructureBody(in, end, error); + if (in == nullptr) { + return nullptr; + } + } while (in != end && + *in != *Grammar::CloseBracketToken); + if (in != end) { + ++in; } - } while (*in != *Grammar::CloseBracketToken); - ++in; - } else { - ++in; - logInvalidTokenError(in, std::string(Grammar::OpenBracketToken), m_logCallback); - error = true; - return nullptr; + } else { + ++in; + logInvalidTokenError(in, std::string(Grammar::OpenBracketToken), m_logCallback); + error = true; + return nullptr; + } } in = lookForNextToken(in, end); @@ -418,8 +426,8 @@ char *OpenDDLParser::parseStructureBody(char *in, char *end, bool &error) { } in = lookForNextToken(in, end); - if (*in != '}') { - logInvalidTokenError(in, std::string(Grammar::CloseBracketToken), m_logCallback); + if (in == end || *in != '}') { + logInvalidTokenError(in == end ? "" : in, std::string(Grammar::CloseBracketToken), m_logCallback); return nullptr; } else { //in++; @@ -455,7 +463,7 @@ DDLNode *OpenDDLParser::top() { return nullptr; } - DDLNode *top(m_stack.back()); + DDLNode *top = m_stack.back(); return top; } @@ -647,12 +655,15 @@ char *OpenDDLParser::parseBooleanLiteral(char *in, char *end, Value **boolean) { in = lookForNextToken(in, end); char *start(in); + + size_t len(0); while (!isSeparator(*in) && in != end) { ++in; + ++len; } - int res = ::strncmp(Grammar::BoolTrue, start, strlen(Grammar::BoolTrue)); + int res = ::strncmp(Grammar::BoolTrue, start, len); if (0 != res) { - res = ::strncmp(Grammar::BoolFalse, start, strlen(Grammar::BoolFalse)); + res = ::strncmp(Grammar::BoolFalse, start, len); if (0 != res) { *boolean = nullptr; return in; @@ -733,7 +744,7 @@ char *OpenDDLParser::parseFloatingLiteral(char *in, char *end, Value **floating, in = lookForNextToken(in, end); char *start(in); - while (!isSeparator(*in) && in != end) { + while (in != end && !isSeparator(*in)) { ++in; } @@ -838,6 +849,13 @@ char *OpenDDLParser::parseHexaLiteral(char *in, char *end, Value **data) { int value(0); while (pos > 0) { int v = hex2Decimal(*start); + if (v < 0) { + while (isEndofLine(*in)) { + ++in; + } + return in; + } + --pos; value = (value << 4) | v; ++start; @@ -901,10 +919,10 @@ char *OpenDDLParser::parseDataList(char *in, char *end, Value::ValueType type, V } in = lookForNextToken(in, end); - if (*in == '{') { + if (in != end && *in == '{') { ++in; Value *current(nullptr), *prev(nullptr); - while ('}' != *in) { + while (in != end && '}' != *in) { current = nullptr; in = lookForNextToken(in, end); if (Value::ValueType::ddl_ref == type) { @@ -962,11 +980,12 @@ char *OpenDDLParser::parseDataList(char *in, char *end, Value::ValueType type, V } in = getNextSeparator(in, end); - if (',' != *in && Grammar::CloseBracketToken[0] != *in && !isSpace(*in)) { + if (in == end || (',' != *in && Grammar::CloseBracketToken[0] != *in && !isSpace(*in))) { break; } } - ++in; + if (in != end) + ++in; } return in; diff --git a/contrib/openddlparser/include/openddlparser/OpenDDLCommon.h b/contrib/openddlparser/include/openddlparser/OpenDDLCommon.h index 6ccc83b88..4b92d1406 100644 --- a/contrib/openddlparser/include/openddlparser/OpenDDLCommon.h +++ b/contrib/openddlparser/include/openddlparser/OpenDDLCommon.h @@ -26,8 +26,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include #include -#include -#include +#include +#include #ifndef _WIN32 #include #endif diff --git a/contrib/openddlparser/include/openddlparser/OpenDDLParser.h b/contrib/openddlparser/include/openddlparser/OpenDDLParser.h index 3fbb4b6af..735e784e3 100644 --- a/contrib/openddlparser/include/openddlparser/OpenDDLParser.h +++ b/contrib/openddlparser/include/openddlparser/OpenDDLParser.h @@ -40,15 +40,6 @@ struct Identifier; struct Reference; struct Property; -template -inline bool isEmbeddedCommentOpenTag(T *in, T *end) { - if (in == '/' && in + 1 == '*') { - return true; - } - - return false; -} - /// @brief Utility function to search for the next token or the end of the buffer. /// @param in [in] The start position in the buffer. /// @param end [in] The end position in the buffer. diff --git a/contrib/openddlparser/include/openddlparser/OpenDDLParserUtils.h b/contrib/openddlparser/include/openddlparser/OpenDDLParserUtils.h index 42ad675f8..62144a01c 100644 --- a/contrib/openddlparser/include/openddlparser/OpenDDLParserUtils.h +++ b/contrib/openddlparser/include/openddlparser/OpenDDLParserUtils.h @@ -54,7 +54,9 @@ inline bool isSeparator(T in) { return false; } -static const unsigned char chartype_table[256] = { +const size_t CharTableSize = 256; + +static const unsigned char chartype_table[CharTableSize] = { 0, 0, 0, @@ -318,6 +320,10 @@ static const unsigned char chartype_table[256] = { template inline bool isNumeric(const T in) { + if (static_cast(in) >= CharTableSize) { + return '\0'; + } + size_t idx = static_cast(in); return idx < sizeof(chartype_table) && (chartype_table[idx] == 1); } @@ -433,7 +439,7 @@ inline bool isEndofLine(const T in) { template inline static T *getNextSeparator(T *in, T *end) { - while (!isSeparator(*in) || in == end) { + while (in != end && !isSeparator(*in)) { ++in; } return in; diff --git a/include/assimp/BaseImporter.h b/include/assimp/BaseImporter.h index 06b87f1e1..d0b173171 100644 --- a/include/assimp/BaseImporter.h +++ b/include/assimp/BaseImporter.h @@ -259,7 +259,7 @@ public: // static utilities std::size_t numTokens, unsigned int searchBytes = 200, bool tokensSol = false, - bool noAlphaBeforeTokens = false); + bool noGraphBeforeTokens = false); // ------------------------------------------------------------------- /** @brief Check whether a file has a specific file extension @@ -275,6 +275,16 @@ public: // static utilities const char *ext1 = nullptr, const char *ext2 = nullptr); + // ------------------------------------------------------------------- + /** @brief Check whether a file has one of the passed file extensions + * @param pFile Input file + * @param extensions Extensions to check for. Lowercase characters only, no dot! + * @note Case-insensitive + */ + static bool HasExtension( + const std::string &pFile, + const std::set &extensions); + // ------------------------------------------------------------------- /** @brief Extract file extension from a string * @param pFile Input file diff --git a/include/assimp/postprocess.h b/include/assimp/postprocess.h index cdcbf0577..a905a8be0 100644 --- a/include/assimp/postprocess.h +++ b/include/assimp/postprocess.h @@ -94,6 +94,7 @@ enum aiPostProcessSteps * indexed geometry, this step is compulsory or you'll just waste rendering * time. If this flag is not specified, no vertices are referenced by * more than one face and no index buffer is required for rendering. + * Unless the importer (like ply) had to split vertices. Then you need one regardless. */ aiProcess_JoinIdenticalVertices = 0x2, diff --git a/port/swig/DONOTUSEYET b/port/swig/DONOTUSEYET deleted file mode 100644 index 87c6e0699..000000000 --- a/port/swig/DONOTUSEYET +++ /dev/null @@ -1 +0,0 @@ -The interface files are by no means complete yet and only work with the not-yet-released D SWIG backend, although adding support for other languages should not be too much of problem via #ifdefs. diff --git a/port/swig/assimp.i b/port/swig/assimp.i deleted file mode 100644 index 58e1546e7..000000000 --- a/port/swig/assimp.i +++ /dev/null @@ -1,140 +0,0 @@ -%module assimp - -// SWIG helpers for std::string and std::vector wrapping. -%include -%include - -// Globally enable enum prefix stripping. -%dstripprefix; - - -// PACK_STRUCT is a no-op for SWIG – it does not matter for the generated -// bindings how the underlying C++ code manages its memory. -#define PACK_STRUCT - - -// Helper macros for wrapping the pointer-and-length arrays used in the -// Assimp API. - -%define ASSIMP_ARRAY(CLASS, TYPE, NAME, LENGTH) -%newobject CLASS::NAME; -%extend CLASS { - std::vector *NAME() const { - std::vector *result = new std::vector; - result->reserve(LENGTH); - - for (unsigned int i = 0; i < LENGTH; ++i) { - result->push_back($self->NAME[i]); - } - - return result; - } -} -%ignore CLASS::NAME; -%enddef - -%define ASSIMP_POINTER_ARRAY(CLASS, TYPE, NAME, LENGTH) -%newobject CLASS::NAME; -%extend CLASS { - std::vector *NAME() const { - std::vector *result = new std::vector; - result->reserve(LENGTH); - - TYPE *currentValue = $self->NAME; - TYPE *valueLimit = $self->NAME + LENGTH; - while (currentValue < valueLimit) { - result->push_back(currentValue); - ++currentValue; - } - - return result; - } -} -%ignore CLASS::NAME; -%enddef - -%define ASSIMP_POINTER_ARRAY_ARRAY(CLASS, TYPE, NAME, OUTER_LENGTH, INNER_LENGTH) -%newobject CLASS::NAME; -%extend CLASS { - std::vector > *NAME() const { - std::vector > *result = new std::vector >; - result->reserve(OUTER_LENGTH); - - for (unsigned int i = 0; i < OUTER_LENGTH; ++i) { - std::vector currentElements; - - if ($self->NAME[i] != 0) { - currentElements.reserve(INNER_LENGTH); - - TYPE *currentValue = $self->NAME[i]; - TYPE *valueLimit = $self->NAME[i] + INNER_LENGTH; - while (currentValue < valueLimit) { - currentElements.push_back(currentValue); - ++currentValue; - } - } - - result->push_back(currentElements); - } - - return result; - } -} -%ignore CLASS::NAME; -%enddef - - -%include "interface/aiDefines.i" -%include "interface/aiTypes.i" -%include "interface/assimp.i" -%include "interface/aiTexture.i" -%include "interface/aiMatrix4x4.i" -%include "interface/aiMatrix3x3.i" -%include "interface/aiVector3D.i" -%include "interface/aiVector2D.i" -%include "interface/aiColor4D.i" -%include "interface/aiLight.i" -%include "interface/aiCamera.i" -%include "interface/aiFileIO.i" -%include "interface/aiAssert.i" -%include "interface/aiVersion.i" -%include "interface/aiAnim.i" -%include "interface/aiMaterial.i" -%include "interface/aiMesh.i" -%include "interface/aiPostProcess.i" -%include "interface/aiConfig.i" -%include "interface/assimp.i" -%include "interface/aiQuaternion.i" -%include "interface/aiScene.i" -%include "interface/Logger.i" -%include "interface/DefaultLogger.i" -%include "interface/NullLogger.i" -%include "interface/LogStream.i" -%include "interface/IOStream.i" -%include "interface/IOSystem.i" - - -// We have to "instantiate" the templates used by the ASSSIMP_*_ARRAY macros -// here at the end to avoid running into forward reference issues (SWIG would -// spit out the helper functions before the header includes for the element -// types otherwise). - -%template(UintVector) std::vector; -%template(aiAnimationVector) std::vector; -%template(aiAnimMeshVector) std::vector; -%template(aiBonesVector) std::vector; -%template(aiCameraVector) std::vector; -%template(aiColor4DVector) std::vector; -%template(aiColor4DVectorVector) std::vector >; -%template(aiFaceVector) std::vector; -%template(aiLightVector) std::vector; -%template(aiMaterialVector) std::vector; -%template(aiMaterialPropertyVector) std::vector; -%template(aiMeshAnimVector) std::vector; -%template(aiMeshVector) std::vector; -%template(aiNodeVector) std::vector; -%template(aiNodeAnimVector) std::vector; -%template(aiTextureVector) std::vector; -%template(aiVector3DVector) std::vector; -%template(aiVector3DVectorVector) std::vector >; -%template(aiVertexWeightVector) std::vector; diff --git a/port/swig/d/build.sh b/port/swig/d/build.sh deleted file mode 100755 index 0bf6bff6a..000000000 --- a/port/swig/d/build.sh +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/sh -gcc -shared -fPIC -g3 -I../../../include/ -lassimp -olibassimp_wrap.so assimp_wrap.cxx diff --git a/port/swig/d/generate.sh b/port/swig/d/generate.sh deleted file mode 100755 index 7de66b1ff..000000000 --- a/port/swig/d/generate.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/sh -rm -rf assimp/ -mkdir assimp -swig -c++ -d -outcurrentdir -I../../../include -splitproxy -package assimp $@ ../assimp.i diff --git a/port/swig/interface/DefaultLogger.i b/port/swig/interface/DefaultLogger.i deleted file mode 100644 index 600d28e84..000000000 --- a/port/swig/interface/DefaultLogger.i +++ /dev/null @@ -1,5 +0,0 @@ -%{ -#include "DefaultLogger.h" -%} - -%include "DefaultLogger.h" diff --git a/port/swig/interface/IOStream.i b/port/swig/interface/IOStream.i deleted file mode 100644 index baca5ef45..000000000 --- a/port/swig/interface/IOStream.i +++ /dev/null @@ -1,5 +0,0 @@ -%{ -#include "IOStream.h" -%} - -%include "IOStream.h" diff --git a/port/swig/interface/IOSystem.i b/port/swig/interface/IOSystem.i deleted file mode 100644 index 3e3e04a67..000000000 --- a/port/swig/interface/IOSystem.i +++ /dev/null @@ -1,11 +0,0 @@ -%{ -#include "IOSystem.h" -%} - -// The const char* overload is used instead. -%ignore Assimp::IOSystem::Exists(const std::string&) const; -%ignore Assimp::IOSystem::Open(const std::string& pFile); -%ignore Assimp::IOSystem::Open(const std::string& pFile, const std::string& pMode); -%ignore Assimp::IOSystem::ComparePaths(const std::string& one, const std::string& second) const; - -%include "IOSystem.h" diff --git a/port/swig/interface/LogStream.i b/port/swig/interface/LogStream.i deleted file mode 100644 index 022f8e586..000000000 --- a/port/swig/interface/LogStream.i +++ /dev/null @@ -1,5 +0,0 @@ -%{ -#include "LogStream.h" -%} - -%include "LogStream.h" diff --git a/port/swig/interface/Logger.i b/port/swig/interface/Logger.i deleted file mode 100644 index cadc50b8e..000000000 --- a/port/swig/interface/Logger.i +++ /dev/null @@ -1,5 +0,0 @@ -%{ -#include "Logger.h" -%} - -%include "Logger.h" diff --git a/port/swig/interface/NullLogger.i b/port/swig/interface/NullLogger.i deleted file mode 100644 index 5cf42edf5..000000000 --- a/port/swig/interface/NullLogger.i +++ /dev/null @@ -1,5 +0,0 @@ -%{ -#include "NullLogger.h" -%} - -%include "NullLogger.h" diff --git a/port/swig/interface/aiAnim.i b/port/swig/interface/aiAnim.i deleted file mode 100644 index de497008f..000000000 --- a/port/swig/interface/aiAnim.i +++ /dev/null @@ -1,8 +0,0 @@ -%{ -#include "aiAnim.h" -%} - -ASSIMP_ARRAY(aiAnimation, aiNodeAnim*, mChannels, $self->mNumChannels); -ASSIMP_ARRAY(aiAnimation, aiMeshAnim*, mMeshChannels, $self->mNumMeshChannels); - -%include "aiAnim.h" diff --git a/port/swig/interface/aiAssert.i b/port/swig/interface/aiAssert.i deleted file mode 100644 index bc8a9b88c..000000000 --- a/port/swig/interface/aiAssert.i +++ /dev/null @@ -1,5 +0,0 @@ -%{ -#include "aiAssert.h" -%} - -%include "aiAssert.h" diff --git a/port/swig/interface/aiCamera.i b/port/swig/interface/aiCamera.i deleted file mode 100644 index 5c2124501..000000000 --- a/port/swig/interface/aiCamera.i +++ /dev/null @@ -1,5 +0,0 @@ -%{ -#include "aiCamera.h" -%} - -%include "aiCamera.h" diff --git a/port/swig/interface/aiColor4D.i b/port/swig/interface/aiColor4D.i deleted file mode 100644 index 3c009168b..000000000 --- a/port/swig/interface/aiColor4D.i +++ /dev/null @@ -1,5 +0,0 @@ -%{ -#include "aiColor4D.h" -%} - -%include "aiColor4D.h" diff --git a/port/swig/interface/aiConfig.i b/port/swig/interface/aiConfig.i deleted file mode 100644 index 110abb3d6..000000000 --- a/port/swig/interface/aiConfig.i +++ /dev/null @@ -1,5 +0,0 @@ -%{ -#include "aiConfig.h" -%} - -%include "aiConfig.h" diff --git a/port/swig/interface/aiDefines.i b/port/swig/interface/aiDefines.i deleted file mode 100644 index 3a61ea62f..000000000 --- a/port/swig/interface/aiDefines.i +++ /dev/null @@ -1,5 +0,0 @@ -%{ -#include "aiDefines.h" -%} - -%include "aiDefines.h" diff --git a/port/swig/interface/aiFileIO.i b/port/swig/interface/aiFileIO.i deleted file mode 100644 index 5a1e0923e..000000000 --- a/port/swig/interface/aiFileIO.i +++ /dev/null @@ -1,5 +0,0 @@ -%{ -#include "aiFileIO.h" -%} - -%include "aiFileIO.h" diff --git a/port/swig/interface/aiLight.i b/port/swig/interface/aiLight.i deleted file mode 100644 index fbefde7c0..000000000 --- a/port/swig/interface/aiLight.i +++ /dev/null @@ -1,5 +0,0 @@ -%{ -#include "aiLight.h" -%} - -%include "aiLight.h" diff --git a/port/swig/interface/aiMaterial.i b/port/swig/interface/aiMaterial.i deleted file mode 100644 index 630e6b711..000000000 --- a/port/swig/interface/aiMaterial.i +++ /dev/null @@ -1,33 +0,0 @@ -%{ -#include "aiMaterial.h" -%} - -ASSIMP_ARRAY(aiMaterial, aiMaterialProperty*, mProperties, $self->mNumProperties) - -%include -%apply enum SWIGTYPE *OUTPUT { aiTextureMapping* mapping }; -%apply unsigned int *OUTPUT { unsigned int* uvindex }; -%apply float *OUTPUT { float* blend }; -%apply enum SWIGTYPE *OUTPUT { aiTextureOp* op }; -%apply unsigned int *OUTPUT { unsigned int* flags }; - -%include "aiMaterial.h" - -%clear unsigned int* flags; -%clear aiTextureOp* op; -%clear float *blend; -%clear unsigned int* uvindex; -%clear aiTextureMapping* mapping; - - -%apply int &OUTPUT { int &pOut }; -%apply float &OUTPUT { float &pOut }; - -%template(GetInteger) aiMaterial::Get; -%template(GetFloat) aiMaterial::Get; -%template(GetColor4D) aiMaterial::Get; -%template(GetColor3D) aiMaterial::Get; -%template(GetString) aiMaterial::Get; - -%clear int &pOut; -%clear float &pOut; diff --git a/port/swig/interface/aiMatrix3x3.i b/port/swig/interface/aiMatrix3x3.i deleted file mode 100644 index 8336d447a..000000000 --- a/port/swig/interface/aiMatrix3x3.i +++ /dev/null @@ -1,5 +0,0 @@ -%{ -#include "aiMatrix3x3.h" -%} - -%include "aiMatrix3x3.h" diff --git a/port/swig/interface/aiMatrix4x4.i b/port/swig/interface/aiMatrix4x4.i deleted file mode 100644 index 976c56b03..000000000 --- a/port/swig/interface/aiMatrix4x4.i +++ /dev/null @@ -1,5 +0,0 @@ -%{ -#include "aiMatrix4x4.h" -%} - -%include "aiMatrix4x4.h" diff --git a/port/swig/interface/aiMesh.i b/port/swig/interface/aiMesh.i deleted file mode 100644 index 141366c2e..000000000 --- a/port/swig/interface/aiMesh.i +++ /dev/null @@ -1,29 +0,0 @@ -%{ -#include "aiMesh.h" -%} - - -ASSIMP_ARRAY(aiFace, unsigned int, mIndices, $self->mNumIndices); - -ASSIMP_POINTER_ARRAY(aiBone, aiVertexWeight, mWeights, $self->mNumWeights); - -ASSIMP_POINTER_ARRAY(aiAnimMesh, aiVector3D, mVertices, $self->mNumVertices); -ASSIMP_POINTER_ARRAY(aiAnimMesh, aiVector3D, mNormals, $self->mNumVertices); -ASSIMP_POINTER_ARRAY(aiAnimMesh, aiVector3D, mTangents, $self->mNumVertices); -ASSIMP_POINTER_ARRAY(aiAnimMesh, aiVector3D, mBitangents, $self->mNumVertices); -ASSIMP_POINTER_ARRAY_ARRAY(aiAnimMesh, aiVector3D, mTextureCoords, AI_MAX_NUMBER_OF_TEXTURECOORDS, $self->mNumVertices); -ASSIMP_POINTER_ARRAY_ARRAY(aiAnimMesh, aiColor4D, mColors, AI_MAX_NUMBER_OF_COLOR_SETS, $self->mNumVertices); - -ASSIMP_ARRAY(aiMesh, aiAnimMesh*, mAnimMeshes, $self->mNumAnimMeshes); -ASSIMP_ARRAY(aiMesh, aiBone*, mBones, $self->mNumBones); -ASSIMP_ARRAY(aiMesh, unsigned int, mNumUVComponents, AI_MAX_NUMBER_OF_TEXTURECOORDS); -ASSIMP_POINTER_ARRAY(aiMesh, aiVector3D, mVertices, $self->mNumVertices); -ASSIMP_POINTER_ARRAY(aiMesh, aiVector3D, mNormals, $self->mNumVertices); -ASSIMP_POINTER_ARRAY(aiMesh, aiVector3D, mTangents, $self->mNumVertices); -ASSIMP_POINTER_ARRAY(aiMesh, aiVector3D, mBitangents, $self->mNumVertices); -ASSIMP_POINTER_ARRAY(aiMesh, aiFace, mFaces, $self->mNumFaces); -ASSIMP_POINTER_ARRAY_ARRAY(aiMesh, aiVector3D, mTextureCoords, AI_MAX_NUMBER_OF_TEXTURECOORDS, $self->mNumVertices); -ASSIMP_POINTER_ARRAY_ARRAY(aiMesh, aiColor4D, mColors, AI_MAX_NUMBER_OF_COLOR_SETS, $self->mNumVertices); - - -%include "aiMesh.h" diff --git a/port/swig/interface/aiPostProcess.i b/port/swig/interface/aiPostProcess.i deleted file mode 100644 index 5f64ec53a..000000000 --- a/port/swig/interface/aiPostProcess.i +++ /dev/null @@ -1,7 +0,0 @@ -%{ -#include "aiPostProcess.h" -%} - -%feature("d:stripprefix", "aiProcess_") aiPostProcessSteps; - -%include "aiPostProcess.h" diff --git a/port/swig/interface/aiQuaternion.i b/port/swig/interface/aiQuaternion.i deleted file mode 100644 index 256057a22..000000000 --- a/port/swig/interface/aiQuaternion.i +++ /dev/null @@ -1,5 +0,0 @@ -%{ -#include "aiQuaternion.h" -%} - -%include "aiQuaternion.h" diff --git a/port/swig/interface/aiScene.i b/port/swig/interface/aiScene.i deleted file mode 100644 index 7278f3368..000000000 --- a/port/swig/interface/aiScene.i +++ /dev/null @@ -1,17 +0,0 @@ -%{ -#include "aiScene.h" -%} - - -ASSIMP_ARRAY(aiScene, aiAnimation*, mAnimations, $self->mNumAnimations); -ASSIMP_ARRAY(aiScene, aiCamera*, mCameras, $self->mNumCameras); -ASSIMP_ARRAY(aiScene, aiLight*, mLights, $self->mNumLights); -ASSIMP_ARRAY(aiScene, aiMaterial*, mMaterials, $self->mNumMaterials); -ASSIMP_ARRAY(aiScene, aiMesh*, mMeshes, $self->mNumMeshes); -ASSIMP_ARRAY(aiScene, aiTexture*, mTextures, $self->mNumTextures); - -ASSIMP_ARRAY(aiNode, aiNode*, mChildren, $self->mNumChildren); -ASSIMP_ARRAY(aiNode, unsigned int, mMeshes, $self->mNumMeshes); - - -%include "aiScene.h" diff --git a/port/swig/interface/aiTexture.i b/port/swig/interface/aiTexture.i deleted file mode 100644 index d07d00190..000000000 --- a/port/swig/interface/aiTexture.i +++ /dev/null @@ -1,5 +0,0 @@ -%{ -#include "aiTexture.h" -%} - -%include "aiTexture.h" diff --git a/port/swig/interface/aiTypes.i b/port/swig/interface/aiTypes.i deleted file mode 100644 index a086dfd30..000000000 --- a/port/swig/interface/aiTypes.i +++ /dev/null @@ -1,8 +0,0 @@ -%{ -#include "aiTypes.h" -%} - -// The const char* overload is used instead. -%ignore aiString::Set(const std::string& pString); - -%include "aiTypes.h" diff --git a/port/swig/interface/aiVector2D.i b/port/swig/interface/aiVector2D.i deleted file mode 100644 index 5db15c0e6..000000000 --- a/port/swig/interface/aiVector2D.i +++ /dev/null @@ -1,5 +0,0 @@ -%{ -#include "aiVector2D.h" -%} - -%include "aiVector2D.h" diff --git a/port/swig/interface/aiVector3D.i b/port/swig/interface/aiVector3D.i deleted file mode 100644 index 2c83f605f..000000000 --- a/port/swig/interface/aiVector3D.i +++ /dev/null @@ -1,5 +0,0 @@ -%{ -#include "aiVector3D.h" -%} - -%include "aiVector3D.h" diff --git a/port/swig/interface/aiVersion.i b/port/swig/interface/aiVersion.i deleted file mode 100644 index 9ddd532ef..000000000 --- a/port/swig/interface/aiVersion.i +++ /dev/null @@ -1,5 +0,0 @@ -%{ -#include "aiVersion.h" -%} - -%include "aiVersion.h" diff --git a/port/swig/interface/assimp.i b/port/swig/interface/assimp.i deleted file mode 100644 index a1b1404a0..000000000 --- a/port/swig/interface/assimp.i +++ /dev/null @@ -1,45 +0,0 @@ -%{ -#include "assimp.hpp" -%} - - -namespace Assimp { - -// See docs in assimp.hpp. -%ignore Importer::ReadFile(const std::string& pFile, unsigned int pFlags); -%ignore Importer::GetExtensionList(std::string& szOut); -%ignore Importer::IsExtensionSupported(const std::string& szExtension); - -// These are only necessary for extending Assimp with custom importers or post -// processing steps, which would require wrapping the internal BaseImporter and -// BaseProcess classes. -%ignore Importer::RegisterLoader(BaseImporter* pImp); -%ignore Importer::UnregisterLoader(BaseImporter* pImp); -%ignore Importer::RegisterPPStep(BaseProcess* pImp); -%ignore Importer::UnregisterPPStep(BaseProcess* pImp); -%ignore Importer::FindLoader(const char* szExtension); - -} - - -// Each aiScene has to keep a reference to the Importer to prevent it from -// being garbage collected, whose destructor would release the underlying -// C++ memory the scene is stored in. -%typemap(dcode) aiScene "package Object m_importer;" -%typemap(dout) - aiScene* GetScene, - aiScene* ReadFile, - aiScene* ApplyPostProcessing, - aiScene* ReadFileFromMemory { - void* cPtr = $wcall; - $dclassname ret = (cPtr is null) ? null : new $dclassname(cPtr, $owner);$excode - ret.m_importer = this; - return ret; -} - -%include -%apply bool *OUTPUT { bool *bWasExisting }; - -%include "assimp.hpp" - -%clear bool *bWasExisting; diff --git a/test/models/IRR/scenegraphAnim.irr b/test/models/IRR/scenegraphAnim.irr index 1c6fd0ef4..2300ea18f 100644 --- a/test/models/IRR/scenegraphAnim.irr +++ b/test/models/IRR/scenegraphAnim.irr @@ -126,7 +126,7 @@ - + diff --git a/test/models/IRR/scenegraphAnimMod.irr b/test/models/IRR/scenegraphAnimMod.irr new file mode 100644 index 000000000..21408b245 --- /dev/null +++ b/test/models/IRR/scenegraphAnimMod.irr @@ -0,0 +1,554 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/models/IRR/scenegraphAnimMod_UTF16LE.irr b/test/models/IRR/scenegraphAnimMod_UTF16LE.irr new file mode 100644 index 000000000..7384ae29a Binary files /dev/null and b/test/models/IRR/scenegraphAnimMod_UTF16LE.irr differ diff --git a/test/models/IRR/scenegraphAnim_UTF16LE.irr b/test/models/IRR/scenegraphAnim_UTF16LE.irr index b22aaf4b7..f6794351f 100644 Binary files a/test/models/IRR/scenegraphAnim_UTF16LE.irr and b/test/models/IRR/scenegraphAnim_UTF16LE.irr differ diff --git a/test/unit/utImporter.cpp b/test/unit/utImporter.cpp index 98080c526..5ecc45e34 100644 --- a/test/unit/utImporter.cpp +++ b/test/unit/utImporter.cpp @@ -361,3 +361,37 @@ TEST_F(ImporterTest, unexpectedException) { EXPECT_TRUE(false); } } + +// ------------------------------------------------------------------------------------------------ + +struct ExtensionTestCase { + std::string testName; + std::string filename; + std::string getExtensionResult; + std::string hasExtension; + bool hasExtensionResult; +}; + +using ExtensionTest = ::testing::TestWithParam; + +TEST_P(ExtensionTest, testGetAndHasExtension) { + const ExtensionTestCase& testCase = GetParam(); + EXPECT_EQ(testCase.getExtensionResult, BaseImporter::GetExtension(testCase.filename)); + EXPECT_EQ(testCase.hasExtensionResult, BaseImporter::HasExtension(testCase.filename, {testCase.hasExtension})); +} + +INSTANTIATE_TEST_SUITE_P( + ExtensionTests, ExtensionTest, + ::testing::ValuesIn({ + {"NoExtension", "name", "", "glb", false}, + {"NoExtensionAndEmptyVersion", "name#", "", "glb", false}, + {"WithExtensionAndEmptyVersion", "name.glb#", "glb#", "glb", false}, + {"WithExtensionAndVersion", "name.glb#1234", "glb", "glb", true}, + {"WithExtensionAndHashInStem", "name#1234.glb", "glb", "glb", true}, + {"WithExtensionAndInvalidVersion", "name.glb#_", "glb#_", "glb", false}, + {"WithExtensionAndDotAndHashInStem", "name.glb#.abc", "abc", "glb", false}, + {"WithTwoExtensions", "name.abc.def", "def", "abc.def", true}, + }), + [](const ::testing::TestParamInfo& info) { + return info.param.testName; + }); diff --git a/test/unit/utglTF2ImportExport.cpp b/test/unit/utglTF2ImportExport.cpp index 91ac87ee5..ba1c859ad 100644 --- a/test/unit/utglTF2ImportExport.cpp +++ b/test/unit/utglTF2ImportExport.cpp @@ -60,7 +60,7 @@ using namespace Assimp; class utglTF2ImportExport : public AbstractImportExportBase { public: - virtual bool importerMatTest(const char *file, bool spec_gloss, std::array exp_modes = { aiTextureMapMode_Wrap, aiTextureMapMode_Wrap }) { + virtual bool importerMatTest(const char *file, bool spec, bool gloss, std::array exp_modes = { aiTextureMapMode_Wrap, aiTextureMapMode_Wrap }) { Assimp::Importer importer; const aiScene *scene = importer.ReadFile(file, aiProcess_ValidateDataStructure); EXPECT_NE(scene, nullptr); @@ -105,16 +105,19 @@ public: aiColor3D spec_color = { 0, 0, 0 }; ai_real glossiness = ai_real(0.5); - if (spec_gloss) { + if (spec) { EXPECT_EQ(aiReturn_SUCCESS, material->Get(AI_MATKEY_COLOR_SPECULAR, spec_color)); constexpr ai_real spec_val(0.20000000298023225); // From the file EXPECT_EQ(spec_val, spec_color.r); EXPECT_EQ(spec_val, spec_color.g); EXPECT_EQ(spec_val, spec_color.b); + } else { + EXPECT_EQ(aiReturn_FAILURE, material->Get(AI_MATKEY_COLOR_SPECULAR, spec_color)); + } + if (gloss) { EXPECT_EQ(aiReturn_SUCCESS, material->Get(AI_MATKEY_GLOSSINESS_FACTOR, glossiness)); EXPECT_EQ(ai_real(1.0), glossiness); } else { - EXPECT_EQ(aiReturn_FAILURE, material->Get(AI_MATKEY_COLOR_SPECULAR, spec_color)); EXPECT_EQ(aiReturn_FAILURE, material->Get(AI_MATKEY_GLOSSINESS_FACTOR, glossiness)); } @@ -143,7 +146,7 @@ public: }; TEST_F(utglTF2ImportExport, importglTF2FromFileTest) { - EXPECT_TRUE(importerMatTest(ASSIMP_TEST_MODELS_DIR "/glTF2/BoxTextured-glTF/BoxTextured.gltf", false, {aiTextureMapMode_Mirror, aiTextureMapMode_Clamp})); + EXPECT_TRUE(importerMatTest(ASSIMP_TEST_MODELS_DIR "/glTF2/BoxTextured-glTF/BoxTextured.gltf", false, false, {aiTextureMapMode_Mirror, aiTextureMapMode_Clamp})); } TEST_F(utglTF2ImportExport, importBinaryglTF2FromFileTest) { @@ -151,7 +154,7 @@ TEST_F(utglTF2ImportExport, importBinaryglTF2FromFileTest) { } TEST_F(utglTF2ImportExport, importglTF2_KHR_materials_pbrSpecularGlossiness) { - EXPECT_TRUE(importerMatTest(ASSIMP_TEST_MODELS_DIR "/glTF2/BoxTextured-glTF-pbrSpecularGlossiness/BoxTextured.gltf", true)); + EXPECT_TRUE(importerMatTest(ASSIMP_TEST_MODELS_DIR "/glTF2/BoxTextured-glTF-pbrSpecularGlossiness/BoxTextured.gltf", true, true)); } void VerifyClearCoatScene(const aiScene *scene) { @@ -223,13 +226,16 @@ TEST_F(utglTF2ImportExport, importglTF2AndExport_KHR_materials_pbrSpecularGlossi // Export with specular glossiness disabled EXPECT_EQ(aiReturn_SUCCESS, exporter.Export(scene, "glb2", ASSIMP_TEST_MODELS_DIR "/glTF2/BoxTextured-glTF-pbrSpecularGlossiness/BoxTextured_out.glb")); + // And re-import + EXPECT_TRUE(importerMatTest(ASSIMP_TEST_MODELS_DIR "/glTF2/BoxTextured-glTF-pbrSpecularGlossiness/BoxTextured_out.glb", true, false)); + // Export with specular glossiness enabled ExportProperties props; props.SetPropertyBool(AI_CONFIG_USE_GLTF_PBR_SPECULAR_GLOSSINESS, true); EXPECT_EQ(aiReturn_SUCCESS, exporter.Export(scene, "glb2", ASSIMP_TEST_MODELS_DIR "/glTF2/BoxTextured-glTF-pbrSpecularGlossiness/BoxTextured_out.glb", 0, &props)); // And re-import - EXPECT_TRUE(importerMatTest(ASSIMP_TEST_MODELS_DIR "/glTF2/BoxTextured-glTF-pbrSpecularGlossiness/BoxTextured_out.glb", true)); + EXPECT_TRUE(importerMatTest(ASSIMP_TEST_MODELS_DIR "/glTF2/BoxTextured-glTF-pbrSpecularGlossiness/BoxTextured_out.glb", true, true)); } TEST_F(utglTF2ImportExport, importglTF2AndExportToOBJ) {