diff --git a/Readme.md b/Readme.md index 9a8ac7c33..a740be772 100644 --- a/Readme.md +++ b/Readme.md @@ -6,20 +6,14 @@ Open Asset Import Library is a library to load various 3d file formats into a sh ### Current project status ### [![Financial Contributors on Open Collective](https://opencollective.com/assimp/all/badge.svg?label=financial+contributors)](https://opencollective.com/assimp) ![C/C++ CI](https://github.com/assimp/assimp/workflows/C/C++%20CI/badge.svg) - - Coverity Scan Build Status - [![Codacy Badge](https://app.codacy.com/project/badge/Grade/9973693b7bdd4543b07084d5d9cf4745)](https://www.codacy.com/gh/assimp/assimp/dashboard?utm_source=github.com&utm_medium=referral&utm_content=assimp/assimp&utm_campaign=Badge_Grade) - -[![Coverage Status](https://coveralls.io/repos/github/assimp/assimp/badge.svg?branch=master)](https://coveralls.io/github/assimp/assimp?branch=master) [![Join the chat at https://gitter.im/assimp/assimp](https://badges.gitter.im/assimp/assimp.svg)](https://gitter.im/assimp/assimp?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [![Average time to resolve an issue](http://isitmaintained.com/badge/resolution/assimp/assimp.svg)](http://isitmaintained.com/project/assimp/assimp "Average time to resolve an issue") [![Percentage of issues still open](http://isitmaintained.com/badge/open/assimp/assimp.svg)](http://isitmaintained.com/project/assimp/assimp "Percentage of issues still open")
APIs are provided for C and C++. There are various bindings to other languages (C#, Java, Python, Delphi, D). Assimp also runs on Android and iOS. -Additionally, assimp features various __mesh post processing tools__: normals and tangent space generation, triangulation, vertex cache locality optimization, removal of degenerate primitives and duplicate vertices, sorting by primitive type, merging of redundant materials and many more. +Additionally, assimp features various __mesh post-processing tools__: normals and tangent space generation, triangulation, vertex cache locality optimization, removal of degenerate primitives and duplicate vertices, sorting by primitive type, merging of redundant materials and many more. ### Latest Doc's ### Please check the latest documents at [Asset-Importer-Lib-Doc](https://assimp-docs.readthedocs.io/en/latest/). @@ -58,20 +52,21 @@ Take a look into the https://github.com/assimp/assimp/blob/master/Build.md file. ### Other tools ### [open3mod](https://github.com/acgessler/open3mod) is a powerful 3D model viewer based on Assimp's import and export abilities. +[Assimp-Viewer(]https://github.com/assimp/assimp_view) is an experimental implementation for an Asset-Viewer based on ImGUI and Assimp (experimental). #### Repository structure #### -Open Asset Import Library is implemented in C++. The directory structure looks like: +Open Asset Import Library is implemented in C++. The directory structure looks like this: /code Source code /contrib Third-party libraries /doc Documentation (doxysource and pre-compiled docs) - /fuzz Contains the test-code for the Google-Fuzzer project + /fuzz Contains the test code for the Google Fuzzer project /include Public header C and C++ header files - /scripts Scripts used to generate the loading code for some formats + /scripts Scripts are used to generate the loading code for some formats /port Ports to other languages and scripts to maintain those. /test Unit- and regression tests, test suite of models /tools Tools (old assimp viewer, command line `assimp`) - /samples A small number of samples to illustrate possible use-cases for Assimp + /samples A small number of samples to illustrate possible use cases for Assimp The source code is organized in the following way: @@ -79,9 +74,9 @@ The source code is organized in the following way: code/CApi Special implementations which are only used for the C-API code/Geometry A collection of geometry tools code/Material The material system - code/PBR An exporter for physical based models + code/PBR An exporter for physical-based models code/PostProcessing The post-processing steps - code/AssetLib/ Implementation for import and export for the format + code/AssetLib/ Implementation for import and export of the format ### Contributing ### Contributions to assimp are highly appreciated. The easiest way to get involved is to submit @@ -118,4 +113,4 @@ and don't sue us if our code doesn't work. Note that, unlike LGPLed code, you ma For the legal details, see the `LICENSE` file. ### Why this name ### -Sorry, we're germans :-), no english native speakers ... +Sorry, we're germans :-), no English native speakers ... diff --git a/code/AssetLib/3DS/3DSConverter.cpp b/code/AssetLib/3DS/3DSConverter.cpp index b4f625b76..b99e9f798 100644 --- a/code/AssetLib/3DS/3DSConverter.cpp +++ b/code/AssetLib/3DS/3DSConverter.cpp @@ -52,9 +52,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include -using namespace Assimp; +namespace Assimp { -static const unsigned int NotSet = 0xcdcdcdcd; +static constexpr unsigned int NotSet = 0xcdcdcdcd; // ------------------------------------------------------------------------------------------------ // Setup final material indices, generae a default material if necessary @@ -68,7 +68,7 @@ void Discreet3DSImporter::ReplaceDefaultMaterial() { unsigned int idx(NotSet); for (unsigned int i = 0; i < mScene->mMaterials.size(); ++i) { std::string s = mScene->mMaterials[i].mName; - for (char & it : s) { + for (char &it : s) { it = static_cast(::tolower(static_cast(it))); } @@ -262,7 +262,7 @@ void Discreet3DSImporter::ConvertMaterial(D3DS::Material &oldMat, unsigned int iWire = 1; mat.AddProperty((int *)&iWire, 1, AI_MATKEY_ENABLE_WIREFRAME); } - [[fallthrough]]; + [[fallthrough]]; case D3DS::Discreet3DS::Gouraud: eShading = aiShadingMode_Gouraud; @@ -805,4 +805,6 @@ void Discreet3DSImporter::ConvertScene(aiScene *pcOut) { } } +} // namespace Assimp + #endif // !! ASSIMP_BUILD_NO_3DS_IMPORTER diff --git a/code/AssetLib/3DS/3DSExporter.h b/code/AssetLib/3DS/3DSExporter.h index 82ec3512f..66e91e10d 100644 --- a/code/AssetLib/3DS/3DSExporter.h +++ b/code/AssetLib/3DS/3DSExporter.h @@ -4,7 +4,6 @@ Open Asset Import Library (assimp) Copyright (c) 2006-2022, assimp team - All rights reserved. Redistribution and use of this software in source and binary forms, @@ -57,8 +56,7 @@ struct aiNode; struct aiMaterial; struct aiMesh; -namespace Assimp -{ +namespace Assimp { // ------------------------------------------------------------------------------------------------ /** @@ -88,7 +86,7 @@ private: std::map trafos; - typedef std::multimap MeshesByNodeMap; + using MeshesByNodeMap = std::multimap; MeshesByNodeMap meshes; }; diff --git a/code/AssetLib/3DS/3DSLoader.cpp b/code/AssetLib/3DS/3DSLoader.cpp index aa29956df..a2dcc32ac 100644 --- a/code/AssetLib/3DS/3DSLoader.cpp +++ b/code/AssetLib/3DS/3DSLoader.cpp @@ -54,9 +54,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include -using namespace Assimp; +namespace Assimp { -static const aiImporterDesc desc = { +static constexpr aiImporterDesc desc = { "Discreet 3DS Importer", "", "", @@ -103,10 +103,6 @@ Discreet3DSImporter::Discreet3DSImporter() : // empty } -// ------------------------------------------------------------------------------------------------ -// Destructor, private as well -Discreet3DSImporter::~Discreet3DSImporter() = default; - // ------------------------------------------------------------------------------------------------ // Returns whether the class can handle the format of the given file. bool Discreet3DSImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /*checkSig*/) const { @@ -1339,4 +1335,6 @@ void Discreet3DSImporter::ParseColorChunk(aiColor3D *out, bool acceptPercent) { (void)bGamma; } +} // namespace Assimp + #endif // !! ASSIMP_BUILD_NO_3DS_IMPORTER diff --git a/code/AssetLib/3DS/3DSLoader.h b/code/AssetLib/3DS/3DSLoader.h index 6bd73f412..c579507e0 100644 --- a/code/AssetLib/3DS/3DSLoader.h +++ b/code/AssetLib/3DS/3DSLoader.h @@ -59,7 +59,6 @@ struct aiNode; namespace Assimp { - using namespace D3DS; // --------------------------------------------------------------------------------- @@ -68,7 +67,7 @@ using namespace D3DS; class Discreet3DSImporter : public BaseImporter { public: Discreet3DSImporter(); - ~Discreet3DSImporter() override; + ~Discreet3DSImporter() override = default; // ------------------------------------------------------------------- /** Returns whether the class can handle the format of the given file. diff --git a/code/AssetLib/3MF/D3MFImporter.cpp b/code/AssetLib/3MF/D3MFImporter.cpp index 5d9644fa5..e8529064c 100644 --- a/code/AssetLib/3MF/D3MFImporter.cpp +++ b/code/AssetLib/3MF/D3MFImporter.cpp @@ -68,7 +68,7 @@ namespace Assimp { using namespace D3MF; -static const aiImporterDesc desc = { +static constexpr aiImporterDesc desc = { "3mf Importer", "", "", @@ -81,10 +81,6 @@ static const aiImporterDesc desc = { "3mf" }; -D3MFImporter::D3MFImporter() = default; - -D3MFImporter::~D3MFImporter() = default; - bool D3MFImporter::CanRead(const std::string &filename, IOSystem *pIOHandler, bool /*checkSig*/) const { if (!ZipArchiveIOSystem::isZipArchive(pIOHandler, filename)) { return false; diff --git a/code/AssetLib/3MF/D3MFImporter.h b/code/AssetLib/3MF/D3MFImporter.h index a39ae790f..9ae68acb0 100644 --- a/code/AssetLib/3MF/D3MFImporter.h +++ b/code/AssetLib/3MF/D3MFImporter.h @@ -56,10 +56,10 @@ namespace Assimp { class D3MFImporter : public BaseImporter { public: /// @brief The default class constructor. - D3MFImporter(); + D3MFImporter() = default; /// @brief The class destructor. - ~D3MFImporter() override; + ~D3MFImporter() override = default; /// @brief Performs the data format detection. /// @param pFile The filename to check. diff --git a/code/AssetLib/3MF/D3MFOpcPackage.cpp b/code/AssetLib/3MF/D3MFOpcPackage.cpp index d833e7467..e772d8b7e 100644 --- a/code/AssetLib/3MF/D3MFOpcPackage.cpp +++ b/code/AssetLib/3MF/D3MFOpcPackage.cpp @@ -68,7 +68,7 @@ using OpcPackageRelationshipPtr = std::shared_ptr; class OpcPackageRelationshipReader { public: OpcPackageRelationshipReader(XmlParser &parser) : - m_relationShips() { + mRelations() { XmlNode root = parser.getRootNode(); ParseRootNode(root); } @@ -108,13 +108,13 @@ public: relPtr->type = currentNode.attribute(XmlTag::RELS_ATTRIB_TYPE).as_string(); relPtr->target = currentNode.attribute(XmlTag::RELS_ATTRIB_TARGET).as_string(); if (validateRels(relPtr)) { - m_relationShips.push_back(relPtr); + mRelations.push_back(relPtr); } } } } - std::vector m_relationShips; + std::vector mRelations; }; static bool IsEmbeddedTexture( const std::string &filename ) { @@ -214,11 +214,11 @@ std::string D3MFOpcPackage::ReadPackageRootRelationship(IOStream *stream) { OpcPackageRelationshipReader reader(xmlParser); - auto itr = std::find_if(reader.m_relationShips.begin(), reader.m_relationShips.end(), [](const OpcPackageRelationshipPtr &rel) { + auto itr = std::find_if(reader.mRelations.begin(), reader.mRelations.end(), [](const OpcPackageRelationshipPtr &rel) { return rel->type == XmlTag::PACKAGE_START_PART_RELATIONSHIP_TYPE; }); - if (itr == reader.m_relationShips.end()) { + if (itr == reader.mRelations.end()) { throw DeadlyImportError("Cannot find ", XmlTag::PACKAGE_START_PART_RELATIONSHIP_TYPE); } diff --git a/code/AssetLib/3MF/XmlSerializer.cpp b/code/AssetLib/3MF/XmlSerializer.cpp index c77111728..5fcdc0ccc 100644 --- a/code/AssetLib/3MF/XmlSerializer.cpp +++ b/code/AssetLib/3MF/XmlSerializer.cpp @@ -49,12 +49,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. namespace Assimp { namespace D3MF { -static const int IdNotSet = -1; +static constexpr int IdNotSet = -1; namespace { -static const size_t ColRGBA_Len = 9; -static const size_t ColRGB_Len = 7; +static constexpr size_t ColRGBA_Len = 9; +static constexpr size_t ColRGB_Len = 7; // format of the color string: #RRGGBBAA or #RRGGBB (3MF Core chapter 5.1.1) bool validateColorString(const char *color) { diff --git a/code/AssetLib/AC/ACLoader.cpp b/code/AssetLib/AC/ACLoader.cpp index e93fba5f0..1bb77c441 100644 --- a/code/AssetLib/AC/ACLoader.cpp +++ b/code/AssetLib/AC/ACLoader.cpp @@ -60,9 +60,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include -using namespace Assimp; +namespace Assimp { -static const aiImporterDesc desc = { +static constexpr aiImporterDesc desc = { "AC3D Importer", "", "", @@ -862,4 +862,6 @@ void AC3DImporter::InternReadFile(const std::string &pFile, } } +} // namespace Assimp + #endif //!defined ASSIMP_BUILD_NO_AC_IMPORTER diff --git a/code/AssetLib/AMF/AMFImporter.cpp b/code/AssetLib/AMF/AMFImporter.cpp index ff581b492..eabdb35e1 100644 --- a/code/AssetLib/AMF/AMFImporter.cpp +++ b/code/AssetLib/AMF/AMFImporter.cpp @@ -53,7 +53,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. namespace Assimp { -const aiImporterDesc AMFImporter::Description = { +static constexpr aiImporterDesc Description = { "Additive manufacturing file format(AMF) Importer", "smalcom", "", diff --git a/code/AssetLib/AMF/AMFImporter.hpp b/code/AssetLib/AMF/AMFImporter.hpp index 27f733043..fbaf4fc6d 100644 --- a/code/AssetLib/AMF/AMFImporter.hpp +++ b/code/AssetLib/AMF/AMFImporter.hpp @@ -98,8 +98,12 @@ namespace Assimp { /// old - and children , , , , , /// class AMFImporter : public BaseImporter { -private: - struct SPP_Material; // forward declaration + using AMFMetaDataArray = std::vector; + using MeshArray = std::vector; + using NodeArray = std::vector; + +public: + struct SPP_Material; /// Data type for post-processing step. More suitable container for part of material's composition. struct SPP_Composite { @@ -107,22 +111,6 @@ private: std::string Formula; ///< Formula for calculating ratio of \ref Material. }; - /// \struct SPP_Material - /// Data type for post-processing step. More suitable container for material. - struct SPP_Material { - std::string ID; ///< Material ID. - std::list Metadata; ///< Metadata of material. - AMFColor *Color; ///< Color of material. - std::list Composition; ///< List of child materials if current material is composition of few another. - - /// Return color calculated for specified coordinate. - /// \param [in] pX - "x" coordinate. - /// \param [in] pY - "y" coordinate. - /// \param [in] pZ - "z" coordinate. - /// \return calculated color. - aiColor4D GetColor(const float pX, const float pY, const float pZ) const; - }; - /// Data type for post-processing step. More suitable container for texture. struct SPP_Texture { std::string ID; @@ -139,10 +127,52 @@ private: const AMFTexMap *TexMap; ///< Face texture mapping data. Equal to nullptr if texture mapping is not set for the face. }; - using AMFMetaDataArray = std::vector; - using MeshArray = std::vector; - using NodeArray = std::vector; + /// Data type for post-processing step. More suitable container for material. + struct SPP_Material { + std::string ID; ///< Material ID. + std::list Metadata; ///< Metadata of material. + AMFColor *Color; ///< Color of material. + std::list Composition; ///< List of child materials if current material is composition of few another. + /// Return color calculated for specified coordinate. + /// \param [in] pX - "x" coordinate. + /// \param [in] pY - "y" coordinate. + /// \param [in] pZ - "z" coordinate. + /// \return calculated color. + aiColor4D GetColor(const float pX, const float pY, const float pZ) const; + }; + + /// Default constructor. + AMFImporter() AI_NO_EXCEPT; + + /// Default destructor. + ~AMFImporter() override; + + /// Parse AMF file and fill scene graph. The function has no return value. Result can be found by analyzing the generated graph. + /// Also exception can be thrown if trouble will found. + /// \param [in] pFile - name of file to be parsed. + /// \param [in] pIOHandler - pointer to IO helper object. + void ParseFile(const std::string &pFile, IOSystem *pIOHandler); + void ParseHelper_Node_Enter(AMFNodeElementBase *child); + void ParseHelper_Node_Exit(); + bool CanRead(const std::string &pFile, IOSystem *pIOHandler, bool pCheckSig) const override; + void InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler) override; + const aiImporterDesc *GetInfo() const override; + bool Find_NodeElement(const std::string &pID, const AMFNodeElementBase::EType pType, AMFNodeElementBase **pNodeElement) const; + bool Find_ConvertedNode(const std::string &pID, NodeArray &nodeArray, aiNode **pNode) const; + bool Find_ConvertedMaterial(const std::string &pID, const SPP_Material **pConvertedMaterial) const; + AI_WONT_RETURN void Throw_CloseNotFound(const std::string &nodeName) AI_WONT_RETURN_SUFFIX; + AI_WONT_RETURN void Throw_IncorrectAttr(const std::string &nodeName, const std::string &pAttrName) AI_WONT_RETURN_SUFFIX; + AI_WONT_RETURN void Throw_IncorrectAttrValue(const std::string &nodeName, const std::string &pAttrName) AI_WONT_RETURN_SUFFIX; + AI_WONT_RETURN void Throw_MoreThanOnceDefined(const std::string &nodeName, const std::string &pNodeType, const std::string &pDescription) AI_WONT_RETURN_SUFFIX; + AI_WONT_RETURN void Throw_ID_NotFound(const std::string &pID) const AI_WONT_RETURN_SUFFIX; + void XML_CheckNode_MustHaveChildren(pugi::xml_node &node); + bool XML_SearchNode(const std::string &nodeName); + void ParseHelper_FixTruncatedFloatString(const char *pInStr, std::string &pOutString); + AMFImporter(const AMFImporter &pScene) = delete; + AMFImporter &operator=(const AMFImporter &pScene) = delete; + +private: /// Clear all temporary data. void Clear(); @@ -262,40 +292,9 @@ private: /// \param [in] pUseOldName - if true then use old name of node(and children) - , instead of new name - . void ParseNode_TexMap(XmlNode &node, const bool pUseOldName = false); -public: - /// Default constructor. - AMFImporter() AI_NO_EXCEPT; - /// Default destructor. - ~AMFImporter() override; - - /// Parse AMF file and fill scene graph. The function has no return value. Result can be found by analyzing the generated graph. - /// Also exception can be thrown if trouble will found. - /// \param [in] pFile - name of file to be parsed. - /// \param [in] pIOHandler - pointer to IO helper object. - void ParseFile(const std::string &pFile, IOSystem *pIOHandler); - void ParseHelper_Node_Enter(AMFNodeElementBase *child); - void ParseHelper_Node_Exit(); - bool CanRead(const std::string &pFile, IOSystem *pIOHandler, bool pCheckSig) const override; - void InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler) override; - const aiImporterDesc *GetInfo() const override; - bool Find_NodeElement(const std::string &pID, const AMFNodeElementBase::EType pType, AMFNodeElementBase **pNodeElement) const; - bool Find_ConvertedNode(const std::string &pID, NodeArray &nodeArray, aiNode **pNode) const; - bool Find_ConvertedMaterial(const std::string &pID, const SPP_Material **pConvertedMaterial) const; - AI_WONT_RETURN void Throw_CloseNotFound(const std::string &nodeName) AI_WONT_RETURN_SUFFIX; - AI_WONT_RETURN void Throw_IncorrectAttr(const std::string &nodeName, const std::string &pAttrName) AI_WONT_RETURN_SUFFIX; - AI_WONT_RETURN void Throw_IncorrectAttrValue(const std::string &nodeName, const std::string &pAttrName) AI_WONT_RETURN_SUFFIX; - AI_WONT_RETURN void Throw_MoreThanOnceDefined(const std::string &nodeName, const std::string &pNodeType, const std::string &pDescription) AI_WONT_RETURN_SUFFIX; - AI_WONT_RETURN void Throw_ID_NotFound(const std::string &pID) const AI_WONT_RETURN_SUFFIX; - void XML_CheckNode_MustHaveChildren(pugi::xml_node &node); - bool XML_SearchNode(const std::string &nodeName); - void ParseHelper_FixTruncatedFloatString(const char *pInStr, std::string &pOutString); - AMFImporter(const AMFImporter &pScene) = delete; - AMFImporter &operator=(const AMFImporter &pScene) = delete; private: - static const aiImporterDesc Description; - AMFNodeElementBase *mNodeElement_Cur; ///< Current element. std::list mNodeElement_List; ///< All elements of scene graph. XmlParser *mXmlParser; diff --git a/code/AssetLib/ASE/ASELoader.cpp b/code/AssetLib/ASE/ASELoader.cpp index 4617c9ed4..94e213fb3 100644 --- a/code/AssetLib/ASE/ASELoader.cpp +++ b/code/AssetLib/ASE/ASELoader.cpp @@ -63,10 +63,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // utilities #include -using namespace Assimp; +namespace Assimp { using namespace Assimp::ASE; -static const aiImporterDesc desc = { +static constexpr aiImporterDesc desc = { "ASE Importer", "", "", @@ -1262,6 +1262,8 @@ bool ASEImporter::GenerateNormals(ASE::Mesh &mesh) { return false; } +} + #endif // ASSIMP_BUILD_NO_3DS_IMPORTER #endif // !! ASSIMP_BUILD_NO_BASE_IMPORTER diff --git a/code/AssetLib/ASE/ASEParser.cpp b/code/AssetLib/ASE/ASEParser.cpp index c43eb42ff..90f462598 100644 --- a/code/AssetLib/ASE/ASEParser.cpp +++ b/code/AssetLib/ASE/ASEParser.cpp @@ -53,7 +53,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include -using namespace Assimp; +namespace Assimp { using namespace Assimp::ASE; // ------------------------------------------------------------------------------------------------ @@ -1864,6 +1864,8 @@ void Parser::ParseLV4MeshLong(unsigned int &iOut) { iOut = strtoul10(filePtr, &filePtr); } +} + #endif // ASSIMP_BUILD_NO_3DS_IMPORTER #endif // !! ASSIMP_BUILD_NO_BASE_IMPORTER diff --git a/code/AssetLib/Assbin/AssbinLoader.cpp b/code/AssetLib/Assbin/AssbinLoader.cpp index f7b35636c..6995ea976 100644 --- a/code/AssetLib/Assbin/AssbinLoader.cpp +++ b/code/AssetLib/Assbin/AssbinLoader.cpp @@ -65,7 +65,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. using namespace Assimp; -static const aiImporterDesc desc = { +static constexpr aiImporterDesc desc = { "Assimp Binary Importer", "Gargaj / Conspiracy", "", diff --git a/code/AssetLib/B3D/B3DImporter.cpp b/code/AssetLib/B3D/B3DImporter.cpp index bf8145798..670f3de53 100644 --- a/code/AssetLib/B3D/B3DImporter.cpp +++ b/code/AssetLib/B3D/B3DImporter.cpp @@ -59,10 +59,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include -using namespace Assimp; +namespace Assimp { using namespace std; -static const aiImporterDesc desc = { +static constexpr aiImporterDesc desc = { "BlitzBasic 3D Importer", "", "", @@ -79,9 +79,9 @@ static const aiImporterDesc desc = { #pragma warning(disable : 4018) #endif -//#define DEBUG_B3D +// #define DEBUG_B3D -template +template void DeleteAllBarePointers(std::vector &x) { for (auto p : x) { delete p; @@ -329,7 +329,7 @@ void B3DImporter::ReadBRUS() { mat->AddProperty(&i, 1, AI_MATKEY_TWOSIDED); } - //Textures + // Textures for (int i = 0; i < n_texs; ++i) { int texid = ReadInt(); if (texid < -1 || (texid >= 0 && texid >= static_cast(_textures.size()))) { @@ -372,7 +372,7 @@ void B3DImporter::ReadVRTS() { } if (_vflags & 2) { - ReadQuat(); //skip v 4bytes... + ReadQuat(); // skip v 4bytes... } for (int j = 0; j < _tcsets; ++j) { @@ -704,22 +704,22 @@ void B3DImporter::ReadBB3D(aiScene *scene) { } } - //nodes + // nodes scene->mRootNode = _nodes[0]; _nodes.clear(); // node ownership now belongs to scene - //material + // material if (!_materials.size()) { _materials.emplace_back(std::unique_ptr(new aiMaterial)); } scene->mNumMaterials = static_cast(_materials.size()); scene->mMaterials = unique_to_array(_materials); - //meshes + // meshes scene->mNumMeshes = static_cast(_meshes.size()); scene->mMeshes = unique_to_array(_meshes); - //animations + // animations if (_animations.size() == 1 && _nodeAnims.size()) { aiAnimation *anim = _animations.back().get(); @@ -738,4 +738,6 @@ void B3DImporter::ReadBB3D(aiScene *scene) { flip.Execute(scene); } +} // namespace Assimp + #endif // !! ASSIMP_BUILD_NO_B3D_IMPORTER diff --git a/code/AssetLib/BVH/BVHLoader.cpp b/code/AssetLib/BVH/BVHLoader.cpp index d92887c9e..4d2cfde15 100644 --- a/code/AssetLib/BVH/BVHLoader.cpp +++ b/code/AssetLib/BVH/BVHLoader.cpp @@ -55,10 +55,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include -using namespace Assimp; +namespace Assimp { + using namespace Assimp::Formatter; -static const aiImporterDesc desc = { +static constexpr aiImporterDesc desc = { "BVH Importer (MoCap)", "", "", @@ -73,8 +74,8 @@ static const aiImporterDesc desc = { // ------------------------------------------------------------------------------------------------ // Aborts the file reading with an exception -template -AI_WONT_RETURN void BVHLoader::ThrowException(T&&... args) { +template +AI_WONT_RETURN void BVHLoader::ThrowException(T &&...args) { throw DeadlyImportError(mFileName, ":", mLine, " - ", args...); } @@ -426,7 +427,7 @@ void BVHLoader::CreateAnimation(aiScene *pScene) { nodeAnim->mNodeName.Set(nodeName); std::map channelMap; - //Build map of channels + // Build map of channels for (unsigned int channel = 0; channel < node.mChannels.size(); ++channel) { channelMap[node.mChannels[channel]] = channel; } @@ -441,7 +442,7 @@ void BVHLoader::CreateAnimation(aiScene *pScene) { // Now compute all translations for (BVHLoader::ChannelType channel = Channel_PositionX; channel <= Channel_PositionZ; channel = (BVHLoader::ChannelType)(channel + 1)) { - //Find channel in node + // Find channel in node std::map::iterator mapIter = channelMap.find(channel); if (mapIter == channelMap.end()) @@ -485,30 +486,27 @@ void BVHLoader::CreateAnimation(aiScene *pScene) { for (unsigned int fr = 0; fr < mAnimNumFrames; ++fr) { aiMatrix4x4 temp; aiMatrix3x3 rotMatrix; - for (unsigned int channelIdx = 0; channelIdx < node.mChannels.size(); ++ channelIdx) { - switch (node.mChannels[channelIdx]) { - case Channel_RotationX: - { + for (unsigned int channelIdx = 0; channelIdx < node.mChannels.size(); ++channelIdx) { + switch (node.mChannels[channelIdx]) { + case Channel_RotationX: { const float angle = node.mChannelValues[fr * node.mChannels.size() + channelIdx] * float(AI_MATH_PI) / 180.0f; - aiMatrix4x4::RotationX( angle, temp); rotMatrix *= aiMatrix3x3( temp); - } - break; - case Channel_RotationY: - { + aiMatrix4x4::RotationX(angle, temp); + rotMatrix *= aiMatrix3x3(temp); + } break; + case Channel_RotationY: { const float angle = node.mChannelValues[fr * node.mChannels.size() + channelIdx] * float(AI_MATH_PI) / 180.0f; - aiMatrix4x4::RotationY( angle, temp); rotMatrix *= aiMatrix3x3( temp); - } - break; - case Channel_RotationZ: - { + aiMatrix4x4::RotationY(angle, temp); + rotMatrix *= aiMatrix3x3(temp); + } break; + case Channel_RotationZ: { const float angle = node.mChannelValues[fr * node.mChannels.size() + channelIdx] * float(AI_MATH_PI) / 180.0f; - aiMatrix4x4::RotationZ( angle, temp); rotMatrix *= aiMatrix3x3( temp); - } - break; + aiMatrix4x4::RotationZ(angle, temp); + rotMatrix *= aiMatrix3x3(temp); + } break; default: break; - } - } + } + } rotkey->mTime = double(fr); rotkey->mValue = aiQuaternion(rotMatrix); ++rotkey; @@ -525,4 +523,6 @@ void BVHLoader::CreateAnimation(aiScene *pScene) { } } +} // namespace Assimp + #endif // !! ASSIMP_BUILD_NO_BVH_IMPORTER diff --git a/code/AssetLib/Blender/BlenderLoader.cpp b/code/AssetLib/Blender/BlenderLoader.cpp index 5c6e7bc5b..35b35f08d 100644 --- a/code/AssetLib/Blender/BlenderLoader.cpp +++ b/code/AssetLib/Blender/BlenderLoader.cpp @@ -69,11 +69,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // zlib is needed for compressed blend files #ifndef ASSIMP_BUILD_NO_COMPRESSED_BLEND #include "Common/Compression.h" -/* #ifdef ASSIMP_BUILD_NO_OWN_ZLIB -# include -# else -# include "../contrib/zlib/zlib.h" -# endif*/ #endif namespace Assimp { @@ -89,7 +84,7 @@ using namespace Assimp; using namespace Assimp::Blender; using namespace Assimp::Formatter; -static const aiImporterDesc blenderDesc = { +static constexpr aiImporterDesc blenderDesc = { "Blender 3D Importer (http://www.blender3d.org)", "", "", diff --git a/code/AssetLib/COB/COBLoader.cpp b/code/AssetLib/COB/COBLoader.cpp index 20df53f75..9a6e32f6d 100644 --- a/code/AssetLib/COB/COBLoader.cpp +++ b/code/AssetLib/COB/COBLoader.cpp @@ -61,11 +61,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include -using namespace Assimp; +namespace Assimp { using namespace Assimp::COB; using namespace Assimp::Formatter; -static const float units[] = { +static constexpr float units[] = { 1000.f, 100.f, 1.f, @@ -76,7 +76,7 @@ static const float units[] = { 1.f / 1609.344f }; -static const aiImporterDesc desc = { +static constexpr aiImporterDesc desc = { "TrueSpace Object Importer", "", "", @@ -89,14 +89,6 @@ static const aiImporterDesc desc = { "cob scn" }; -// ------------------------------------------------------------------------------------------------ -// Constructor to be privately used by Importer -COBImporter::COBImporter() = default; - -// ------------------------------------------------------------------------------------------------ -// Destructor, private as well -COBImporter::~COBImporter() = default; - // ------------------------------------------------------------------------------------------------ // Returns whether the class can handle the format of the given file. bool COBImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /*checkSig*/) const { @@ -1172,4 +1164,6 @@ void COBImporter::ReadUnit_Binary(COB::Scene &out, StreamReaderLE &reader, const ASSIMP_LOG_WARN("`Unit` chunk ", nfo.id, " is a child of ", nfo.parent_id, " which does not exist"); } +} + #endif // ASSIMP_BUILD_NO_COB_IMPORTER diff --git a/code/AssetLib/COB/COBLoader.h b/code/AssetLib/COB/COBLoader.h index e6eb96dc1..a9755f5d7 100644 --- a/code/AssetLib/COB/COBLoader.h +++ b/code/AssetLib/COB/COBLoader.h @@ -56,16 +56,16 @@ class LineSplitter; // TinyFormatter.h namespace Formatter { -template -class basic_formatter; -typedef class basic_formatter, std::allocator> format; + template + class basic_formatter; + typedef class basic_formatter, std::allocator> format; } // namespace Formatter // COBScene.h namespace COB { -struct ChunkInfo; -struct Node; -struct Scene; + struct ChunkInfo; + struct Node; + struct Scene; } // namespace COB // ------------------------------------------------------------------------------------------- @@ -75,8 +75,8 @@ struct Scene; // ------------------------------------------------------------------------------------------- class COBImporter : public BaseImporter { public: - COBImporter(); - ~COBImporter() override; + COBImporter() = default; + ~COBImporter() override = default; // -------------------- bool CanRead(const std::string &pFile, IOSystem *pIOHandler, diff --git a/code/AssetLib/CSM/CSMLoader.cpp b/code/AssetLib/CSM/CSMLoader.cpp index db152f453..20f2343f5 100644 --- a/code/AssetLib/CSM/CSMLoader.cpp +++ b/code/AssetLib/CSM/CSMLoader.cpp @@ -44,9 +44,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. /** @file CSMLoader.cpp * Implementation of the CSM importer class. */ - - - #ifndef ASSIMP_BUILD_NO_CSM_IMPORTER #include "CSMLoader.h" @@ -63,7 +60,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. using namespace Assimp; -static const aiImporterDesc desc = { +static constexpr aiImporterDesc desc = { "CharacterStudio Motion Importer (MoCap)", "", "", @@ -79,13 +76,9 @@ static const aiImporterDesc desc = { // ------------------------------------------------------------------------------------------------ // Constructor to be privately used by Importer -CSMImporter::CSMImporter() -: noSkeletonMesh() -{} - -// ------------------------------------------------------------------------------------------------ -// Destructor, private as well -CSMImporter::~CSMImporter() = default; +CSMImporter::CSMImporter() : noSkeletonMesh(){ + // empty +} // ------------------------------------------------------------------------------------------------ // Returns whether the class can handle the format of the given file. diff --git a/code/AssetLib/CSM/CSMLoader.h b/code/AssetLib/CSM/CSMLoader.h index e9c4cd5ee..fc9017d17 100644 --- a/code/AssetLib/CSM/CSMLoader.h +++ b/code/AssetLib/CSM/CSMLoader.h @@ -61,7 +61,7 @@ namespace Assimp { class CSMImporter : public BaseImporter { public: CSMImporter(); - ~CSMImporter() override; + ~CSMImporter() override = default; // ------------------------------------------------------------------- bool CanRead(const std::string &pFile, IOSystem *pIOHandler, @@ -81,9 +81,8 @@ protected: private: bool noSkeletonMesh; -}; // end of class CSMImporter +}; -} // end of namespace Assimp +} // namespace Assimp #endif // AI_AC3DIMPORTER_H_INC - diff --git a/code/AssetLib/Collada/ColladaLoader.cpp b/code/AssetLib/Collada/ColladaLoader.cpp index e1f19a5ed..41e529de0 100644 --- a/code/AssetLib/Collada/ColladaLoader.cpp +++ b/code/AssetLib/Collada/ColladaLoader.cpp @@ -64,7 +64,7 @@ namespace Assimp { using namespace Assimp::Formatter; using namespace Assimp::Collada; -static const aiImporterDesc desc = { +static constexpr aiImporterDesc desc = { "Collada Importer", "", "", @@ -101,10 +101,6 @@ ColladaLoader::ColladaLoader() : // empty } -// ------------------------------------------------------------------------------------------------ -// Destructor, private as well -ColladaLoader::~ColladaLoader() = default; - // ------------------------------------------------------------------------------------------------ // Returns whether the class can handle the format of the given file. bool ColladaLoader::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /*checkSig*/) const { diff --git a/code/AssetLib/Collada/ColladaLoader.h b/code/AssetLib/Collada/ColladaLoader.h index 74b5c06b7..3cea7f531 100644 --- a/code/AssetLib/Collada/ColladaLoader.h +++ b/code/AssetLib/Collada/ColladaLoader.h @@ -86,7 +86,7 @@ public: ColladaLoader(); /// The class destructor. - ~ColladaLoader() override; + ~ColladaLoader() override = default; /// Returns whether the class can handle the format of the given file. /// @see BaseImporter::CanRead() for more details. diff --git a/code/AssetLib/DXF/DXFLoader.cpp b/code/AssetLib/DXF/DXFLoader.cpp index dae665388..f69cdfce2 100644 --- a/code/AssetLib/DXF/DXFLoader.cpp +++ b/code/AssetLib/DXF/DXFLoader.cpp @@ -70,7 +70,7 @@ static const aiColor4D AI_DXF_DEFAULT_COLOR(aiColor4D(0.6f, 0.6f, 0.6f, 0.6f)); // color indices for DXF - 16 are supported, the table is // taken directly from the DXF spec. -static aiColor4D g_aclrDxfIndexColors[] = { +static const aiColor4D g_aclrDxfIndexColors[] = { aiColor4D(0.6f, 0.6f, 0.6f, 1.0f), aiColor4D (1.0f, 0.0f, 0.0f, 1.0f), // red aiColor4D (0.0f, 1.0f, 0.0f, 1.0f), // green @@ -97,7 +97,7 @@ static const int GroupCode_XComp = 10; static const int GroupCode_YComp = 20; static const int GroupCode_ZComp = 30; -static const aiImporterDesc desc = { +static constexpr aiImporterDesc desc = { "Drawing Interchange Format (DXF) Importer", "", "", diff --git a/code/AssetLib/FBX/FBXBinaryTokenizer.cpp b/code/AssetLib/FBX/FBXBinaryTokenizer.cpp index 8d79e2339..55424a6a8 100644 --- a/code/AssetLib/FBX/FBXBinaryTokenizer.cpp +++ b/code/AssetLib/FBX/FBXBinaryTokenizer.cpp @@ -51,6 +51,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "FBXUtil.h" #include #include +#include #include #include #include diff --git a/code/AssetLib/FBX/FBXConverter.cpp b/code/AssetLib/FBX/FBXConverter.cpp index 498da43ca..3538e84a8 100644 --- a/code/AssetLib/FBX/FBXConverter.cpp +++ b/code/AssetLib/FBX/FBXConverter.cpp @@ -577,16 +577,17 @@ void FBXConverter::GetRotationMatrix(Model::RotOrder mode, const aiVector3D &rot bool is_id[3] = { true, true, true }; aiMatrix4x4 temp[3]; - if (std::fabs(rotation.z) > angle_epsilon) { - aiMatrix4x4::RotationZ(AI_DEG_TO_RAD(rotation.z), temp[2]); + const auto rot = AI_DEG_TO_RAD(rotation); + if (std::fabs(rot.z) > angle_epsilon) { + aiMatrix4x4::RotationZ(rot.z, temp[2]); is_id[2] = false; } - if (std::fabs(rotation.y) > angle_epsilon) { - aiMatrix4x4::RotationY(AI_DEG_TO_RAD(rotation.y), temp[1]); + if (std::fabs(rot.y) > angle_epsilon) { + aiMatrix4x4::RotationY(rot.y, temp[1]); is_id[1] = false; } - if (std::fabs(rotation.x) > angle_epsilon) { - aiMatrix4x4::RotationX(AI_DEG_TO_RAD(rotation.x), temp[0]); + if (std::fabs(rot.x) > angle_epsilon) { + aiMatrix4x4::RotationX(rot.x, temp[0]); is_id[0] = false; } @@ -3225,7 +3226,6 @@ aiNodeAnim* FBXConverter::GenerateSimpleNodeAnim(const std::string& name, aiVector3D defTranslate = PropertyGet(props, "Lcl Translation", aiVector3D(0.f, 0.f, 0.f)); aiVector3D defRotation = PropertyGet(props, "Lcl Rotation", aiVector3D(0.f, 0.f, 0.f)); aiVector3D defScale = PropertyGet(props, "Lcl Scaling", aiVector3D(1.f, 1.f, 1.f)); - aiQuaternion defQuat = EulerToQuaternion(defRotation, rotOrder); aiVectorKey* outTranslations = new aiVectorKey[keyCount]; aiQuatKey* outRotations = new aiQuatKey[keyCount]; @@ -3241,8 +3241,9 @@ aiNodeAnim* FBXConverter::GenerateSimpleNodeAnim(const std::string& name, } if (keyframeLists[TransformationComp_Rotation].size() > 0) { - InterpolateKeys(outRotations, keytimes, keyframeLists[TransformationComp_Rotation], defRotation, maxTime, minTime, rotOrder); + InterpolateKeys(outRotations, keytimes, keyframeLists[TransformationComp_Rotation], AI_DEG_TO_RAD(defRotation), maxTime, minTime, rotOrder); } else { + aiQuaternion defQuat = EulerToQuaternion(AI_DEG_TO_RAD(defRotation), rotOrder); for (size_t i = 0; i < keyCount; ++i) { outRotations[i].mTime = CONVERT_FBX_TIME(keytimes[i]) * anim_fps; outRotations[i].mValue = defQuat; @@ -3264,7 +3265,7 @@ aiNodeAnim* FBXConverter::GenerateSimpleNodeAnim(const std::string& name, const aiVector3D& preRotation = PropertyGet(props, "PreRotation", ok); if (ok && preRotation.SquareLength() > zero_epsilon) { - const aiQuaternion preQuat = EulerToQuaternion(preRotation, Model::RotOrder_EulerXYZ); + const aiQuaternion preQuat = EulerToQuaternion(AI_DEG_TO_RAD(preRotation), Model::RotOrder_EulerXYZ); for (size_t i = 0; i < keyCount; ++i) { outRotations[i].mValue = preQuat * outRotations[i].mValue; } @@ -3272,7 +3273,7 @@ aiNodeAnim* FBXConverter::GenerateSimpleNodeAnim(const std::string& name, const aiVector3D& postRotation = PropertyGet(props, "PostRotation", ok); if (ok && postRotation.SquareLength() > zero_epsilon) { - const aiQuaternion postQuat = EulerToQuaternion(postRotation, Model::RotOrder_EulerXYZ); + const aiQuaternion postQuat = EulerToQuaternion(AI_DEG_TO_RAD(postRotation), Model::RotOrder_EulerXYZ); for (size_t i = 0; i < keyCount; ++i) { outRotations[i].mValue = outRotations[i].mValue * postQuat; } diff --git a/code/AssetLib/FBX/FBXExporter.cpp b/code/AssetLib/FBX/FBXExporter.cpp index 31bea76b5..2ea505618 100644 --- a/code/AssetLib/FBX/FBXExporter.cpp +++ b/code/AssetLib/FBX/FBXExporter.cpp @@ -74,8 +74,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // https://code.blender.org/2013/08/fbx-binary-file-format-specification/ // https://wiki.blender.org/index.php/User:Mont29/Foundation/FBX_File_Structure -const ai_real DEG = ai_real( 57.29577951308232087679815481 ); // degrees per radian - using namespace Assimp; using namespace Assimp::FBX; @@ -1391,7 +1389,7 @@ void FBXExporter::WriteObjects () aiMaterial* m = mScene->mMaterials[i]; // these are used to receive material data - float f; aiColor3D c; + ai_real f; aiColor3D c; // start the node record FBX::Node n("Material"); @@ -2434,7 +2432,7 @@ void FBXExporter::WriteObjects () aiMatrix4x4 m(k.mValue.GetMatrix()); aiVector3D qs, qr, qt; m.Decompose(qs, qr, qt); - qr *= DEG; + qr = AI_RAD_TO_DEG(qr); xval.push_back(qr.x); yval.push_back(qr.y); zval.push_back(qr.z); @@ -2515,9 +2513,10 @@ void FBXExporter::WriteModelNode( ); } if (r != zero) { + r = AI_RAD_TO_DEG(r); p.AddP70( "Lcl Rotation", "Lcl Rotation", "", "A", - double(DEG*r.x), double(DEG*r.y), double(DEG*r.z) + double(r.x), double(r.y), double(r.z) ); } if (s != one) { @@ -2601,8 +2600,7 @@ void FBXExporter::WriteModelNodes( transform_chain.emplace_back(elem->first, t); break; case 'r': // rotation - r *= float(DEG); - transform_chain.emplace_back(elem->first, r); + transform_chain.emplace_back(elem->first, AI_RAD_TO_DEG(r)); break; case 's': // scale transform_chain.emplace_back(elem->first, s); diff --git a/code/AssetLib/FBX/FBXImporter.cpp b/code/AssetLib/FBX/FBXImporter.cpp index 56e0f38e9..afd4b11c1 100644 --- a/code/AssetLib/FBX/FBXImporter.cpp +++ b/code/AssetLib/FBX/FBXImporter.cpp @@ -72,30 +72,25 @@ using namespace Assimp::Formatter; using namespace Assimp::FBX; namespace { - -static const aiImporterDesc desc = { - "Autodesk FBX Importer", - "", - "", - "", - aiImporterFlags_SupportTextFlavour, - 0, - 0, - 0, - 0, - "fbx" -}; + static constexpr aiImporterDesc desc = { + "Autodesk FBX Importer", + "", + "", + "", + aiImporterFlags_SupportTextFlavour, + 0, + 0, + 0, + 0, + "fbx" + }; } -// ------------------------------------------------------------------------------------------------ -// Constructor to be privately used by #Importer -FBXImporter::FBXImporter() = default; - // ------------------------------------------------------------------------------------------------ // Returns whether the class can handle the format of the given file. bool FBXImporter::CanRead(const std::string & pFile, IOSystem * pIOHandler, bool /*checkSig*/) const { // at least ASCII-FBX files usually have a 'FBX' somewhere in their head - static const char *tokens[] = { "fbx" }; + static const char *tokens[] = { " \n\r\n " }; return SearchFileHeaderForToken(pIOHandler, pFile, tokens, AI_COUNT_OF(tokens)); } diff --git a/code/AssetLib/FBX/FBXImporter.h b/code/AssetLib/FBX/FBXImporter.h index 9acabaddd..d12b45969 100644 --- a/code/AssetLib/FBX/FBXImporter.h +++ b/code/AssetLib/FBX/FBXImporter.h @@ -70,7 +70,7 @@ typedef class basic_formatter, std::allocator class FBXImporter : public BaseImporter, public LogFunctions { public: /// @brief The class constructor. - FBXImporter(); + FBXImporter() = default; /// @brief The class destructor, default implementation. ~FBXImporter() override = default; diff --git a/code/AssetLib/HMP/HMPLoader.cpp b/code/AssetLib/HMP/HMPLoader.cpp index 431783a6a..5ccb2b474 100644 --- a/code/AssetLib/HMP/HMPLoader.cpp +++ b/code/AssetLib/HMP/HMPLoader.cpp @@ -57,7 +57,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. using namespace Assimp; -static const aiImporterDesc desc = { +static constexpr aiImporterDesc desc = { "3D GameStudio Heightmap (HMP) Importer", "", "", diff --git a/code/AssetLib/IFC/IFCLoader.cpp b/code/AssetLib/IFC/IFCLoader.cpp index 89012902c..c919d9982 100644 --- a/code/AssetLib/IFC/IFCLoader.cpp +++ b/code/AssetLib/IFC/IFCLoader.cpp @@ -103,7 +103,7 @@ void ConvertUnit(const ::Assimp::STEP::EXPRESS::DataType &dt, ConversionData &co } // namespace -static const aiImporterDesc desc = { +static constexpr aiImporterDesc desc = { "Industry Foundation Classes (IFC) Importer", "", "", @@ -185,7 +185,7 @@ void IFCImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy size_t total = 0; int read = 0; do { - int bufferSize = fileInfo.uncompressed_size < INT16_MAX ? fileInfo.uncompressed_size : INT16_MAX; + unsigned bufferSize = fileInfo.uncompressed_size < INT16_MAX ? static_cast(fileInfo.uncompressed_size) : INT16_MAX; void *buffer = malloc(bufferSize); read = unzReadCurrentFile(zip, buffer, bufferSize); if (read > 0) { diff --git a/code/AssetLib/IFC/IFCOpenings.cpp b/code/AssetLib/IFC/IFCOpenings.cpp index 48b843aa1..c47446dda 100644 --- a/code/AssetLib/IFC/IFCOpenings.cpp +++ b/code/AssetLib/IFC/IFCOpenings.cpp @@ -1372,7 +1372,7 @@ std::vector GetContourInPlane2D(const std::shared_ptr& mes const std::vector& va = mesh->mVerts; if(va.size() <= 2) { std::stringstream msg; - msg << "Skipping: Only " << va.size() << " verticies in opening mesh."; + msg << "Skipping: Only " << va.size() << " vertices in opening mesh."; IFCImporter::LogDebug(msg.str().c_str()); ok = false; return contour; diff --git a/code/AssetLib/IQM/IQMImporter.cpp b/code/AssetLib/IQM/IQMImporter.cpp index 139b490d8..432c12113 100644 --- a/code/AssetLib/IQM/IQMImporter.cpp +++ b/code/AssetLib/IQM/IQMImporter.cpp @@ -59,7 +59,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // http://sauerbraten.org/iqm/ // https://github.com/lsalzman/iqm - inline void swap_block( uint32_t *block, size_t size ){ (void)block; // suppress 'unreferenced formal parameter' MSVC warning size >>= 2; @@ -67,7 +66,7 @@ inline void swap_block( uint32_t *block, size_t size ){ AI_SWAP4( block[ i ] ); } -static const aiImporterDesc desc = { +static constexpr aiImporterDesc desc = { "Inter-Quake Model Importer", "", "", @@ -100,13 +99,6 @@ bool IQMImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool c if (!pIOHandler) { return true; } - /* - * don't use CheckMagicToken because that checks with swapped bytes too, leading to false - * positives. This magic is not uint32_t, but char[4], so memcmp is the best way - - const char* tokens[] = {"3DMO", "3dmo"}; - return CheckMagicToken(pIOHandler,pFile,tokens,2,0,4); - */ std::unique_ptr pStream(pIOHandler->Open(pFile, "rb")); unsigned char data[15]; if (!pStream || 15 != pStream->Read(data, 1, 15)) { diff --git a/code/AssetLib/Irr/IRRLoader.cpp b/code/AssetLib/Irr/IRRLoader.cpp index ba6ebc964..99e053892 100644 --- a/code/AssetLib/Irr/IRRLoader.cpp +++ b/code/AssetLib/Irr/IRRLoader.cpp @@ -66,7 +66,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. using namespace Assimp; -static const aiImporterDesc desc = { +static constexpr aiImporterDesc desc = { "Irrlicht Scene Reader", "", "", @@ -575,8 +575,8 @@ void SetupMapping(aiMaterial *mat, aiTextureMapping mode, const aiVector3D &axis m->mSemantic = prop->mSemantic; m->mType = aiPTI_Float; - m->mDataLength = 12; - m->mData = new char[12]; + m->mDataLength = sizeof(aiVector3D); + m->mData = new char[m->mDataLength]; *((aiVector3D *)m->mData) = axis; p.push_back(m); } diff --git a/code/AssetLib/Irr/IRRMeshLoader.cpp b/code/AssetLib/Irr/IRRMeshLoader.cpp index 8161a2997..b35a95c12 100644 --- a/code/AssetLib/Irr/IRRMeshLoader.cpp +++ b/code/AssetLib/Irr/IRRMeshLoader.cpp @@ -56,7 +56,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. using namespace Assimp; -static const aiImporterDesc desc = { +static constexpr aiImporterDesc desc = { "Irrlicht Mesh Reader", "", "", diff --git a/code/AssetLib/LWO/LWOBLoader.cpp b/code/AssetLib/LWO/LWOBLoader.cpp index e49adcf98..4a9792b79 100644 --- a/code/AssetLib/LWO/LWOBLoader.cpp +++ b/code/AssetLib/LWO/LWOBLoader.cpp @@ -51,64 +51,56 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "LWOLoader.h" using namespace Assimp; - // ------------------------------------------------------------------------------------------------ -void LWOImporter::LoadLWOBFile() -{ +void LWOImporter::LoadLWOBFile() { LE_NCONST uint8_t* const end = mFileBuffer + fileSize; bool running = true; - while (running) - { - if (mFileBuffer + sizeof(IFF::ChunkHeader) > end)break; + while (running) { + if (mFileBuffer + sizeof(IFF::ChunkHeader) > end) + break; const IFF::ChunkHeader head = IFF::LoadChunk(mFileBuffer); - if (mFileBuffer + head.length > end) - { + if (mFileBuffer + head.length > end) { throw DeadlyImportError("LWOB: Invalid chunk length"); } uint8_t* const next = mFileBuffer+head.length; - switch (head.type) - { + switch (head.type) { // vertex list - case AI_LWO_PNTS: - { + case AI_LWO_PNTS: { if (!mCurLayer->mTempPoints.empty()) ASSIMP_LOG_WARN("LWO: PNTS chunk encountered twice"); - else LoadLWOPoints(head.length); - break; - } - // face list - case AI_LWO_POLS: - { + else + LoadLWOPoints(head.length); + } break; + case AI_LWO_POLS: { // face list + if (!mCurLayer->mFaces.empty()) + ASSIMP_LOG_WARN("LWO: POLS chunk encountered twice"); + else + LoadLWOBPolygons(head.length); + } break; + + case AI_LWO_SRFS: // list of tags + { + if (!mTags->empty()) + ASSIMP_LOG_WARN("LWO: SRFS chunk encountered twice"); + else + LoadLWOTags(head.length); + } break; - if (!mCurLayer->mFaces.empty()) - ASSIMP_LOG_WARN("LWO: POLS chunk encountered twice"); - else LoadLWOBPolygons(head.length); - break; - } - // list of tags - case AI_LWO_SRFS: - { - if (!mTags->empty()) - ASSIMP_LOG_WARN("LWO: SRFS chunk encountered twice"); - else LoadLWOTags(head.length); - break; - } + case AI_LWO_SURF: // surface chunk + { + LoadLWOBSurface(head.length); + } break; - // surface chunk - case AI_LWO_SURF: - { - LoadLWOBSurface(head.length); + default: break; - } } mFileBuffer = next; } } // ------------------------------------------------------------------------------------------------ -void LWOImporter::LoadLWOBPolygons(unsigned int length) -{ +void LWOImporter::LoadLWOBPolygons(unsigned int length) { // first find out how many faces and vertices we'll finally need LE_NCONST uint16_t* const end = (LE_NCONST uint16_t*)(mFileBuffer+length); LE_NCONST uint16_t* cursor = (LE_NCONST uint16_t*)mFileBuffer; @@ -123,8 +115,7 @@ void LWOImporter::LoadLWOBPolygons(unsigned int length) CountVertsAndFacesLWOB(iNumVertices,iNumFaces,cursor,end); // allocate the output array and copy face indices - if (iNumFaces) - { + if (iNumFaces) { cursor = (LE_NCONST uint16_t*)mFileBuffer; mCurLayer->mFaces.resize(iNumFaces); @@ -135,10 +126,8 @@ void LWOImporter::LoadLWOBPolygons(unsigned int length) // ------------------------------------------------------------------------------------------------ void LWOImporter::CountVertsAndFacesLWOB(unsigned int& verts, unsigned int& faces, - LE_NCONST uint16_t*& cursor, const uint16_t* const end, unsigned int max) -{ - while (cursor < end && max--) - { + LE_NCONST uint16_t*& cursor, const uint16_t* const end, unsigned int max) { + while (cursor < end && max--) { uint16_t numIndices; // must have 2 shorts left for numIndices and surface if (end - cursor < 2) { @@ -154,8 +143,7 @@ void LWOImporter::CountVertsAndFacesLWOB(unsigned int& verts, unsigned int& face cursor += numIndices; int16_t surface; ::memcpy(&surface, cursor++, 2); - if (surface < 0) - { + if (surface < 0) { // there are detail polygons ::memcpy(&numIndices, cursor++, 2); CountVertsAndFacesLWOB(verts,faces,cursor,end,numIndices); @@ -167,18 +155,14 @@ void LWOImporter::CountVertsAndFacesLWOB(unsigned int& verts, unsigned int& face void LWOImporter::CopyFaceIndicesLWOB(FaceList::iterator& it, LE_NCONST uint16_t*& cursor, const uint16_t* const end, - unsigned int max) -{ - while (cursor < end && max--) - { + unsigned int max) { + while (cursor < end && max--) { LWO::Face& face = *it;++it; uint16_t numIndices; ::memcpy(&numIndices, cursor++, 2); face.mNumIndices = numIndices; - if(face.mNumIndices) - { - if (cursor + face.mNumIndices >= end) - { + if(face.mNumIndices) { + if (cursor + face.mNumIndices >= end) { break; } face.mIndices = new unsigned int[face.mNumIndices]; @@ -187,8 +171,7 @@ void LWOImporter::CopyFaceIndicesLWOB(FaceList::iterator& it, uint16_t index; ::memcpy(&index, cursor++, 2); mi = index; - if (mi > mCurLayer->mTempPoints.size()) - { + if (mi > mCurLayer->mTempPoints.size()) { ASSIMP_LOG_WARN("LWOB: face index is out of range"); mi = (unsigned int)mCurLayer->mTempPoints.size()-1; } @@ -198,15 +181,13 @@ void LWOImporter::CopyFaceIndicesLWOB(FaceList::iterator& it, } int16_t surface; ::memcpy(&surface, cursor++, 2); - if (surface < 0) - { + if (surface < 0) { surface = -surface; // there are detail polygons. uint16_t numPolygons; ::memcpy(&numPolygons, cursor++, 2); - if (cursor < end) - { + if (cursor < end) { CopyFaceIndicesLWOB(it,cursor,end,numPolygons); } } @@ -215,8 +196,7 @@ void LWOImporter::CopyFaceIndicesLWOB(FaceList::iterator& it, } // ------------------------------------------------------------------------------------------------ -LWO::Texture* LWOImporter::SetupNewTextureLWOB(LWO::TextureList& list,unsigned int size) -{ +LWO::Texture* LWOImporter::SetupNewTextureLWOB(LWO::TextureList& list,unsigned int size) { list.emplace_back(); LWO::Texture* tex = &list.back(); @@ -224,8 +204,7 @@ LWO::Texture* LWOImporter::SetupNewTextureLWOB(LWO::TextureList& list,unsigned i GetS0(type,size); const char* s = type.c_str(); - if(strstr(s, "Image Map")) - { + if(strstr(s, "Image Map")) { // Determine mapping type if(strstr(s, "Planar")) tex->mapMode = LWO::Texture::Planar; @@ -237,9 +216,7 @@ LWO::Texture* LWOImporter::SetupNewTextureLWOB(LWO::TextureList& list,unsigned i tex->mapMode = LWO::Texture::Cubic; else if(strstr(s, "Front")) tex->mapMode = LWO::Texture::FrontProjection; - } - else - { + } else { // procedural or gradient, not supported ASSIMP_LOG_ERROR("LWOB: Unsupported legacy texture: ", type); } @@ -248,8 +225,7 @@ LWO::Texture* LWOImporter::SetupNewTextureLWOB(LWO::TextureList& list,unsigned i } // ------------------------------------------------------------------------------------------------ -void LWOImporter::LoadLWOBSurface(unsigned int size) -{ +void LWOImporter::LoadLWOBSurface(unsigned int size) { LE_NCONST uint8_t* const end = mFileBuffer + size; mSurfaces->push_back( LWO::Surface () ); @@ -277,148 +253,147 @@ void LWOImporter::LoadLWOBSurface(unsigned int size) } uint8_t* const next = mFileBuffer+head.length; - switch (head.type) - { - // diffuse color - case AI_LWO_COLR: - { - AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,COLR,3); - surf.mColor.r = GetU1() / 255.0f; - surf.mColor.g = GetU1() / 255.0f; - surf.mColor.b = GetU1() / 255.0f; - break; - } - // diffuse strength ... - case AI_LWO_DIFF: - { - AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,DIFF,2); - surf.mDiffuseValue = GetU2() / 255.0f; - break; - } - // specular strength ... - case AI_LWO_SPEC: - { - AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,SPEC,2); - surf.mSpecularValue = GetU2() / 255.0f; - break; - } - // luminosity ... - case AI_LWO_LUMI: - { - AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,LUMI,2); - surf.mLuminosity = GetU2() / 255.0f; - break; - } - // transparency - case AI_LWO_TRAN: - { - AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,TRAN,2); - surf.mTransparency = GetU2() / 255.0f; - break; - } - // surface flags - case AI_LWO_FLAG: - { - AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,FLAG,2); - uint16_t flag = GetU2(); - if (flag & 0x4 ) surf.mMaximumSmoothAngle = 1.56207f; - if (flag & 0x8 ) surf.mColorHighlights = 1.f; - if (flag & 0x100) surf.bDoubleSided = true; - break; - } - // maximum smoothing angle - case AI_LWO_SMAN: - { - AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,SMAN,4); - surf.mMaximumSmoothAngle = std::fabs( GetF4() ); - break; - } - // glossiness - case AI_LWO_GLOS: - { - AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,GLOS,2); - surf.mGlossiness = (float)GetU2(); - break; - } - // color texture - case AI_LWO_CTEX: - { - pTex = SetupNewTextureLWOB(surf.mColorTextures, - head.length); - break; - } - // diffuse texture - case AI_LWO_DTEX: - { - pTex = SetupNewTextureLWOB(surf.mDiffuseTextures, - head.length); - break; - } - // specular texture - case AI_LWO_STEX: - { - pTex = SetupNewTextureLWOB(surf.mSpecularTextures, - head.length); - break; - } - // bump texture - case AI_LWO_BTEX: - { - pTex = SetupNewTextureLWOB(surf.mBumpTextures, - head.length); - break; - } - // transparency texture - case AI_LWO_TTEX: - { - pTex = SetupNewTextureLWOB(surf.mOpacityTextures, - head.length); - break; - } - // texture path - case AI_LWO_TIMG: - { - if (pTex) { - GetS0(pTex->mFileName,head.length); - } else { - ASSIMP_LOG_WARN("LWOB: Unexpected TIMG chunk"); + switch (head.type) { + // diffuse color + case AI_LWO_COLR: + { + AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,COLR,3); + surf.mColor.r = GetU1() / 255.0f; + surf.mColor.g = GetU1() / 255.0f; + surf.mColor.b = GetU1() / 255.0f; + break; } - break; - } - // texture strength - case AI_LWO_TVAL: - { - AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,TVAL,1); - if (pTex) { - pTex->mStrength = (float)GetU1()/ 255.f; - } else { - ASSIMP_LOG_ERROR("LWOB: Unexpected TVAL chunk"); + // diffuse strength ... + case AI_LWO_DIFF: + { + AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,DIFF,2); + surf.mDiffuseValue = GetU2() / 255.0f; + break; } - break; - } - // texture flags - case AI_LWO_TFLG: - { - AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,TFLG,2); - - if (nullptr != pTex) { - const uint16_t s = GetU2(); - if (s & 1) - pTex->majorAxis = LWO::Texture::AXIS_X; - else if (s & 2) - pTex->majorAxis = LWO::Texture::AXIS_Y; - else if (s & 4) - pTex->majorAxis = LWO::Texture::AXIS_Z; - - if (s & 16) { - ASSIMP_LOG_WARN("LWOB: Ignoring \'negate\' flag on texture"); + // specular strength ... + case AI_LWO_SPEC: + { + AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,SPEC,2); + surf.mSpecularValue = GetU2() / 255.0f; + break; + } + // luminosity ... + case AI_LWO_LUMI: + { + AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,LUMI,2); + surf.mLuminosity = GetU2() / 255.0f; + break; + } + // transparency + case AI_LWO_TRAN: + { + AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,TRAN,2); + surf.mTransparency = GetU2() / 255.0f; + break; + } + // surface flags + case AI_LWO_FLAG: + { + AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,FLAG,2); + uint16_t flag = GetU2(); + if (flag & 0x4 ) surf.mMaximumSmoothAngle = 1.56207f; + if (flag & 0x8 ) surf.mColorHighlights = 1.f; + if (flag & 0x100) surf.bDoubleSided = true; + break; + } + // maximum smoothing angle + case AI_LWO_SMAN: + { + AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,SMAN,4); + surf.mMaximumSmoothAngle = std::fabs( GetF4() ); + break; + } + // glossiness + case AI_LWO_GLOS: + { + AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,GLOS,2); + surf.mGlossiness = (float)GetU2(); + break; + } + // color texture + case AI_LWO_CTEX: + { + pTex = SetupNewTextureLWOB(surf.mColorTextures, + head.length); + break; + } + // diffuse texture + case AI_LWO_DTEX: + { + pTex = SetupNewTextureLWOB(surf.mDiffuseTextures, + head.length); + break; + } + // specular texture + case AI_LWO_STEX: + { + pTex = SetupNewTextureLWOB(surf.mSpecularTextures, + head.length); + break; + } + // bump texture + case AI_LWO_BTEX: + { + pTex = SetupNewTextureLWOB(surf.mBumpTextures, + head.length); + break; + } + // transparency texture + case AI_LWO_TTEX: + { + pTex = SetupNewTextureLWOB(surf.mOpacityTextures, + head.length); + break; + } + // texture path + case AI_LWO_TIMG: + { + if (pTex) { + GetS0(pTex->mFileName,head.length); + } else { + ASSIMP_LOG_WARN("LWOB: Unexpected TIMG chunk"); } + break; } - else { - ASSIMP_LOG_WARN("LWOB: Unexpected TFLG chunk"); + // texture strength + case AI_LWO_TVAL: + { + AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,TVAL,1); + if (pTex) { + pTex->mStrength = (float)GetU1()/ 255.f; + } else { + ASSIMP_LOG_ERROR("LWOB: Unexpected TVAL chunk"); + } + break; + } + // texture flags + case AI_LWO_TFLG: + { + AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,TFLG,2); + + if (nullptr != pTex) { + const uint16_t s = GetU2(); + if (s & 1) + pTex->majorAxis = LWO::Texture::AXIS_X; + else if (s & 2) + pTex->majorAxis = LWO::Texture::AXIS_Y; + else if (s & 4) + pTex->majorAxis = LWO::Texture::AXIS_Z; + + if (s & 16) { + ASSIMP_LOG_WARN("LWOB: Ignoring \'negate\' flag on texture"); + } + } + else { + ASSIMP_LOG_WARN("LWOB: Unexpected TFLG chunk"); + } + break; } - break; - } } mFileBuffer = next; } diff --git a/code/AssetLib/LWS/LWSLoader.cpp b/code/AssetLib/LWS/LWSLoader.cpp index c41ff9cac..dec834495 100644 --- a/code/AssetLib/LWS/LWSLoader.cpp +++ b/code/AssetLib/LWS/LWSLoader.cpp @@ -63,7 +63,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. using namespace Assimp; -static const aiImporterDesc desc = { +static constexpr aiImporterDesc desc = { "LightWave Scene Importer", "", "", @@ -139,10 +139,6 @@ LWSImporter::LWSImporter() : // nothing to do here } -// ------------------------------------------------------------------------------------------------ -// Destructor, private as well -LWSImporter::~LWSImporter() = default; - // ------------------------------------------------------------------------------------------------ // Returns whether the class can handle the format of the given file. bool LWSImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /*checkSig*/) const { diff --git a/code/AssetLib/LWS/LWSLoader.h b/code/AssetLib/LWS/LWSLoader.h index 3df9fe9d9..4e92ef0d5 100644 --- a/code/AssetLib/LWS/LWSLoader.h +++ b/code/AssetLib/LWS/LWSLoader.h @@ -174,7 +174,7 @@ struct NodeDesc { class LWSImporter : public BaseImporter { public: LWSImporter(); - ~LWSImporter() override; + ~LWSImporter() override = default; // ------------------------------------------------------------------- // Check whether we can read a specific file diff --git a/code/AssetLib/M3D/M3DImporter.cpp b/code/AssetLib/M3D/M3DImporter.cpp index 895b2bf70..71f416139 100644 --- a/code/AssetLib/M3D/M3DImporter.cpp +++ b/code/AssetLib/M3D/M3DImporter.cpp @@ -85,7 +85,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. are listed in aiScene->mRootNode->children, but all without meshes */ -static const aiImporterDesc desc = { +static constexpr aiImporterDesc desc = { "Model 3D Importer", "", "", diff --git a/code/AssetLib/MD2/MD2Loader.cpp b/code/AssetLib/MD2/MD2Loader.cpp index ee7dbc6a6..596d26414 100644 --- a/code/AssetLib/MD2/MD2Loader.cpp +++ b/code/AssetLib/MD2/MD2Loader.cpp @@ -5,8 +5,6 @@ Open Asset Import Library (assimp) Copyright (c) 2006-2022, assimp team - - All rights reserved. Redistribution and use of this software in source and binary forms, @@ -41,7 +39,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. --------------------------------------------------------------------------- */ - #ifndef ASSIMP_BUILD_NO_MD2_IMPORTER /** @file Implementation of the MD2 importer class */ @@ -65,7 +62,7 @@ using namespace Assimp::MD2; # define ARRAYSIZE(_array) (int(sizeof(_array) / sizeof(_array[0]))) #endif -static const aiImporterDesc desc = { +static constexpr aiImporterDesc desc = { "Quake II Mesh Importer", "", "", @@ -79,7 +76,7 @@ static const aiImporterDesc desc = { }; // ------------------------------------------------------------------------------------------------ -// Helper function to lookup a normal in Quake 2's precalculated table +// Helper function to lookup a normal in Quake 2's pre-calculated table void MD2::LookupNormalIndex(uint8_t iNormalIndex,aiVector3D& vOut) { // make sure the normal index has a valid value @@ -100,10 +97,6 @@ MD2Importer::MD2Importer() fileSize() {} -// ------------------------------------------------------------------------------------------------ -// Destructor, private as well -MD2Importer::~MD2Importer() = default; - // ------------------------------------------------------------------------------------------------ // Returns whether the class can handle the format of the given file. bool MD2Importer::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool /*checkSig*/) const diff --git a/code/AssetLib/MD2/MD2Loader.h b/code/AssetLib/MD2/MD2Loader.h index a49ccb2fd..bab026ea0 100644 --- a/code/AssetLib/MD2/MD2Loader.h +++ b/code/AssetLib/MD2/MD2Loader.h @@ -63,7 +63,7 @@ using namespace MD2; class MD2Importer : public BaseImporter { public: MD2Importer(); - ~MD2Importer() override; + ~MD2Importer() override = default; // ------------------------------------------------------------------- /** Returns whether the class can handle the format of the given file. diff --git a/code/AssetLib/MD3/MD3Loader.cpp b/code/AssetLib/MD3/MD3Loader.cpp index fcb8d0c35..e743889e3 100644 --- a/code/AssetLib/MD3/MD3Loader.cpp +++ b/code/AssetLib/MD3/MD3Loader.cpp @@ -70,7 +70,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. using namespace Assimp; -static const aiImporterDesc desc = { +static constexpr aiImporterDesc desc = { "Quake III Mesh Importer", "", "", diff --git a/code/AssetLib/MD5/MD5Loader.cpp b/code/AssetLib/MD5/MD5Loader.cpp index 4236f32e9..697e758fb 100644 --- a/code/AssetLib/MD5/MD5Loader.cpp +++ b/code/AssetLib/MD5/MD5Loader.cpp @@ -64,7 +64,7 @@ using namespace Assimp; // Minimum weight value. Weights inside [-n ... n] are ignored #define AI_MD5_WEIGHT_EPSILON Math::getEpsilon() -static const aiImporterDesc desc = { +static constexpr aiImporterDesc desc = { "Doom 3 / MD5 Mesh Importer", "", "", @@ -92,10 +92,6 @@ MD5Importer::MD5Importer() : // empty } -// ------------------------------------------------------------------------------------------------ -// Destructor, private as well -MD5Importer::~MD5Importer() = default; - // ------------------------------------------------------------------------------------------------ // Returns whether the class can handle the format of the given file. bool MD5Importer::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /*checkSig*/) const { diff --git a/code/AssetLib/MD5/MD5Loader.h b/code/AssetLib/MD5/MD5Loader.h index 63fb1c36b..c213c04e6 100644 --- a/code/AssetLib/MD5/MD5Loader.h +++ b/code/AssetLib/MD5/MD5Loader.h @@ -65,7 +65,7 @@ using namespace Assimp::MD5; class MD5Importer : public BaseImporter { public: MD5Importer(); - ~MD5Importer() override; + ~MD5Importer() override = default; // ------------------------------------------------------------------- /** Returns whether the class can handle the format of the given file. diff --git a/code/AssetLib/MDC/MDCLoader.cpp b/code/AssetLib/MDC/MDCLoader.cpp index 10ea618b9..87247adec 100644 --- a/code/AssetLib/MDC/MDCLoader.cpp +++ b/code/AssetLib/MDC/MDCLoader.cpp @@ -60,7 +60,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. using namespace Assimp; using namespace Assimp::MDC; -static const aiImporterDesc desc = { +static constexpr aiImporterDesc desc = { "Return To Castle Wolfenstein Mesh Importer", "", "", @@ -103,10 +103,6 @@ MDCImporter::MDCImporter() : // empty } -// ------------------------------------------------------------------------------------------------ -// Destructor, private as well -MDCImporter::~MDCImporter() = default; - // ------------------------------------------------------------------------------------------------ // Returns whether the class can handle the format of the given file. bool MDCImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /*checkSig*/) const { diff --git a/code/AssetLib/MDC/MDCLoader.h b/code/AssetLib/MDC/MDCLoader.h index 6e67cd12f..a1f8d9fc9 100644 --- a/code/AssetLib/MDC/MDCLoader.h +++ b/code/AssetLib/MDC/MDCLoader.h @@ -62,7 +62,7 @@ using namespace MDC; class MDCImporter : public BaseImporter { public: MDCImporter(); - ~MDCImporter() override; + ~MDCImporter() override = default; // ------------------------------------------------------------------- /** Returns whether the class can handle the format of the given file. diff --git a/code/AssetLib/MDL/MDLLoader.cpp b/code/AssetLib/MDL/MDLLoader.cpp index 7b2ec7115..2b14fe980 100644 --- a/code/AssetLib/MDL/MDLLoader.cpp +++ b/code/AssetLib/MDL/MDLLoader.cpp @@ -65,7 +65,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. using namespace Assimp; -static const aiImporterDesc desc = { +static constexpr aiImporterDesc desc = { "Quake Mesh / 3D GameStudio Mesh Importer", "", "", @@ -96,10 +96,6 @@ MDLImporter::MDLImporter() : // empty } -// ------------------------------------------------------------------------------------------------ -// Destructor, private as well -MDLImporter::~MDLImporter() = default; - // ------------------------------------------------------------------------------------------------ // Returns whether the class can handle the format of the given file. bool MDLImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /*checkSig*/) const { diff --git a/code/AssetLib/MDL/MDLLoader.h b/code/AssetLib/MDL/MDLLoader.h index 44ff21e3e..333f7c8b1 100644 --- a/code/AssetLib/MDL/MDLLoader.h +++ b/code/AssetLib/MDL/MDLLoader.h @@ -39,10 +39,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ---------------------------------------------------------------------- */ - -/** @file MDLLoader.h - * @brief Declaration of the loader for MDL files - */ +/// @file MDLLoader.h +/// @brief Declaration of the loader for MDL files #pragma once #ifndef AI_MDLLOADER_H_INCLUDED #define AI_MDLLOADER_H_INCLUDED @@ -83,11 +81,10 @@ using namespace MDL; * them all with a single 1000-line function-beast. However, it has been * split into several code paths to make the code easier to read and maintain. */ -class MDLImporter : public BaseImporter -{ +class MDLImporter : public BaseImporter { public: MDLImporter(); - ~MDLImporter() override; + ~MDLImporter() override = default; // ------------------------------------------------------------------- /** Returns whether the class can handle the format of the given file. diff --git a/code/AssetLib/MMD/MMDImporter.cpp b/code/AssetLib/MMD/MMDImporter.cpp index 0905ce1e0..b96d45c98 100644 --- a/code/AssetLib/MMD/MMDImporter.cpp +++ b/code/AssetLib/MMD/MMDImporter.cpp @@ -57,7 +57,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include -static const aiImporterDesc desc = { "MMD Importer", +static constexpr aiImporterDesc desc = { "MMD Importer", "", "", "surfaces supported?", @@ -81,10 +81,6 @@ MMDImporter::MMDImporter() : m_strAbsPath = io.getOsSeparator(); } -// ------------------------------------------------------------------------------------------------ -// Destructor. -MMDImporter::~MMDImporter() = default; - // ------------------------------------------------------------------------------------------------ // Returns true, if file is an pmx file. bool MMDImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, diff --git a/code/AssetLib/MMD/MMDImporter.h b/code/AssetLib/MMD/MMDImporter.h index 36f384829..1f584bf12 100644 --- a/code/AssetLib/MMD/MMDImporter.h +++ b/code/AssetLib/MMD/MMDImporter.h @@ -50,46 +50,34 @@ struct aiMesh; namespace Assimp { // ------------------------------------------------------------------------------------------------ -/// \class MMDImporter -/// \brief Imports MMD a pmx/pmd/vmd file +/// @class MMDImporter +/// @brief Imports MMD a pmx/pmd/vmd file // ------------------------------------------------------------------------------------------------ class MMDImporter : public BaseImporter { public: - /// \brief Default constructor + /// @brief Default constructor MMDImporter(); - /// \brief Destructor - ~MMDImporter() override; + /// @brief Destructor + ~MMDImporter() override = default; public: - /// \brief Returns whether the class can handle the format of the given file. - /// \remark See BaseImporter::CanRead() for details. + /// @brief Returns whether the class can handle the format of the given file. + /// @remark See BaseImporter::CanRead() for details. bool CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const override; private: - //! \brief Appends the supported extension. const aiImporterDesc* GetInfo() const override; - - //! \brief File import implementation. void InternReadFile(const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler) override; - - //! \brief Create the data from imported content. void CreateDataFromImport(const pmx::PmxModel* pModel, aiScene* pScene); - - //! \brief Create the mesh aiMesh* CreateMesh(const pmx::PmxModel* pModel, const int indexStart, const int indexCount); - - //! \brief Create the material aiMaterial* CreateMaterial(const pmx::PmxMaterial* pMat, const pmx::PmxModel* pModel); private: - //! Data buffer std::vector m_Buffer; - //! Absolute pathname of model in file system std::string m_strAbsPath; }; -// ------------------------------------------------------------------------------------------------ } // Namespace Assimp diff --git a/code/AssetLib/MS3D/MS3DLoader.cpp b/code/AssetLib/MS3D/MS3DLoader.cpp index d4dd2be75..e0f0f8b5a 100644 --- a/code/AssetLib/MS3D/MS3DLoader.cpp +++ b/code/AssetLib/MS3D/MS3DLoader.cpp @@ -60,7 +60,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. using namespace Assimp; -static const aiImporterDesc desc = { +static constexpr aiImporterDesc desc = { "Milkshape 3D Importer", "", "", @@ -84,9 +84,6 @@ MS3DImporter::MS3DImporter() : mScene() {} -// ------------------------------------------------------------------------------------------------ -// Destructor, private as well -MS3DImporter::~MS3DImporter() = default; // ------------------------------------------------------------------------------------------------ // Returns whether the class can handle the format of the given file. bool MS3DImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool /*checkSig*/) const diff --git a/code/AssetLib/MS3D/MS3DLoader.h b/code/AssetLib/MS3D/MS3DLoader.h index 4bd417566..3e25f1f59 100644 --- a/code/AssetLib/MS3D/MS3DLoader.h +++ b/code/AssetLib/MS3D/MS3DLoader.h @@ -48,6 +48,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include + struct aiNode; namespace Assimp { @@ -58,7 +59,7 @@ namespace Assimp { class MS3DImporter : public BaseImporter { public: MS3DImporter(); - ~MS3DImporter() override; + ~MS3DImporter() override = default; // ------------------------------------------------------------------- /** Returns whether the class can handle the format of the given file. diff --git a/code/AssetLib/NDO/NDOLoader.cpp b/code/AssetLib/NDO/NDOLoader.cpp index edccc1624..405438dfc 100644 --- a/code/AssetLib/NDO/NDOLoader.cpp +++ b/code/AssetLib/NDO/NDOLoader.cpp @@ -43,8 +43,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * Implementation of the NDO importer class. */ - #ifndef ASSIMP_BUILD_NO_NDO_IMPORTER + #include "NDOLoader.h" #include #include @@ -56,7 +56,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. using namespace Assimp; -static const aiImporterDesc desc = { +static constexpr aiImporterDesc desc = { "Nendo Mesh Importer", "", "", @@ -69,14 +69,6 @@ static const aiImporterDesc desc = { "ndo" }; -// ------------------------------------------------------------------------------------------------ -// Constructor to be privately used by Importer -NDOImporter::NDOImporter() = default; - -// ------------------------------------------------------------------------------------------------ -// Destructor, private as well -NDOImporter::~NDOImporter() = default; - // ------------------------------------------------------------------------------------------------ // Returns whether the class can handle the format of the given file. bool NDOImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool /*checkSig*/) const diff --git a/code/AssetLib/NDO/NDOLoader.h b/code/AssetLib/NDO/NDOLoader.h index 61dd93981..c4f127851 100644 --- a/code/AssetLib/NDO/NDOLoader.h +++ b/code/AssetLib/NDO/NDOLoader.h @@ -65,8 +65,8 @@ class Importer; */ class NDOImporter : public BaseImporter { public: - NDOImporter(); - ~NDOImporter() override; + NDOImporter() = default; + ~NDOImporter() override = default; //! Represents a single edge struct Edge { diff --git a/code/AssetLib/NFF/NFFLoader.cpp b/code/AssetLib/NFF/NFFLoader.cpp index ce7007155..78adc27bd 100644 --- a/code/AssetLib/NFF/NFFLoader.cpp +++ b/code/AssetLib/NFF/NFFLoader.cpp @@ -56,9 +56,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include -using namespace Assimp; +namespace Assimp { -static const aiImporterDesc desc = { +static constexpr aiImporterDesc desc = { "Neutral File Format Importer", "", "", @@ -71,14 +71,6 @@ static const aiImporterDesc desc = { "enff nff" }; -// ------------------------------------------------------------------------------------------------ -// Constructor to be privately used by Importer -NFFImporter::NFFImporter() = default; - -// ------------------------------------------------------------------------------------------------ -// Destructor, private as well -NFFImporter::~NFFImporter() = default; - // ------------------------------------------------------------------------------------------------ // Returns whether the class can handle the format of the given file. bool NFFImporter::CanRead(const std::string & pFile, IOSystem * /*pIOHandler*/, bool /*checkSig*/) const { @@ -94,7 +86,7 @@ const aiImporterDesc *NFFImporter::GetInfo() const { // ------------------------------------------------------------------------------------------------ #define AI_NFF_PARSE_FLOAT(f) \ SkipSpaces(&sz); \ - if (!::IsLineEnd(*sz)) sz = fast_atoreal_move(sz, (ai_real &)f); + if (!IsLineEnd(*sz)) sz = fast_atoreal_move(sz, (ai_real &)f); // ------------------------------------------------------------------------------------------------ #define AI_NFF_PARSE_TRIPLE(v) \ @@ -338,8 +330,8 @@ void NFFImporter::InternReadFile(const std::string &pFile, break; } - // read the numbr of vertices - unsigned int num = ::strtoul10(sz, &sz); + // read the number of vertices + unsigned int num = strtoul10(sz, &sz); // temporary storage std::vector tempColors; @@ -365,7 +357,7 @@ void NFFImporter::InternReadFile(const std::string &pFile, // color definition if (TokenMatch(sz, "0x", 2)) { hasColor = true; - unsigned int numIdx = ::strtoul16(sz, &sz); + unsigned int numIdx = strtoul16(sz, &sz); aiColor4D clr; clr.a = 1.f; @@ -403,15 +395,16 @@ void NFFImporter::InternReadFile(const std::string &pFile, } AI_NFF2_GET_NEXT_TOKEN(); - if (!num) throw DeadlyImportError("NFF2: There are zero vertices"); - num = ::strtoul10(sz, &sz); + if (!num) + throw DeadlyImportError("NFF2: There are zero vertices"); + num = strtoul10(sz, &sz); std::vector tempIdx; tempIdx.reserve(10); for (unsigned int i = 0; i < num; ++i) { AI_NFF2_GET_NEXT_TOKEN(); SkipSpaces(line, &sz); - unsigned int numIdx = ::strtoul10(sz, &sz); + unsigned int numIdx = strtoul10(sz, &sz); // read all faces indices if (numIdx) { @@ -421,7 +414,7 @@ void NFFImporter::InternReadFile(const std::string &pFile, for (unsigned int a = 0; a < numIdx; ++a) { SkipSpaces(sz, &sz); - unsigned int m = ::strtoul10(sz, &sz); + unsigned int m = strtoul10(sz, &sz); if (m >= (unsigned int)tempPositions.size()) { ASSIMP_LOG_ERROR("NFF2: Vertex index overflow"); m = 0; @@ -446,7 +439,7 @@ void NFFImporter::InternReadFile(const std::string &pFile, if (TokenMatch(sz, "0x", 2)) { hasColor = true; const char *sz2 = sz; - numIdx = ::strtoul16(sz, &sz); + numIdx = strtoul16(sz, &sz); const unsigned int diff = (unsigned int)(sz - sz2); // 0xRRGGBB @@ -518,7 +511,7 @@ void NFFImporter::InternReadFile(const std::string &pFile, // Material ID? else if (!materialTable.empty() && TokenMatch(sz, "matid", 5)) { SkipSpaces(&sz); - matIdx = ::strtoul10(sz, &sz); + matIdx = strtoul10(sz, &sz); if (matIdx >= materialTable.size()) { ASSIMP_LOG_ERROR("NFF2: Material index overflow."); matIdx = 0; @@ -1165,4 +1158,6 @@ void NFFImporter::InternReadFile(const std::string &pFile, pScene->mRootNode = root; } +} // namespace Assimp + #endif // !! ASSIMP_BUILD_NO_NFF_IMPORTER diff --git a/code/AssetLib/NFF/NFFLoader.h b/code/AssetLib/NFF/NFFLoader.h index 7fd094306..b402aec84 100644 --- a/code/AssetLib/NFF/NFFLoader.h +++ b/code/AssetLib/NFF/NFFLoader.h @@ -63,8 +63,8 @@ namespace Assimp { */ class NFFImporter : public BaseImporter { public: - NFFImporter(); - ~NFFImporter() override; + NFFImporter() = default; + ~NFFImporter() override = default; // ------------------------------------------------------------------- /** Returns whether the class can handle the format of the given file. diff --git a/code/AssetLib/OFF/OFFLoader.cpp b/code/AssetLib/OFF/OFFLoader.cpp index f50afb57b..ce8dfc2d4 100644 --- a/code/AssetLib/OFF/OFFLoader.cpp +++ b/code/AssetLib/OFF/OFFLoader.cpp @@ -43,7 +43,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * @brief Implementation of the OFF importer class */ - #ifndef ASSIMP_BUILD_NO_OFF_IMPORTER // internal headers @@ -56,9 +55,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include -using namespace Assimp; +namespace Assimp { -static const aiImporterDesc desc = { +static constexpr aiImporterDesc desc = { "OFF Importer", "", "", @@ -71,99 +70,92 @@ static const aiImporterDesc desc = { "off" }; -// ------------------------------------------------------------------------------------------------ -// Constructor to be privately used by Importer -OFFImporter::OFFImporter() = default; - -// ------------------------------------------------------------------------------------------------ -// Destructor, private as well -OFFImporter::~OFFImporter() = default; - // ------------------------------------------------------------------------------------------------ // Returns whether the class can handle the format of the given file. -bool OFFImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool /*checkSig*/) const -{ - static const char* tokens[] = { "off" }; - return SearchFileHeaderForToken(pIOHandler,pFile,tokens,AI_COUNT_OF(tokens),3); +bool OFFImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /*checkSig*/) const { + static const char *tokens[] = { "off" }; + return SearchFileHeaderForToken(pIOHandler, pFile, tokens, AI_COUNT_OF(tokens), 3); } // ------------------------------------------------------------------------------------------------ -const aiImporterDesc* OFFImporter::GetInfo () const -{ +const aiImporterDesc *OFFImporter::GetInfo() const { return &desc; } - // skip blank space, lines and comments -static void NextToken(const char **car, const char* end) { - SkipSpacesAndLineEnd(car); - while (*car < end && (**car == '#' || **car == '\n' || **car == '\r')) { - SkipLine(car); +static void NextToken(const char **car, const char *end) { SkipSpacesAndLineEnd(car); - } + while (*car < end && (**car == '#' || **car == '\n' || **car == '\r')) { + SkipLine(car); + SkipSpacesAndLineEnd(car); + } } // ------------------------------------------------------------------------------------------------ // Imports the given file into the given scene structure. -void OFFImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler) { - std::unique_ptr file( pIOHandler->Open( pFile, "rb")); +void OFFImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler) { + std::unique_ptr file(pIOHandler->Open(pFile, "rb")); // Check whether we can read from the file if (file == nullptr) { - throw DeadlyImportError("Failed to open OFF file ", pFile, "."); + throw DeadlyImportError("Failed to open OFF file ", pFile, "."); } // allocate storage and copy the contents of the file to a memory buffer std::vector mBuffer2; - TextFileToBuffer(file.get(),mBuffer2); - const char* buffer = &mBuffer2[0]; + TextFileToBuffer(file.get(), mBuffer2); + const char *buffer = &mBuffer2[0]; // Proper OFF header parser. We only implement normal loading for now. bool hasTexCoord = false, hasNormals = false, hasColors = false; bool hasHomogenous = false, hasDimension = false; unsigned int dimensions = 3; - const char* car = buffer; - const char* end = buffer + mBuffer2.size(); + const char *car = buffer; + const char *end = buffer + mBuffer2.size(); NextToken(&car, end); if (car < end - 2 && car[0] == 'S' && car[1] == 'T') { - hasTexCoord = true; car += 2; + hasTexCoord = true; + car += 2; } if (car < end - 1 && car[0] == 'C') { - hasColors = true; car++; + hasColors = true; + car++; } - if (car < end- 1 && car[0] == 'N') { - hasNormals = true; car++; + if (car < end - 1 && car[0] == 'N') { + hasNormals = true; + car++; } if (car < end - 1 && car[0] == '4') { - hasHomogenous = true; car++; + hasHomogenous = true; + car++; } if (car < end - 1 && car[0] == 'n') { - hasDimension = true; car++; + hasDimension = true; + car++; } if (car < end - 3 && car[0] == 'O' && car[1] == 'F' && car[2] == 'F') { car += 3; - NextToken(&car, end); + NextToken(&car, end); } else { - // in case there is no OFF header (which is allowed by the - // specification...), then we might have unintentionally read an - // additional dimension from the primitive count fields - dimensions = 3; - hasHomogenous = false; - NextToken(&car, end); + // in case there is no OFF header (which is allowed by the + // specification...), then we might have unintentionally read an + // additional dimension from the primitive count fields + dimensions = 3; + hasHomogenous = false; + NextToken(&car, end); - // at this point the next token should be an integer number - if (car >= end - 1 || *car < '0' || *car > '9') { - throw DeadlyImportError("OFF: Header is invalid"); - } + // at this point the next token should be an integer number + if (car >= end - 1 || *car < '0' || *car > '9') { + throw DeadlyImportError("OFF: Header is invalid"); + } } if (hasDimension) { dimensions = strtoul10(car, &car); - NextToken(&car, end); + NextToken(&car, end); } if (dimensions > 3) { - throw DeadlyImportError - ("OFF: Number of vertex coordinates higher than 3 unsupported"); + throw DeadlyImportError("OFF: Number of vertex coordinates higher than 3 unsupported"); } NextToken(&car, end); @@ -171,7 +163,7 @@ void OFFImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOS NextToken(&car, end); const unsigned int numFaces = strtoul10(car, &car); NextToken(&car, end); - strtoul10(car, &car); // skip edge count + strtoul10(car, &car); // skip edge count NextToken(&car, end); if (!numVertices) { @@ -182,13 +174,13 @@ void OFFImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOS } pScene->mNumMeshes = 1; - pScene->mMeshes = new aiMesh*[ pScene->mNumMeshes ]; + pScene->mMeshes = new aiMesh *[pScene->mNumMeshes]; - aiMesh* mesh = new aiMesh(); + aiMesh *mesh = new aiMesh(); pScene->mMeshes[0] = mesh; mesh->mNumFaces = numFaces; - aiFace* faces = new aiFace[mesh->mNumFaces]; + aiFace *faces = new aiFace[mesh->mNumFaces]; mesh->mFaces = faces; mesh->mNumVertices = numVertices; @@ -206,100 +198,101 @@ void OFFImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOS // now read all vertex lines for (unsigned int i = 0; i < numVertices; ++i) { - if(!GetNextLine(buffer, line)) { + if (!GetNextLine(buffer, line)) { ASSIMP_LOG_ERROR("OFF: The number of verts in the header is incorrect"); break; } - aiVector3D& v = mesh->mVertices[i]; + aiVector3D &v = mesh->mVertices[i]; sz = line; - // helper array to write a for loop over possible dimension values - ai_real* vec[3] = {&v.x, &v.y, &v.z}; + // helper array to write a for loop over possible dimension values + ai_real *vec[3] = { &v.x, &v.y, &v.z }; - // stop at dimensions: this allows loading 1D or 2D coordinate vertices - for (unsigned int dim = 0; dim < dimensions; ++dim ) { - SkipSpaces(&sz); - sz = fast_atoreal_move(sz, *vec[dim]); - } + // stop at dimensions: this allows loading 1D or 2D coordinate vertices + for (unsigned int dim = 0; dim < dimensions; ++dim) { + SkipSpaces(&sz); + sz = fast_atoreal_move(sz, *vec[dim]); + } - // if has homogeneous coordinate, divide others by this one - if (hasHomogenous) { - SkipSpaces(&sz); - ai_real w = 1.; - sz = fast_atoreal_move(sz, w); - for (unsigned int dim = 0; dim < dimensions; ++dim ) { - *(vec[dim]) /= w; - } - } + // if has homogeneous coordinate, divide others by this one + if (hasHomogenous) { + SkipSpaces(&sz); + ai_real w = 1.; + sz = fast_atoreal_move(sz, w); + for (unsigned int dim = 0; dim < dimensions; ++dim) { + *(vec[dim]) /= w; + } + } - // read optional normals - if (hasNormals) { - aiVector3D& n = mesh->mNormals[i]; - SkipSpaces(&sz); - sz = fast_atoreal_move(sz,(ai_real&)n.x); - SkipSpaces(&sz); - sz = fast_atoreal_move(sz,(ai_real&)n.y); - SkipSpaces(&sz); - fast_atoreal_move(sz,(ai_real&)n.z); - } + // read optional normals + if (hasNormals) { + aiVector3D &n = mesh->mNormals[i]; + SkipSpaces(&sz); + sz = fast_atoreal_move(sz, (ai_real &)n.x); + SkipSpaces(&sz); + sz = fast_atoreal_move(sz, (ai_real &)n.y); + SkipSpaces(&sz); + fast_atoreal_move(sz, (ai_real &)n.z); + } - // reading colors is a pain because the specification says it can be - // integers or floats, and any number of them between 1 and 4 included, - // until the next comment or end of line - // in theory should be testing type ! - if (hasColors) { - aiColor4D& c = mesh->mColors[0][i]; - SkipSpaces(&sz); - sz = fast_atoreal_move(sz,(ai_real&)c.r); + // reading colors is a pain because the specification says it can be + // integers or floats, and any number of them between 1 and 4 included, + // until the next comment or end of line + // in theory should be testing type ! + if (hasColors) { + aiColor4D &c = mesh->mColors[0][i]; + SkipSpaces(&sz); + sz = fast_atoreal_move(sz, (ai_real &)c.r); if (*sz != '#' && *sz != '\n' && *sz != '\r') { - SkipSpaces(&sz); - sz = fast_atoreal_move(sz,(ai_real&)c.g); + SkipSpaces(&sz); + sz = fast_atoreal_move(sz, (ai_real &)c.g); } else { - c.g = 0.; - } + c.g = 0.; + } if (*sz != '#' && *sz != '\n' && *sz != '\r') { - SkipSpaces(&sz); - sz = fast_atoreal_move(sz,(ai_real&)c.b); + SkipSpaces(&sz); + sz = fast_atoreal_move(sz, (ai_real &)c.b); } else { - c.b = 0.; - } + c.b = 0.; + } if (*sz != '#' && *sz != '\n' && *sz != '\r') { - SkipSpaces(&sz); - sz = fast_atoreal_move(sz,(ai_real&)c.a); + SkipSpaces(&sz); + sz = fast_atoreal_move(sz, (ai_real &)c.a); } else { - c.a = 1.; - } - } + c.a = 1.; + } + } if (hasTexCoord) { - aiVector3D& t = mesh->mTextureCoords[0][i]; - SkipSpaces(&sz); - sz = fast_atoreal_move(sz,(ai_real&)t.x); - SkipSpaces(&sz); - fast_atoreal_move(sz,(ai_real&)t.y); - } + aiVector3D &t = mesh->mTextureCoords[0][i]; + SkipSpaces(&sz); + sz = fast_atoreal_move(sz, (ai_real &)t.x); + SkipSpaces(&sz); + fast_atoreal_move(sz, (ai_real &)t.y); + } } // load faces with their indices faces = mesh->mFaces; - for (unsigned int i = 0; i < numFaces; ) { - if(!GetNextLine(buffer,line)) { + for (unsigned int i = 0; i < numFaces;) { + if (!GetNextLine(buffer, line)) { ASSIMP_LOG_ERROR("OFF: The number of faces in the header is incorrect"); throw DeadlyImportError("OFF: The number of faces in the header is incorrect"); } unsigned int idx; - sz = line; SkipSpaces(&sz); - idx = strtoul10(sz,&sz); - if(!idx || idx > 9) { - ASSIMP_LOG_ERROR("OFF: Faces with zero indices aren't allowed"); + sz = line; + SkipSpaces(&sz); + idx = strtoul10(sz, &sz); + if (!idx || idx > 9) { + ASSIMP_LOG_ERROR("OFF: Faces with zero indices aren't allowed"); --mesh->mNumFaces; ++i; continue; - } - faces->mNumIndices = idx; + } + faces->mNumIndices = idx; faces->mIndices = new unsigned int[faces->mNumIndices]; - for (unsigned int m = 0; m < faces->mNumIndices;++m) { + for (unsigned int m = 0; m < faces->mNumIndices; ++m) { SkipSpaces(&sz); - idx = strtoul10(sz,&sz); + idx = strtoul10(sz, &sz); if (idx >= numVertices) { ASSIMP_LOG_ERROR("OFF: Vertex index is out of range"); idx = numVertices - 1; @@ -314,20 +307,22 @@ void OFFImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOS pScene->mRootNode = new aiNode(); pScene->mRootNode->mName.Set(""); pScene->mRootNode->mNumMeshes = 1; - pScene->mRootNode->mMeshes = new unsigned int [pScene->mRootNode->mNumMeshes]; + pScene->mRootNode->mMeshes = new unsigned int[pScene->mRootNode->mNumMeshes]; pScene->mRootNode->mMeshes[0] = 0; // generate a default material pScene->mNumMaterials = 1; - pScene->mMaterials = new aiMaterial*[pScene->mNumMaterials]; - aiMaterial* pcMat = new aiMaterial(); + pScene->mMaterials = new aiMaterial *[pScene->mNumMaterials]; + aiMaterial *pcMat = new aiMaterial(); - aiColor4D clr( ai_real( 0.6 ), ai_real( 0.6 ), ai_real( 0.6 ), ai_real( 1.0 ) ); - pcMat->AddProperty(&clr,1,AI_MATKEY_COLOR_DIFFUSE); + aiColor4D clr(ai_real(0.6), ai_real(0.6), ai_real(0.6), ai_real(1.0)); + pcMat->AddProperty(&clr, 1, AI_MATKEY_COLOR_DIFFUSE); pScene->mMaterials[0] = pcMat; const int twosided = 1; pcMat->AddProperty(&twosided, 1, AI_MATKEY_TWOSIDED); } +} // namespace Assimp + #endif // !! ASSIMP_BUILD_NO_OFF_IMPORTER diff --git a/code/AssetLib/OFF/OFFLoader.h b/code/AssetLib/OFF/OFFLoader.h index 04bb7f481..b8577e507 100644 --- a/code/AssetLib/OFF/OFFLoader.h +++ b/code/AssetLib/OFF/OFFLoader.h @@ -57,8 +57,8 @@ namespace Assimp { */ class OFFImporter : public BaseImporter { public: - OFFImporter(); - ~OFFImporter() override; + OFFImporter() = default; + ~OFFImporter() override = default; // ------------------------------------------------------------------- /** Returns whether the class can handle the format of the given file. diff --git a/code/AssetLib/Obj/ObjFileImporter.cpp b/code/AssetLib/Obj/ObjFileImporter.cpp index 173ef2074..339e90b06 100644 --- a/code/AssetLib/Obj/ObjFileImporter.cpp +++ b/code/AssetLib/Obj/ObjFileImporter.cpp @@ -54,7 +54,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include -static const aiImporterDesc desc = { +static constexpr aiImporterDesc desc = { "Wavefront Object Importer", "", "", @@ -78,7 +78,9 @@ using namespace std; ObjFileImporter::ObjFileImporter() : m_Buffer(), m_pRootObject(nullptr), - m_strAbsPath(std::string(1, DefaultIOSystem().getOsSeparator())) {} + m_strAbsPath(std::string(1, DefaultIOSystem().getOsSeparator())) { + // empty +} // ------------------------------------------------------------------------------------------------ // Destructor. @@ -101,8 +103,13 @@ const aiImporterDesc *ObjFileImporter::GetInfo() const { // ------------------------------------------------------------------------------------------------ // Obj-file import implementation void ObjFileImporter::InternReadFile(const std::string &file, aiScene *pScene, IOSystem *pIOHandler) { + if (m_pRootObject != nullptr) { + delete m_pRootObject; + m_pRootObject = nullptr; + } + // Read file into memory - static const std::string mode = "rb"; + static constexpr char mode[] = "rb"; auto streamCloser = [&](IOStream *pStream) { pIOHandler->Close(pStream); }; diff --git a/code/AssetLib/Ogre/OgreImporter.cpp b/code/AssetLib/Ogre/OgreImporter.cpp index 860aed727..5bf6901a0 100644 --- a/code/AssetLib/Ogre/OgreImporter.cpp +++ b/code/AssetLib/Ogre/OgreImporter.cpp @@ -48,7 +48,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include -static const aiImporterDesc desc = { +static constexpr aiImporterDesc desc = { "Ogre3D Mesh Importer", "", "", diff --git a/code/AssetLib/OpenGEX/OpenGEXImporter.cpp b/code/AssetLib/OpenGEX/OpenGEXImporter.cpp index 16268ead5..735f56755 100644 --- a/code/AssetLib/OpenGEX/OpenGEXImporter.cpp +++ b/code/AssetLib/OpenGEX/OpenGEXImporter.cpp @@ -52,7 +52,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include -static const aiImporterDesc desc = { +static constexpr aiImporterDesc desc = { "Open Game Engine Exchange", "", "", @@ -66,42 +66,42 @@ static const aiImporterDesc desc = { }; namespace Grammar { - static const char* MetricType = "Metric"; - static const char *Metric_DistanceType = "distance"; - static const char *Metric_AngleType = "angle"; - static const char *Metric_TimeType = "time"; - static const char *Metric_UpType = "up"; - static const char *NameType = "Name"; - static const char *ObjectRefType = "ObjectRef"; - static const char *MaterialRefType = "MaterialRef"; - static const char *MetricKeyType = "key"; - static const char *GeometryNodeType = "GeometryNode"; - static const char *CameraNodeType = "CameraNode"; - static const char *LightNodeType = "LightNode"; - static const char *GeometryObjectType = "GeometryObject"; - static const char *CameraObjectType = "CameraObject"; - static const char *LightObjectType = "LightObject"; - static const char *TransformType = "Transform"; - static const char *MeshType = "Mesh"; - static const char *VertexArrayType = "VertexArray"; - static const char *IndexArrayType = "IndexArray"; - static const char *MaterialType = "Material"; - static const char *ColorType = "Color"; - static const char *ParamType = "Param"; - static const char *TextureType = "Texture"; - static const char *AttenType = "Atten"; + static constexpr char MetricType[] = "Metric"; + static constexpr char Metric_DistanceType[] = "distance"; + static constexpr char Metric_AngleType[] = "angle"; + static constexpr char Metric_TimeType[] = "time"; + static constexpr char Metric_UpType[] = "up"; + static constexpr char NameType[] = "Name"; + static constexpr char ObjectRefType[] = "ObjectRef"; + static constexpr char MaterialRefType[] = "MaterialRef"; + static constexpr char MetricKeyType[] = "key"; + static constexpr char GeometryNodeType[] = "GeometryNode"; + static constexpr char CameraNodeType[] = "CameraNode"; + static constexpr char LightNodeType[] = "LightNode"; + static constexpr char GeometryObjectType[] = "GeometryObject"; + static constexpr char CameraObjectType[] = "CameraObject"; + static constexpr char LightObjectType[] = "LightObject"; + static constexpr char TransformType[] = "Transform"; + static constexpr char MeshType[] = "Mesh"; + static constexpr char VertexArrayType[] = "VertexArray"; + static constexpr char IndexArrayType[] = "IndexArray"; + static constexpr char MaterialType[] = "Material"; + static constexpr char ColorType[] = "Color"; + static constexpr char ParamType[] = "Param"; + static constexpr char TextureType[] = "Texture"; + static constexpr char AttenType[] = "Atten"; - static const char *DiffuseColorToken = "diffuse"; - static const char *SpecularColorToken = "specular"; - static const char *EmissionColorToken = "emission"; + static constexpr char DiffuseColorToken[] = "diffuse"; + static constexpr char SpecularColorToken[] = "specular"; + static constexpr char EmissionColorToken[] = "emission"; - static const char *DiffuseTextureToken = "diffuse"; - static const char *DiffuseSpecularTextureToken = "specular"; - static const char *SpecularPowerTextureToken = "specular_power"; - static const char *EmissionTextureToken = "emission"; - static const char *OpacyTextureToken = "opacity"; - static const char *TransparencyTextureToken = "transparency"; - static const char *NormalTextureToken = "normal"; + static constexpr char DiffuseTextureToken[] = "diffuse"; + static constexpr char DiffuseSpecularTextureToken[] = "specular"; + static constexpr char SpecularPowerTextureToken[] = "specular_power"; + static constexpr char EmissionTextureToken[] = "emission"; + static constexpr char OpacyTextureToken[] = "opacity"; + static constexpr char TransparencyTextureToken[] = "transparency"; + static constexpr char NormalTextureToken[] = "normal"; enum TokenType { NoneType = -1, @@ -139,7 +139,7 @@ namespace Grammar { return false; } - int idx(-1); + int idx = -1; for (size_t i = 0; i < 4; i++) { if (ValidMetricToken[i] == token) { idx = (int)i; diff --git a/code/AssetLib/Ply/PlyLoader.cpp b/code/AssetLib/Ply/PlyLoader.cpp index 783c7f1c6..a747ba5cd 100644 --- a/code/AssetLib/Ply/PlyLoader.cpp +++ b/code/AssetLib/Ply/PlyLoader.cpp @@ -53,9 +53,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include -using namespace ::Assimp; +namespace Assimp { -static const aiImporterDesc desc = { +static constexpr aiImporterDesc desc = { "Stanford Polygon Library (PLY) Importer", "", "", @@ -71,16 +71,16 @@ static const aiImporterDesc desc = { // ------------------------------------------------------------------------------------------------ // Internal stuff namespace { -// ------------------------------------------------------------------------------------------------ -// Checks that property index is within range -template -inline const T &GetProperty(const std::vector &props, int idx) { - if (static_cast(idx) >= props.size()) { - throw DeadlyImportError("Invalid .ply file: Property index is out of range."); - } + // ------------------------------------------------------------------------------------------------ + // Checks that property index is within range + template + inline const T &GetProperty(const std::vector &props, int idx) { + if (static_cast(idx) >= props.size()) { + throw DeadlyImportError("Invalid .ply file: Property index is out of range."); + } - return props[idx]; -} + return props[idx]; + } } // namespace // ------------------------------------------------------------------------------------------------ @@ -92,10 +92,6 @@ PLYImporter::PLYImporter() : // empty } -// ------------------------------------------------------------------------------------------------ -// Destructor, private as well -PLYImporter::~PLYImporter() = default; - // ------------------------------------------------------------------------------------------------ // Returns whether the class can handle the format of the given file. bool PLYImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /*checkSig*/) const { @@ -215,7 +211,7 @@ void PLYImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy throw DeadlyImportError("Invalid .ply file: Missing format specification"); } - //free the file buffer + // free the file buffer streamedBuffer.close(); if (mGeneratedMesh == nullptr) { @@ -376,7 +372,7 @@ void PLYImporter::LoadVertex(const PLY::Element *pcElement, const PLY::ElementIn haveNormal = true; } - //Colors + // Colors aiColor4D cOut; bool haveColor = false; if (0xFFFFFFFF != aiColors[0]) { @@ -415,7 +411,7 @@ void PLYImporter::LoadVertex(const PLY::Element *pcElement, const PLY::ElementIn haveColor = true; } - //Texture coordinates + // Texture coordinates aiVector3D tOut; tOut.z = 0; bool haveTextureCoords = false; @@ -431,7 +427,7 @@ void PLYImporter::LoadVertex(const PLY::Element *pcElement, const PLY::ElementIn haveTextureCoords = true; } - //create aiMesh if needed + // create aiMesh if needed if (nullptr == mGeneratedMesh) { mGeneratedMesh = new aiMesh(); mGeneratedMesh->mMaterialIndex = 0; @@ -512,8 +508,8 @@ void PLYImporter::LoadFace(const PLY::Element *pcElement, const PLY::ElementInst bool bIsTriStrip = false; // index of the material index property - //unsigned int iMaterialIndex = 0xFFFFFFFF; - //PLY::EDataType eType2 = EDT_Char; + // unsigned int iMaterialIndex = 0xFFFFFFFF; + // PLY::EDataType eType2 = EDT_Char; // texture coordinates unsigned int iTextureCoord = 0xFFFFFFFF; @@ -595,7 +591,7 @@ void PLYImporter::LoadFace(const PLY::Element *pcElement, const PLY::ElementInst if (0xFFFFFFFF != iTextureCoord) { const unsigned int iNum = (unsigned int)GetProperty(instElement->alProperties, iTextureCoord).avList.size(); - //should be 6 coords + // should be 6 coords std::vector::const_iterator p = GetProperty(instElement->alProperties, iTextureCoord).avList.begin(); @@ -625,7 +621,7 @@ void PLYImporter::LoadFace(const PLY::Element *pcElement, const PLY::ElementInst // a value of -1 indicates a restart of the strip bool flip = false; const std::vector &quak = GetProperty(instElement->alProperties, iProperty).avList; - //pvOut->reserve(pvOut->size() + quak.size() + (quak.size()>>2u)); //Limits memory consumption + // pvOut->reserve(pvOut->size() + quak.size() + (quak.size()>>2u)); //Limits memory consumption int aiTable[2] = { -1, -1 }; for (std::vector::const_iterator a = quak.begin(); a != quak.end(); ++a) { @@ -863,7 +859,7 @@ void PLYImporter::LoadMaterial(std::vector *pvOut, std::string &de const int two_sided = 1; pcHelper->AddProperty(&two_sided, 1, AI_MATKEY_TWOSIDED); - //default texture + // default texture if (!defaultTexture.empty()) { const aiString name(defaultTexture.c_str()); pcHelper->AddProperty(&name, _AI_MATKEY_TEXTURE_BASE, aiTextureType_DIFFUSE, 0); @@ -873,7 +869,7 @@ void PLYImporter::LoadMaterial(std::vector *pvOut, std::string &de pcHelper->AddProperty(&two_sided, 1, AI_MATKEY_TWOSIDED); } - //set to wireframe, so when using this material info we can switch to points rendering + // set to wireframe, so when using this material info we can switch to points rendering if (pointsOnly) { const int wireframe = 1; pcHelper->AddProperty(&wireframe, 1, AI_MATKEY_ENABLE_WIREFRAME); @@ -890,7 +886,7 @@ void PLYImporter::LoadMaterial(std::vector *pvOut, std::string &de int iMode = (int)aiShadingMode_Gouraud; pcHelper->AddProperty(&iMode, 1, AI_MATKEY_SHADING_MODEL); - //generate white material most 3D engine just multiply ambient / diffuse color with actual ambient / light color + // generate white material most 3D engine just multiply ambient / diffuse color with actual ambient / light color aiColor3D clr; clr.b = clr.g = clr.r = 1.0f; pcHelper->AddProperty(&clr, 1, AI_MATKEY_COLOR_DIFFUSE); @@ -906,13 +902,13 @@ void PLYImporter::LoadMaterial(std::vector *pvOut, std::string &de pcHelper->AddProperty(&two_sided, 1, AI_MATKEY_TWOSIDED); } - //default texture + // default texture if (!defaultTexture.empty()) { const aiString name(defaultTexture.c_str()); pcHelper->AddProperty(&name, _AI_MATKEY_TEXTURE_BASE, aiTextureType_DIFFUSE, 0); } - //set to wireframe, so when using this material info we can switch to points rendering + // set to wireframe, so when using this material info we can switch to points rendering if (pointsOnly) { const int wireframe = 1; pcHelper->AddProperty(&wireframe, 1, AI_MATKEY_ENABLE_WIREFRAME); @@ -922,4 +918,6 @@ void PLYImporter::LoadMaterial(std::vector *pvOut, std::string &de } } +} // namespace Assimp + #endif // !! ASSIMP_BUILD_NO_PLY_IMPORTER diff --git a/code/AssetLib/Ply/PlyLoader.h b/code/AssetLib/Ply/PlyLoader.h index e29da1db6..f85445f91 100644 --- a/code/AssetLib/Ply/PlyLoader.h +++ b/code/AssetLib/Ply/PlyLoader.h @@ -65,7 +65,7 @@ using namespace PLY; class PLYImporter : public BaseImporter { public: PLYImporter(); - ~PLYImporter() override; + ~PLYImporter() override = default; // ------------------------------------------------------------------- /** Returns whether the class can handle the format of the given file. diff --git a/code/AssetLib/Q3BSP/Q3BSPFileImporter.cpp b/code/AssetLib/Q3BSP/Q3BSPFileImporter.cpp index 924949eeb..30b1bf053 100644 --- a/code/AssetLib/Q3BSP/Q3BSPFileImporter.cpp +++ b/code/AssetLib/Q3BSP/Q3BSPFileImporter.cpp @@ -65,7 +65,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include -static const aiImporterDesc desc = { +static constexpr aiImporterDesc desc = { "Quake III BSP Importer", "", "", @@ -146,7 +146,11 @@ Q3BSPFileImporter::Q3BSPFileImporter() : // ------------------------------------------------------------------------------------------------ // Destructor. Q3BSPFileImporter::~Q3BSPFileImporter() { - // Clear face-to-material map + clear(); +} + +// ------------------------------------------------------------------------------------------------ +void Q3BSPFileImporter::clear() { for (FaceMap::iterator it = m_MaterialLookupMap.begin(); it != m_MaterialLookupMap.end(); ++it) { const std::string &matName = it->first; if (!matName.empty()) { @@ -173,6 +177,7 @@ const aiImporterDesc *Q3BSPFileImporter::GetInfo() const { // ------------------------------------------------------------------------------------------------ // Import method. void Q3BSPFileImporter::InternReadFile(const std::string &rFile, aiScene *scene, IOSystem *ioHandler) { + clear(); ZipArchiveIOSystem Archive(ioHandler, rFile); if (!Archive.isOpen()) { throw DeadlyImportError("Failed to open file ", rFile, "."); diff --git a/code/AssetLib/Q3BSP/Q3BSPFileImporter.h b/code/AssetLib/Q3BSP/Q3BSPFileImporter.h index fdcfff876..63d6edb21 100644 --- a/code/AssetLib/Q3BSP/Q3BSPFileImporter.h +++ b/code/AssetLib/Q3BSP/Q3BSPFileImporter.h @@ -81,6 +81,7 @@ protected: using FaceMapIt = std::map* >::iterator; using FaceMapConstIt = std::map*>::const_iterator; + void clear(); const aiImporterDesc* GetInfo () const override; void InternReadFile(const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler) override; void separateMapName( const std::string &rImportName, std::string &rArchiveName, std::string &rMapName ); diff --git a/code/AssetLib/Q3D/Q3DLoader.cpp b/code/AssetLib/Q3D/Q3DLoader.cpp index 22d1065de..b599ad8f2 100644 --- a/code/AssetLib/Q3D/Q3DLoader.cpp +++ b/code/AssetLib/Q3D/Q3DLoader.cpp @@ -55,9 +55,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include -using namespace Assimp; +namespace Assimp { -static const aiImporterDesc desc = { +static constexpr aiImporterDesc desc = { "Quick3D Importer", "", "", @@ -127,7 +127,7 @@ void Q3DImporter::InternReadFile(const std::string &pFile, std::vector materials; try { materials.reserve(numMats); - } catch(const std::bad_alloc&) { + } catch (const std::bad_alloc &) { ASSIMP_LOG_ERROR("Invalid alloc for materials."); throw DeadlyImportError("Invalid Quick3D-file, material allocation failed."); } @@ -135,7 +135,7 @@ void Q3DImporter::InternReadFile(const std::string &pFile, std::vector meshes; try { meshes.reserve(numMeshes); - } catch(const std::bad_alloc&) { + } catch (const std::bad_alloc &) { ASSIMP_LOG_ERROR("Invalid alloc for meshes."); throw DeadlyImportError("Invalid Quick3D-file, mesh allocation failed."); } @@ -237,7 +237,6 @@ void Q3DImporter::InternReadFile(const std::string &pFile, if (minor > '0' && major == '3') stream.IncPtr(mesh.faces.size()); } - // stream.IncPtr(4); // unknown value here } break; // materials chunk @@ -275,8 +274,6 @@ void Q3DImporter::InternReadFile(const std::string &pFile, // read the transparency mat.transparency = stream.GetF4(); - // unknown value here - // stream.IncPtr(4); // FIX: it could be the texture index ... mat.texIdx = (unsigned int)stream.GetI4(); } @@ -425,7 +422,8 @@ outer: pScene->mMeshes = new aiMesh *[pScene->mNumMaterials]; for (unsigned int i = 0, real = 0; i < (unsigned int)materials.size(); ++i) { - if (fidx[i].empty()) continue; + if (fidx[i].empty()) + continue; // Allocate a mesh and a material aiMesh *mesh = pScene->mMeshes[real] = new aiMesh(); @@ -548,14 +546,9 @@ outer: // Now we need to attach the meshes to the root node of the scene pScene->mRootNode->mNumMeshes = pScene->mNumMeshes; pScene->mRootNode->mMeshes = new unsigned int[pScene->mNumMeshes]; - for (unsigned int i = 0; i < pScene->mNumMeshes; ++i) + for (unsigned int i = 0; i < pScene->mNumMeshes; ++i) { pScene->mRootNode->mMeshes[i] = i; - - /*pScene->mRootNode->mTransformation *= aiMatrix4x4( - 1.f, 0.f, 0.f, 0.f, - 0.f, -1.f,0.f, 0.f, - 0.f, 0.f, 1.f, 0.f, - 0.f, 0.f, 0.f, 1.f);*/ + } // Add cameras and light sources to the scene root node pScene->mRootNode->mNumChildren = pScene->mNumLights + pScene->mNumCameras; @@ -577,4 +570,6 @@ outer: } } +} // namespace Assimp + #endif // !! ASSIMP_BUILD_NO_Q3D_IMPORTER diff --git a/code/AssetLib/Raw/RawLoader.cpp b/code/AssetLib/Raw/RawLoader.cpp index 1791a5c52..4c5f852b0 100644 --- a/code/AssetLib/Raw/RawLoader.cpp +++ b/code/AssetLib/Raw/RawLoader.cpp @@ -55,9 +55,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include -using namespace Assimp; +namespace Assimp { -static const aiImporterDesc desc = { +static constexpr aiImporterDesc desc = { "Raw Importer", "", "", @@ -70,14 +70,6 @@ static const aiImporterDesc desc = { "raw" }; -// ------------------------------------------------------------------------------------------------ -// Constructor to be privately used by Importer -RAWImporter::RAWImporter() = default; - -// ------------------------------------------------------------------------------------------------ -// Destructor, private as well -RAWImporter::~RAWImporter() = default; - // ------------------------------------------------------------------------------------------------ // Returns whether the class can handle the format of the given file. bool RAWImporter::CanRead(const std::string &filename, IOSystem * /*pIOHandler*/, bool /*checkSig*/) const { @@ -295,4 +287,6 @@ void RAWImporter::InternReadFile(const std::string &pFile, } } +} // namespace Assimp + #endif // !! ASSIMP_BUILD_NO_RAW_IMPORTER diff --git a/code/AssetLib/Raw/RawLoader.h b/code/AssetLib/Raw/RawLoader.h index 54314f728..83e4a9f1f 100644 --- a/code/AssetLib/Raw/RawLoader.h +++ b/code/AssetLib/Raw/RawLoader.h @@ -57,8 +57,8 @@ namespace Assimp { */ class RAWImporter : public BaseImporter { public: - RAWImporter(); - ~RAWImporter() override; + RAWImporter() = default; + ~RAWImporter() override = default; // ------------------------------------------------------------------- /** Returns whether the class can handle the format of the given file. diff --git a/code/AssetLib/SIB/SIBImporter.cpp b/code/AssetLib/SIB/SIBImporter.cpp index 9f299180b..26b1c5227 100644 --- a/code/AssetLib/SIB/SIBImporter.cpp +++ b/code/AssetLib/SIB/SIBImporter.cpp @@ -69,9 +69,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include -using namespace Assimp; +namespace Assimp { -static const aiImporterDesc desc = { +static constexpr aiImporterDesc desc = { "Silo SIB Importer", "Richard Mitton (http://www.codersnotes.com/about)", "", @@ -94,7 +94,7 @@ enum { N }; -typedef std::pair SIBPair; +using SIBPair = std::pair; struct SIBEdge { uint32_t faceA, faceB; @@ -199,15 +199,6 @@ static aiString ReadString(StreamReaderLE *stream, uint32_t numWChars) { return result; } - -// ------------------------------------------------------------------------------------------------ -// Constructor to be privately used by Importer -SIBImporter::SIBImporter() = default; - -// ------------------------------------------------------------------------------------------------ -// Destructor, private as well -SIBImporter::~SIBImporter() = default; - // ------------------------------------------------------------------------------------------------ // Returns whether the class can handle the format of the given file. bool SIBImporter::CanRead(const std::string &filename, IOSystem * /*pIOHandler*/, bool /*checkSig*/) const { @@ -882,4 +873,6 @@ void SIBImporter::InternReadFile(const std::string &pFile, } } +} // namespace Assimp + #endif // !! ASSIMP_BUILD_NO_SIB_IMPORTER diff --git a/code/AssetLib/SIB/SIBImporter.h b/code/AssetLib/SIB/SIBImporter.h index 2b197ddca..903c36561 100644 --- a/code/AssetLib/SIB/SIBImporter.h +++ b/code/AssetLib/SIB/SIBImporter.h @@ -57,8 +57,8 @@ namespace Assimp { */ class ASSIMP_API SIBImporter : public BaseImporter { public: - SIBImporter(); - ~SIBImporter() override; + SIBImporter() = default; + ~SIBImporter() override = default; // ------------------------------------------------------------------- /** Returns whether the class can handle the format of the given file. diff --git a/code/AssetLib/SMD/SMDLoader.cpp b/code/AssetLib/SMD/SMDLoader.cpp index 9af871cee..4b63dd9d0 100644 --- a/code/AssetLib/SMD/SMDLoader.cpp +++ b/code/AssetLib/SMD/SMDLoader.cpp @@ -64,9 +64,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define strtok_s strtok_r #endif -using namespace Assimp; +namespace Assimp { -static const aiImporterDesc desc = { +static constexpr aiImporterDesc desc = { "Valve SMD Importer", "", "", @@ -1077,4 +1077,6 @@ void SMDImporter::ParseVertex(const char* szCurrent, SMDI_PARSE_RETURN; } +} + #endif // !! ASSIMP_BUILD_NO_SMD_IMPORTER diff --git a/code/AssetLib/STL/STLLoader.cpp b/code/AssetLib/STL/STLLoader.cpp index 9c0fb4f59..269ee1467 100644 --- a/code/AssetLib/STL/STLLoader.cpp +++ b/code/AssetLib/STL/STLLoader.cpp @@ -52,11 +52,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include -using namespace Assimp; +namespace Assimp { namespace { -static const aiImporterDesc desc = { +static constexpr aiImporterDesc desc = { "Stereolithography (STL) Importer", "", "", @@ -129,7 +129,7 @@ STLImporter::STLImporter() : mBuffer(), mFileSize(0), mScene() { - // empty + // empty } // ------------------------------------------------------------------------------------------------ @@ -250,13 +250,13 @@ void STLImporter::LoadASCIIFile(aiNode *root) { sz += 5; // skip the "solid" SkipSpaces(&sz); const char *szMe = sz; - while (!::IsSpaceOrNewLine(*sz)) { + while (!IsSpaceOrNewLine(*sz)) { sz++; } size_t temp = (size_t)(sz - szMe); // setup the name of the node - if ( temp ) { + if (temp) { if (temp >= MAXLEN) { throw DeadlyImportError("STL: Node name too long"); } @@ -303,7 +303,7 @@ void STLImporter::LoadASCIIFile(aiNode *root) { normalBuffer.emplace_back(vn); normalBuffer.emplace_back(vn); } - } else if (!strncmp(sz, "vertex", 6) && ::IsSpaceOrNewLine(*(sz + 6))) { // vertex 1.50000 1.50000 0.00000 + } else if (!strncmp(sz, "vertex", 6) && IsSpaceOrNewLine(*(sz + 6))) { // vertex 1.50000 1.50000 0.00000 if (faceVertexCounter >= 3) { ASSIMP_LOG_ERROR("STL: a facet with more than 3 vertices has been found"); ++sz; @@ -325,14 +325,14 @@ void STLImporter::LoadASCIIFile(aiNode *root) { } else if (!::strncmp(sz, "endsolid", 8)) { do { ++sz; - } while (!::IsLineEnd(*sz)); + } while (!IsLineEnd(*sz)); SkipSpacesAndLineEnd(&sz); // finished! break; } else { // else skip the whole identifier do { ++sz; - } while (!::IsSpaceOrNewLine(*sz)); + } while (!IsSpaceOrNewLine(*sz)); } } @@ -349,14 +349,14 @@ void STLImporter::LoadASCIIFile(aiNode *root) { throw DeadlyImportError("Normal buffer size does not match position buffer size"); } - // only process positionbuffer when filled, else exception when accessing with index operator + // only process position buffer when filled, else exception when accessing with index operator // see line 353: only warning is triggered - // see line 373(now): access to empty positionbuffer with index operator forced exception + // see line 373(now): access to empty position buffer with index operator forced exception if (!positionBuffer.empty()) { pMesh->mNumFaces = static_cast(positionBuffer.size() / 3); pMesh->mNumVertices = static_cast(positionBuffer.size()); pMesh->mVertices = new aiVector3D[pMesh->mNumVertices]; - for (size_t i=0; imNumVertices; ++i ) { + for (size_t i = 0; i < pMesh->mNumVertices; ++i) { pMesh->mVertices[i].x = positionBuffer[i].x; pMesh->mVertices[i].y = positionBuffer[i].y; pMesh->mVertices[i].z = positionBuffer[i].z; @@ -366,7 +366,7 @@ void STLImporter::LoadASCIIFile(aiNode *root) { // also only process normalBuffer when filled, else exception when accessing with index operator if (!normalBuffer.empty()) { pMesh->mNormals = new aiVector3D[pMesh->mNumVertices]; - for (size_t i=0; imNumVertices; ++i ) { + for (size_t i = 0; i < pMesh->mNumVertices; ++i) { pMesh->mNormals[i].x = normalBuffer[i].x; pMesh->mNormals[i].y = normalBuffer[i].y; pMesh->mNormals[i].z = normalBuffer[i].z; @@ -450,9 +450,8 @@ bool STLImporter::LoadBinaryFile() { aiVector3D *vp = pMesh->mVertices = new aiVector3D[pMesh->mNumVertices]; aiVector3D *vn = pMesh->mNormals = new aiVector3D[pMesh->mNumVertices]; - typedef aiVector3t aiVector3F; - aiVector3F *theVec; - aiVector3F theVec3F; + aiVector3f *theVec; + aiVector3f theVec3F; for (unsigned int i = 0; i < pMesh->mNumFaces; ++i) { // NOTE: Blender sometimes writes empty normals ... this is not @@ -460,8 +459,8 @@ bool STLImporter::LoadBinaryFile() { // There's one normal for the face in the STL; use it three times // for vertex normals - theVec = (aiVector3F *)sz; - ::memcpy(&theVec3F, theVec, sizeof(aiVector3F)); + theVec = (aiVector3f *)sz; + ::memcpy(&theVec3F, theVec, sizeof(aiVector3f)); vn->x = theVec3F.x; vn->y = theVec3F.y; vn->z = theVec3F.z; @@ -471,7 +470,7 @@ bool STLImporter::LoadBinaryFile() { vn += 3; // vertex 1 - ::memcpy(&theVec3F, theVec, sizeof(aiVector3F)); + ::memcpy(&theVec3F, theVec, sizeof(aiVector3f)); vp->x = theVec3F.x; vp->y = theVec3F.y; vp->z = theVec3F.z; @@ -479,7 +478,7 @@ bool STLImporter::LoadBinaryFile() { ++vp; // vertex 2 - ::memcpy(&theVec3F, theVec, sizeof(aiVector3F)); + ::memcpy(&theVec3F, theVec, sizeof(aiVector3f)); vp->x = theVec3F.x; vp->y = theVec3F.y; vp->z = theVec3F.z; @@ -487,7 +486,7 @@ bool STLImporter::LoadBinaryFile() { ++vp; // vertex 3 - ::memcpy(&theVec3F, theVec, sizeof(aiVector3F)); + ::memcpy(&theVec3F, theVec, sizeof(aiVector3f)); vp->x = theVec3F.x; vp->y = theVec3F.y; vp->z = theVec3F.z; @@ -570,4 +569,6 @@ void STLImporter::pushMeshesToNode(std::vector &meshIndices, aiNod meshIndices.clear(); } +} // namespace Assimp + #endif // !! ASSIMP_BUILD_NO_STL_IMPORTER diff --git a/code/AssetLib/Terragen/TerragenLoader.cpp b/code/AssetLib/Terragen/TerragenLoader.cpp index 738ad8e27..b1870414c 100644 --- a/code/AssetLib/Terragen/TerragenLoader.cpp +++ b/code/AssetLib/Terragen/TerragenLoader.cpp @@ -51,9 +51,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include -using namespace Assimp; +namespace Assimp { -static const aiImporterDesc desc = { +static constexpr aiImporterDesc desc = { "Terragen Heightmap Importer", "", "", @@ -73,10 +73,6 @@ TerragenImporter::TerragenImporter() : // empty } -// ------------------------------------------------------------------------------------------------ -// Destructor, private as well -TerragenImporter::~TerragenImporter() = default; - // ------------------------------------------------------------------------------------------------ // Returns whether the class can handle the format of the given file. bool TerragenImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /*checkSig*/) const { @@ -244,4 +240,6 @@ void TerragenImporter::InternReadFile(const std::string &pFile, pScene->mFlags |= AI_SCENE_FLAGS_TERRAIN; } +} // namespace Assimp + #endif // !! ASSIMP_BUILD_NO_TERRAGEN_IMPORTER diff --git a/code/AssetLib/Terragen/TerragenLoader.h b/code/AssetLib/Terragen/TerragenLoader.h index cb9ff9166..0c7b686e9 100644 --- a/code/AssetLib/Terragen/TerragenLoader.h +++ b/code/AssetLib/Terragen/TerragenLoader.h @@ -73,7 +73,7 @@ namespace Assimp { class TerragenImporter : public BaseImporter { public: TerragenImporter(); - ~TerragenImporter() override; + ~TerragenImporter() override = default; // ------------------------------------------------------------------- bool CanRead(const std::string &pFile, IOSystem *pIOHandler, diff --git a/code/AssetLib/Unreal/UnrealLoader.cpp b/code/AssetLib/Unreal/UnrealLoader.cpp index f2b0ab118..5f622da42 100644 --- a/code/AssetLib/Unreal/UnrealLoader.cpp +++ b/code/AssetLib/Unreal/UnrealLoader.cpp @@ -63,7 +63,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include -using namespace Assimp; +namespace Assimp { namespace Unreal { @@ -152,7 +152,7 @@ inline void DecompressVertex(aiVector3D &v, int32_t in) { } // end namespace Unreal -static const aiImporterDesc desc = { +static constexpr aiImporterDesc desc = { "Unreal Mesh Importer", "", "", @@ -178,7 +178,7 @@ UnrealImporter::~UnrealImporter() = default; // ------------------------------------------------------------------------------------------------ // Returns whether the class can handle the format of the given file. -bool UnrealImporter::CanRead(const std::string & filename, IOSystem * /*pIOHandler*/, bool /*checkSig*/) const { +bool UnrealImporter::CanRead(const std::string &filename, IOSystem * /*pIOHandler*/, bool /*checkSig*/) const { return SimpleExtensionCheck(filename, "3d", "uc"); } @@ -336,12 +336,12 @@ void UnrealImporter::InternReadFile(const std::string &pFile, tempTextures.emplace_back(); std::pair &me = tempTextures.back(); for (; !IsLineEnd(*data); ++data) { - if (!::ASSIMP_strincmp(data, "NAME=", 5)) { + if (!ASSIMP_strincmp(data, "NAME=", 5)) { const char *d = data += 5; for (; !IsSpaceOrNewLine(*data); ++data) ; me.first = std::string(d, (size_t)(data - d)); - } else if (!::ASSIMP_strincmp(data, "FILE=", 5)) { + } else if (!ASSIMP_strincmp(data, "FILE=", 5)) { const char *d = data += 5; for (; !IsSpaceOrNewLine(*data); ++data) ; @@ -363,10 +363,10 @@ void UnrealImporter::InternReadFile(const std::string &pFile, std::pair &me = textures.back(); for (; !IsLineEnd(*data); ++data) { - if (!::ASSIMP_strincmp(data, "NUM=", 4)) { + if (!ASSIMP_strincmp(data, "NUM=", 4)) { data += 4; me.first = strtoul10(data, &data); - } else if (!::ASSIMP_strincmp(data, "TEXTURE=", 8)) { + } else if (!ASSIMP_strincmp(data, "TEXTURE=", 8)) { data += 8; const char *d = data; for (; !IsSpaceOrNewLine(*data); ++data) @@ -516,4 +516,6 @@ void UnrealImporter::InternReadFile(const std::string &pFile, flipper.Execute(pScene); } +} // namespace Assimp + #endif // !! ASSIMP_BUILD_NO_3D_IMPORTER diff --git a/code/AssetLib/X/XFileImporter.cpp b/code/AssetLib/X/XFileImporter.cpp index 1474ad808..00f44b34b 100644 --- a/code/AssetLib/X/XFileImporter.cpp +++ b/code/AssetLib/X/XFileImporter.cpp @@ -57,10 +57,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include -using namespace Assimp; +namespace Assimp { + using namespace Assimp::Formatter; -static const aiImporterDesc desc = { +static constexpr aiImporterDesc desc = { "Direct3D XFile Importer", "", "", @@ -73,142 +74,137 @@ static const aiImporterDesc desc = { "x" }; -// ------------------------------------------------------------------------------------------------ -// Constructor to be privately used by Importer -XFileImporter::XFileImporter() = default; - // ------------------------------------------------------------------------------------------------ // Returns whether the class can handle the format of the given file. -bool XFileImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool /*checkSig*/) const { +bool XFileImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /*checkSig*/) const { static const uint32_t token[] = { AI_MAKE_MAGIC("xof ") }; - return CheckMagicToken(pIOHandler,pFile,token,AI_COUNT_OF(token)); + return CheckMagicToken(pIOHandler, pFile, token, AI_COUNT_OF(token)); } // ------------------------------------------------------------------------------------------------ // Get file extension list -const aiImporterDesc* XFileImporter::GetInfo () const { +const aiImporterDesc *XFileImporter::GetInfo() const { return &desc; } // ------------------------------------------------------------------------------------------------ // Imports the given file into the given scene structure. -void XFileImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler) { +void XFileImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler) { // read file into memory - std::unique_ptr file( pIOHandler->Open( pFile)); + std::unique_ptr file(pIOHandler->Open(pFile)); if (file == nullptr) { - throw DeadlyImportError( "Failed to open file ", pFile, "." ); + throw DeadlyImportError("Failed to open file ", pFile, "."); } static const size_t MinSize = 16; size_t fileSize = file->FileSize(); - if ( fileSize < MinSize ) { - throw DeadlyImportError( "XFile is too small." ); + if (fileSize < MinSize) { + throw DeadlyImportError("XFile is too small."); } // in the hope that binary files will never start with a BOM ... - mBuffer.resize( fileSize + 1); - file->Read( &mBuffer.front(), 1, fileSize); + mBuffer.resize(fileSize + 1); + file->Read(&mBuffer.front(), 1, fileSize); ConvertToUTF8(mBuffer); // parse the file into a temporary representation - XFileParser parser( mBuffer); + XFileParser parser(mBuffer); // and create the proper return structures out of it - CreateDataRepresentationFromImport( pScene, parser.GetImportedData()); + CreateDataRepresentationFromImport(pScene, parser.GetImportedData()); // if nothing came from it, report it as error - if ( !pScene->mRootNode ) { - throw DeadlyImportError( "XFile is ill-formatted - no content imported." ); + if (!pScene->mRootNode) { + throw DeadlyImportError("XFile is ill-formatted - no content imported."); } } // ------------------------------------------------------------------------------------------------ // Constructs the return data structure out of the imported data. -void XFileImporter::CreateDataRepresentationFromImport( aiScene* pScene, XFile::Scene* pData) -{ +void XFileImporter::CreateDataRepresentationFromImport(aiScene *pScene, XFile::Scene *pData) { // Read the global materials first so that meshes referring to them can find them later - ConvertMaterials( pScene, pData->mGlobalMaterials); + ConvertMaterials(pScene, pData->mGlobalMaterials); // copy nodes, extracting meshes and materials on the way - pScene->mRootNode = CreateNodes( pScene, nullptr, pData->mRootNode); + pScene->mRootNode = CreateNodes(pScene, nullptr, pData->mRootNode); // extract animations - CreateAnimations( pScene, pData); + CreateAnimations(pScene, pData); // read the global meshes that were stored outside of any node - if( !pData->mGlobalMeshes.empty() ) { + if (!pData->mGlobalMeshes.empty()) { // create a root node to hold them if there isn't any, yet - if( pScene->mRootNode == nullptr ) { + if (pScene->mRootNode == nullptr) { pScene->mRootNode = new aiNode; - pScene->mRootNode->mName.Set( "$dummy_node"); + pScene->mRootNode->mName.Set("$dummy_node"); } // convert all global meshes and store them in the root node. // If there was one before, the global meshes now suddenly have its transformation matrix... // Don't know what to do there, I don't want to insert another node under the present root node // just to avoid this. - CreateMeshes( pScene, pScene->mRootNode, pData->mGlobalMeshes); + CreateMeshes(pScene, pScene->mRootNode, pData->mGlobalMeshes); } if (!pScene->mRootNode) { - throw DeadlyImportError( "No root node" ); + throw DeadlyImportError("No root node"); } // Convert everything to OpenGL space... it's the same operation as the conversion back, so we can reuse the step directly MakeLeftHandedProcess convertProcess; - convertProcess.Execute( pScene); + convertProcess.Execute(pScene); FlipWindingOrderProcess flipper; flipper.Execute(pScene); // finally: create a dummy material if not material was imported - if( pScene->mNumMaterials == 0) { + if (pScene->mNumMaterials == 0) { pScene->mNumMaterials = 1; // create the Material - aiMaterial* mat = new aiMaterial; - int shadeMode = (int) aiShadingMode_Gouraud; - mat->AddProperty( &shadeMode, 1, AI_MATKEY_SHADING_MODEL); + aiMaterial *mat = new aiMaterial; + int shadeMode = (int)aiShadingMode_Gouraud; + mat->AddProperty(&shadeMode, 1, AI_MATKEY_SHADING_MODEL); // material colours int specExp = 1; - aiColor3D clr = aiColor3D( 0, 0, 0); - mat->AddProperty( &clr, 1, AI_MATKEY_COLOR_EMISSIVE); - mat->AddProperty( &clr, 1, AI_MATKEY_COLOR_SPECULAR); + aiColor3D clr = aiColor3D(0, 0, 0); + mat->AddProperty(&clr, 1, AI_MATKEY_COLOR_EMISSIVE); + mat->AddProperty(&clr, 1, AI_MATKEY_COLOR_SPECULAR); - clr = aiColor3D( 0.5f, 0.5f, 0.5f); - mat->AddProperty( &clr, 1, AI_MATKEY_COLOR_DIFFUSE); - mat->AddProperty( &specExp, 1, AI_MATKEY_SHININESS); + clr = aiColor3D(0.5f, 0.5f, 0.5f); + mat->AddProperty(&clr, 1, AI_MATKEY_COLOR_DIFFUSE); + mat->AddProperty(&specExp, 1, AI_MATKEY_SHININESS); - pScene->mMaterials = new aiMaterial*[1]; + pScene->mMaterials = new aiMaterial *[1]; pScene->mMaterials[0] = mat; } } // ------------------------------------------------------------------------------------------------ // Recursively creates scene nodes from the imported hierarchy. -aiNode* XFileImporter::CreateNodes( aiScene* pScene, aiNode* pParent, const XFile::Node* pNode) { - if ( !pNode ) { +aiNode *XFileImporter::CreateNodes(aiScene *pScene, aiNode *pParent, const XFile::Node *pNode) { + if (!pNode) { return nullptr; } // create node - aiNode* node = new aiNode; + aiNode *node = new aiNode; node->mName.length = (ai_uint32)pNode->mName.length(); node->mParent = pParent; - memcpy( node->mName.data, pNode->mName.c_str(), pNode->mName.length()); + memcpy(node->mName.data, pNode->mName.c_str(), pNode->mName.length()); node->mName.data[node->mName.length] = 0; node->mTransformation = pNode->mTrafoMatrix; // convert meshes from the source node - CreateMeshes( pScene, node, pNode->mMeshes); + CreateMeshes(pScene, node, pNode->mMeshes); // handle children - if( !pNode->mChildren.empty() ) { + if (!pNode->mChildren.empty()) { node->mNumChildren = (unsigned int)pNode->mChildren.size(); - node->mChildren = new aiNode* [node->mNumChildren]; + node->mChildren = new aiNode *[node->mNumChildren]; - for ( unsigned int a = 0; a < pNode->mChildren.size(); ++a ) { - node->mChildren[ a ] = CreateNodes( pScene, node, pNode->mChildren[ a ] ); + for (unsigned int a = 0; a < pNode->mChildren.size(); ++a) { + node->mChildren[a] = CreateNodes(pScene, node, pNode->mChildren[a]); } } @@ -217,55 +213,55 @@ aiNode* XFileImporter::CreateNodes( aiScene* pScene, aiNode* pParent, const XFil // ------------------------------------------------------------------------------------------------ // Creates the meshes for the given node. -void XFileImporter::CreateMeshes( aiScene* pScene, aiNode* pNode, const std::vector& pMeshes) { +void XFileImporter::CreateMeshes(aiScene *pScene, aiNode *pNode, const std::vector &pMeshes) { if (pMeshes.empty()) { return; } // create a mesh for each mesh-material combination in the source node - std::vector meshes; - for( unsigned int a = 0; a < pMeshes.size(); ++a ) { - XFile::Mesh* sourceMesh = pMeshes[a]; - if ( nullptr == sourceMesh ) { + std::vector meshes; + for (unsigned int a = 0; a < pMeshes.size(); ++a) { + XFile::Mesh *sourceMesh = pMeshes[a]; + if (nullptr == sourceMesh) { continue; } // first convert its materials so that we can find them with their index afterwards - ConvertMaterials( pScene, sourceMesh->mMaterials); + ConvertMaterials(pScene, sourceMesh->mMaterials); - unsigned int numMaterials = std::max( (unsigned int)sourceMesh->mMaterials.size(), 1u); - for( unsigned int b = 0; b < numMaterials; ++b ) { + unsigned int numMaterials = std::max((unsigned int)sourceMesh->mMaterials.size(), 1u); + for (unsigned int b = 0; b < numMaterials; ++b) { // collect the faces belonging to this material std::vector faces; unsigned int numVertices = 0; - if( !sourceMesh->mFaceMaterials.empty() ) { + if (!sourceMesh->mFaceMaterials.empty()) { // if there is a per-face material defined, select the faces with the corresponding material - for( unsigned int c = 0; c < sourceMesh->mFaceMaterials.size(); ++c ) { - if( sourceMesh->mFaceMaterials[c] == b) { - faces.push_back( c); + for (unsigned int c = 0; c < sourceMesh->mFaceMaterials.size(); ++c) { + if (sourceMesh->mFaceMaterials[c] == b) { + faces.push_back(c); numVertices += (unsigned int)sourceMesh->mPosFaces[c].mIndices.size(); } } } else { // if there is no per-face material, place everything into one mesh - for( unsigned int c = 0; c < sourceMesh->mPosFaces.size(); ++c ) { - faces.push_back( c); + for (unsigned int c = 0; c < sourceMesh->mPosFaces.size(); ++c) { + faces.push_back(c); numVertices += (unsigned int)sourceMesh->mPosFaces[c].mIndices.size(); } } // no faces/vertices using this material? strange... - if ( numVertices == 0 ) { + if (numVertices == 0) { continue; } // create a submesh using this material - aiMesh* mesh = new aiMesh; - meshes.push_back( mesh); + aiMesh *mesh = new aiMesh; + meshes.push_back(mesh); // find the material in the scene's material list. Either own material // or referenced material, it should already have a valid index - if( !sourceMesh->mFaceMaterials.empty() ) { + if (!sourceMesh->mFaceMaterials.empty()) { mesh->mMaterialIndex = static_cast(sourceMesh->mMaterials[b].sceneIndex); } else { mesh->mMaterialIndex = 0; @@ -282,41 +278,41 @@ void XFileImporter::CreateMeshes( aiScene* pScene, aiNode* pNode, const std::vec mesh->mName.Set(sourceMesh->mName); // normals? - if ( sourceMesh->mNormals.size() > 0 ) { - mesh->mNormals = new aiVector3D[ numVertices ]; + if (sourceMesh->mNormals.size() > 0) { + mesh->mNormals = new aiVector3D[numVertices]; } // texture coords - for( unsigned int c = 0; c < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++c ) { - if ( !sourceMesh->mTexCoords[ c ].empty() ) { - mesh->mTextureCoords[ c ] = new aiVector3D[ numVertices ]; + for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++c) { + if (!sourceMesh->mTexCoords[c].empty()) { + mesh->mTextureCoords[c] = new aiVector3D[numVertices]; } } // vertex colors - for( unsigned int c = 0; c < AI_MAX_NUMBER_OF_COLOR_SETS; ++c ) { - if ( !sourceMesh->mColors[ c ].empty() ) { - mesh->mColors[ c ] = new aiColor4D[ numVertices ]; + for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_COLOR_SETS; ++c) { + if (!sourceMesh->mColors[c].empty()) { + mesh->mColors[c] = new aiColor4D[numVertices]; } } // now collect the vertex data of all data streams present in the imported mesh - unsigned int newIndex( 0 ); + unsigned int newIndex(0); std::vector orgPoints; // from which original point each new vertex stems - orgPoints.resize( numVertices, 0); + orgPoints.resize(numVertices, 0); - for( unsigned int c = 0; c < faces.size(); ++c ) { + for (unsigned int c = 0; c < faces.size(); ++c) { unsigned int f = faces[c]; // index of the source face - const XFile::Face& pf = sourceMesh->mPosFaces[f]; // position source face + const XFile::Face &pf = sourceMesh->mPosFaces[f]; // position source face // create face. either triangle or triangle fan depending on the index count - aiFace& df = mesh->mFaces[c]; // destination face + aiFace &df = mesh->mFaces[c]; // destination face df.mNumIndices = (unsigned int)pf.mIndices.size(); - df.mIndices = new unsigned int[ df.mNumIndices]; + df.mIndices = new unsigned int[df.mNumIndices]; // collect vertex data for indices of this face - for( unsigned int d = 0; d < df.mNumIndices; ++d ) { - df.mIndices[ d ] = newIndex; - const unsigned int newIdx( pf.mIndices[ d ] ); - if ( newIdx > sourceMesh->mPositions.size() ) { + for (unsigned int d = 0; d < df.mNumIndices; ++d) { + df.mIndices[d] = newIndex; + const unsigned int newIdx = pf.mIndices[d]; + if (newIdx >= sourceMesh->mPositions.size()) { continue; } @@ -325,24 +321,26 @@ void XFileImporter::CreateMeshes( aiScene* pScene, aiNode* pNode, const std::vec // Position mesh->mVertices[newIndex] = sourceMesh->mPositions[pf.mIndices[d]]; // Normal, if present - if ( mesh->HasNormals() ) { - if ( sourceMesh->mNormFaces[ f ].mIndices.size() > d ) { - const size_t idx( sourceMesh->mNormFaces[ f ].mIndices[ d ] ); - mesh->mNormals[ newIndex ] = sourceMesh->mNormals[ idx ]; + if (mesh->HasNormals()) { + if (sourceMesh->mNormFaces[f].mIndices.size() > d) { + const size_t idx(sourceMesh->mNormFaces[f].mIndices[d]); + if (idx < sourceMesh->mNormals.size()) { + mesh->mNormals[newIndex] = sourceMesh->mNormals[idx]; + } } } // texture coord sets - for( unsigned int e = 0; e < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++e ) { - if( mesh->HasTextureCoords( e)) { + for (unsigned int e = 0; e < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++e) { + if (mesh->HasTextureCoords(e)) { aiVector2D tex = sourceMesh->mTexCoords[e][pf.mIndices[d]]; - mesh->mTextureCoords[e][newIndex] = aiVector3D( tex.x, 1.0f - tex.y, 0.0f); + mesh->mTextureCoords[e][newIndex] = aiVector3D(tex.x, 1.0f - tex.y, 0.0f); } } // vertex color sets - for ( unsigned int e = 0; e < AI_MAX_NUMBER_OF_COLOR_SETS; ++e ) { - if ( mesh->HasVertexColors( e ) ) { - mesh->mColors[ e ][ newIndex ] = sourceMesh->mColors[ e ][ pf.mIndices[ d ] ]; + for (unsigned int e = 0; e < AI_MAX_NUMBER_OF_COLOR_SETS; ++e) { + if (mesh->HasVertexColors(e)) { + mesh->mColors[e][newIndex] = sourceMesh->mColors[e][pf.mIndices[d]]; } } @@ -351,63 +349,66 @@ void XFileImporter::CreateMeshes( aiScene* pScene, aiNode* pNode, const std::vec } // there should be as much new vertices as we calculated before - ai_assert( newIndex == numVertices); + ai_assert(newIndex == numVertices); // convert all bones of the source mesh which influence vertices in this newly created mesh - const std::vector& bones = sourceMesh->mBones; - std::vector newBones; - for( unsigned int c = 0; c < bones.size(); ++c ) { - const XFile::Bone& obone = bones[c]; + const std::vector &bones = sourceMesh->mBones; + std::vector newBones; + for (unsigned int c = 0; c < bones.size(); ++c) { + const XFile::Bone &obone = bones[c]; // set up a vertex-linear array of the weights for quick searching if a bone influences a vertex - std::vector oldWeights( sourceMesh->mPositions.size(), 0.0); - for ( unsigned int d = 0; d < obone.mWeights.size(); ++d ) { - oldWeights[ obone.mWeights[ d ].mVertex ] = obone.mWeights[ d ].mWeight; + std::vector oldWeights(sourceMesh->mPositions.size(), 0.0); + for (unsigned int d = 0; d < obone.mWeights.size(); ++d) { + const unsigned int boneIdx = obone.mWeights[d].mVertex; + if (boneIdx < obone.mWeights.size()) { + oldWeights[obone.mWeights[d].mVertex] = obone.mWeights[d].mWeight; + } } // collect all vertex weights that influence a vertex in the new mesh std::vector newWeights; - newWeights.reserve( numVertices); - for( unsigned int d = 0; d < orgPoints.size(); ++d ) { + newWeights.reserve(numVertices); + for (unsigned int d = 0; d < orgPoints.size(); ++d) { // does the new vertex stem from an old vertex which was influenced by this bone? ai_real w = oldWeights[orgPoints[d]]; - if ( w > 0.0 ) { - newWeights.emplace_back( d, w ); + if (w > 0.0) { + newWeights.emplace_back(d, w); } } // if the bone has no weights in the newly created mesh, ignore it - if ( newWeights.empty() ) { + if (newWeights.empty()) { continue; } // create - aiBone* nbone = new aiBone; - newBones.push_back( nbone); + aiBone *nbone = new aiBone; + newBones.push_back(nbone); // copy name and matrix - nbone->mName.Set( obone.mName); + nbone->mName.Set(obone.mName); nbone->mOffsetMatrix = obone.mOffsetMatrix; nbone->mNumWeights = (unsigned int)newWeights.size(); nbone->mWeights = new aiVertexWeight[nbone->mNumWeights]; - for ( unsigned int d = 0; d < newWeights.size(); ++d ) { - nbone->mWeights[ d ] = newWeights[ d ]; + for (unsigned int d = 0; d < newWeights.size(); ++d) { + nbone->mWeights[d] = newWeights[d]; } } // store the bones in the mesh mesh->mNumBones = (unsigned int)newBones.size(); - if( !newBones.empty()) { - mesh->mBones = new aiBone*[mesh->mNumBones]; - std::copy( newBones.begin(), newBones.end(), mesh->mBones); + if (!newBones.empty()) { + mesh->mBones = new aiBone *[mesh->mNumBones]; + std::copy(newBones.begin(), newBones.end(), mesh->mBones); } } } // reallocate scene mesh array to be large enough - aiMesh** prevArray = pScene->mMeshes; - pScene->mMeshes = new aiMesh*[pScene->mNumMeshes + meshes.size()]; - if( prevArray) { - memcpy( pScene->mMeshes, prevArray, pScene->mNumMeshes * sizeof( aiMesh*)); - delete [] prevArray; + aiMesh **prevArray = pScene->mMeshes; + pScene->mMeshes = new aiMesh *[pScene->mNumMeshes + meshes.size()]; + if (prevArray) { + memcpy(pScene->mMeshes, prevArray, pScene->mNumMeshes * sizeof(aiMesh *)); + delete[] prevArray; } // allocate mesh index array in the node @@ -415,7 +416,7 @@ void XFileImporter::CreateMeshes( aiScene* pScene, aiNode* pNode, const std::vec pNode->mMeshes = new unsigned int[pNode->mNumMeshes]; // store all meshes in the mesh library of the scene and store their indices in the node - for( unsigned int a = 0; a < meshes.size(); a++) { + for (unsigned int a = 0; a < meshes.size(); a++) { pScene->mMeshes[pScene->mNumMeshes] = meshes[a]; pNode->mMeshes[a] = pScene->mNumMeshes; pScene->mNumMeshes++; @@ -424,35 +425,34 @@ void XFileImporter::CreateMeshes( aiScene* pScene, aiNode* pNode, const std::vec // ------------------------------------------------------------------------------------------------ // Converts the animations from the given imported data and creates them in the scene. -void XFileImporter::CreateAnimations( aiScene* pScene, const XFile::Scene* pData) { - std::vector newAnims; +void XFileImporter::CreateAnimations(aiScene *pScene, const XFile::Scene *pData) { + std::vector newAnims; - for( unsigned int a = 0; a < pData->mAnims.size(); ++a ) { - const XFile::Animation* anim = pData->mAnims[a]; + for (unsigned int a = 0; a < pData->mAnims.size(); ++a) { + const XFile::Animation *anim = pData->mAnims[a]; // some exporters mock me with empty animation tags. - if ( anim->mAnims.empty() ) { + if (anim->mAnims.empty()) { continue; } // create a new animation to hold the data - aiAnimation* nanim = new aiAnimation; - newAnims.push_back( nanim); - nanim->mName.Set( anim->mName); + aiAnimation *nanim = new aiAnimation; + newAnims.push_back(nanim); + nanim->mName.Set(anim->mName); // duration will be determined by the maximum length nanim->mDuration = 0; nanim->mTicksPerSecond = pData->mAnimTicksPerSecond; nanim->mNumChannels = (unsigned int)anim->mAnims.size(); - nanim->mChannels = new aiNodeAnim*[nanim->mNumChannels]; + nanim->mChannels = new aiNodeAnim *[nanim->mNumChannels]; - for( unsigned int b = 0; b < anim->mAnims.size(); ++b ) { - const XFile::AnimBone* bone = anim->mAnims[b]; - aiNodeAnim* nbone = new aiNodeAnim; - nbone->mNodeName.Set( bone->mBoneName); + for (unsigned int b = 0; b < anim->mAnims.size(); ++b) { + const XFile::AnimBone *bone = anim->mAnims[b]; + aiNodeAnim *nbone = new aiNodeAnim; + nbone->mNodeName.Set(bone->mBoneName); nanim->mChannels[b] = nbone; // key-frames are given as combined transformation matrix keys - if( !bone->mTrafoKeys.empty() ) - { + if (!bone->mTrafoKeys.empty()) { nbone->mNumPositionKeys = (unsigned int)bone->mTrafoKeys.size(); nbone->mPositionKeys = new aiVectorKey[nbone->mNumPositionKeys]; nbone->mNumRotationKeys = (unsigned int)bone->mTrafoKeys.size(); @@ -460,44 +460,44 @@ void XFileImporter::CreateAnimations( aiScene* pScene, const XFile::Scene* pData nbone->mNumScalingKeys = (unsigned int)bone->mTrafoKeys.size(); nbone->mScalingKeys = new aiVectorKey[nbone->mNumScalingKeys]; - for( unsigned int c = 0; c < bone->mTrafoKeys.size(); ++c) { + for (unsigned int c = 0; c < bone->mTrafoKeys.size(); ++c) { // deconstruct each matrix into separate position, rotation and scaling double time = bone->mTrafoKeys[c].mTime; aiMatrix4x4 trafo = bone->mTrafoKeys[c].mMatrix; // extract position - aiVector3D pos( trafo.a4, trafo.b4, trafo.c4); + aiVector3D pos(trafo.a4, trafo.b4, trafo.c4); nbone->mPositionKeys[c].mTime = time; nbone->mPositionKeys[c].mValue = pos; // extract scaling aiVector3D scale; - scale.x = aiVector3D( trafo.a1, trafo.b1, trafo.c1).Length(); - scale.y = aiVector3D( trafo.a2, trafo.b2, trafo.c2).Length(); - scale.z = aiVector3D( trafo.a3, trafo.b3, trafo.c3).Length(); + scale.x = aiVector3D(trafo.a1, trafo.b1, trafo.c1).Length(); + scale.y = aiVector3D(trafo.a2, trafo.b2, trafo.c2).Length(); + scale.z = aiVector3D(trafo.a3, trafo.b3, trafo.c3).Length(); nbone->mScalingKeys[c].mTime = time; nbone->mScalingKeys[c].mValue = scale; // reconstruct rotation matrix without scaling aiMatrix3x3 rotmat( - trafo.a1 / scale.x, trafo.a2 / scale.y, trafo.a3 / scale.z, - trafo.b1 / scale.x, trafo.b2 / scale.y, trafo.b3 / scale.z, - trafo.c1 / scale.x, trafo.c2 / scale.y, trafo.c3 / scale.z); + trafo.a1 / scale.x, trafo.a2 / scale.y, trafo.a3 / scale.z, + trafo.b1 / scale.x, trafo.b2 / scale.y, trafo.b3 / scale.z, + trafo.c1 / scale.x, trafo.c2 / scale.y, trafo.c3 / scale.z); // and convert it into a quaternion nbone->mRotationKeys[c].mTime = time; - nbone->mRotationKeys[c].mValue = aiQuaternion( rotmat); + nbone->mRotationKeys[c].mValue = aiQuaternion(rotmat); } // longest lasting key sequence determines duration - nanim->mDuration = std::max( nanim->mDuration, bone->mTrafoKeys.back().mTime); + nanim->mDuration = std::max(nanim->mDuration, bone->mTrafoKeys.back().mTime); } else { // separate key sequences for position, rotation, scaling nbone->mNumPositionKeys = (unsigned int)bone->mPosKeys.size(); if (nbone->mNumPositionKeys != 0) { nbone->mPositionKeys = new aiVectorKey[nbone->mNumPositionKeys]; - for( unsigned int c = 0; c < nbone->mNumPositionKeys; ++c ) { + for (unsigned int c = 0; c < nbone->mNumPositionKeys; ++c) { aiVector3D pos = bone->mPosKeys[c].mValue; nbone->mPositionKeys[c].mTime = bone->mPosKeys[c].mTime; @@ -509,11 +509,11 @@ void XFileImporter::CreateAnimations( aiScene* pScene, const XFile::Scene* pData nbone->mNumRotationKeys = (unsigned int)bone->mRotKeys.size(); if (nbone->mNumRotationKeys != 0) { nbone->mRotationKeys = new aiQuatKey[nbone->mNumRotationKeys]; - for( unsigned int c = 0; c < nbone->mNumRotationKeys; ++c ) { + for (unsigned int c = 0; c < nbone->mNumRotationKeys; ++c) { aiMatrix3x3 rotmat = bone->mRotKeys[c].mValue.GetMatrix(); nbone->mRotationKeys[c].mTime = bone->mRotKeys[c].mTime; - nbone->mRotationKeys[c].mValue = aiQuaternion( rotmat); + nbone->mRotationKeys[c].mValue = aiQuaternion(rotmat); nbone->mRotationKeys[c].mValue.w *= -1.0f; // needs quat inversion } } @@ -522,153 +522,149 @@ void XFileImporter::CreateAnimations( aiScene* pScene, const XFile::Scene* pData nbone->mNumScalingKeys = (unsigned int)bone->mScaleKeys.size(); if (nbone->mNumScalingKeys != 0) { nbone->mScalingKeys = new aiVectorKey[nbone->mNumScalingKeys]; - for( unsigned int c = 0; c < nbone->mNumScalingKeys; c++) + for (unsigned int c = 0; c < nbone->mNumScalingKeys; c++) nbone->mScalingKeys[c] = bone->mScaleKeys[c]; } // longest lasting key sequence determines duration - if( bone->mPosKeys.size() > 0) - nanim->mDuration = std::max( nanim->mDuration, bone->mPosKeys.back().mTime); - if( bone->mRotKeys.size() > 0) - nanim->mDuration = std::max( nanim->mDuration, bone->mRotKeys.back().mTime); - if( bone->mScaleKeys.size() > 0) - nanim->mDuration = std::max( nanim->mDuration, bone->mScaleKeys.back().mTime); + if (bone->mPosKeys.size() > 0) + nanim->mDuration = std::max(nanim->mDuration, bone->mPosKeys.back().mTime); + if (bone->mRotKeys.size() > 0) + nanim->mDuration = std::max(nanim->mDuration, bone->mRotKeys.back().mTime); + if (bone->mScaleKeys.size() > 0) + nanim->mDuration = std::max(nanim->mDuration, bone->mScaleKeys.back().mTime); } } } // store all converted animations in the scene - if( newAnims.size() > 0) - { + if (newAnims.size() > 0) { pScene->mNumAnimations = (unsigned int)newAnims.size(); - pScene->mAnimations = new aiAnimation* [pScene->mNumAnimations]; - for( unsigned int a = 0; a < newAnims.size(); a++) + pScene->mAnimations = new aiAnimation *[pScene->mNumAnimations]; + for (unsigned int a = 0; a < newAnims.size(); a++) pScene->mAnimations[a] = newAnims[a]; } } // ------------------------------------------------------------------------------------------------ // Converts all materials in the given array and stores them in the scene's material list. -void XFileImporter::ConvertMaterials( aiScene* pScene, std::vector& pMaterials) -{ +void XFileImporter::ConvertMaterials(aiScene *pScene, std::vector &pMaterials) { // count the non-referrer materials in the array - unsigned int numNewMaterials( 0 ); - for ( unsigned int a = 0; a < pMaterials.size(); ++a ) { - if ( !pMaterials[ a ].mIsReference ) { + unsigned int numNewMaterials(0); + for (unsigned int a = 0; a < pMaterials.size(); ++a) { + if (!pMaterials[a].mIsReference) { ++numNewMaterials; } } // resize the scene's material list to offer enough space for the new materials - if( numNewMaterials > 0 ) { - aiMaterial** prevMats = pScene->mMaterials; - pScene->mMaterials = new aiMaterial*[pScene->mNumMaterials + numNewMaterials]; - if( nullptr != prevMats) { - ::memcpy( pScene->mMaterials, prevMats, pScene->mNumMaterials * sizeof( aiMaterial*)); - delete [] prevMats; + if (numNewMaterials > 0) { + aiMaterial **prevMats = pScene->mMaterials; + pScene->mMaterials = new aiMaterial *[pScene->mNumMaterials + numNewMaterials]; + if (nullptr != prevMats) { + ::memcpy(pScene->mMaterials, prevMats, pScene->mNumMaterials * sizeof(aiMaterial *)); + delete[] prevMats; } } // convert all the materials given in the array - for( unsigned int a = 0; a < pMaterials.size(); ++a ) { - XFile::Material& oldMat = pMaterials[a]; - if( oldMat.mIsReference) { + for (unsigned int a = 0; a < pMaterials.size(); ++a) { + XFile::Material &oldMat = pMaterials[a]; + if (oldMat.mIsReference) { // find the material it refers to by name, and store its index - for( size_t b = 0; b < pScene->mNumMaterials; ++b ) { + for (size_t b = 0; b < pScene->mNumMaterials; ++b) { aiString name; - pScene->mMaterials[b]->Get( AI_MATKEY_NAME, name); - if( strcmp( name.C_Str(), oldMat.mName.data()) == 0 ) { + pScene->mMaterials[b]->Get(AI_MATKEY_NAME, name); + if (strcmp(name.C_Str(), oldMat.mName.data()) == 0) { oldMat.sceneIndex = b; break; } } - if( oldMat.sceneIndex == SIZE_MAX ) { - ASSIMP_LOG_WARN( "Could not resolve global material reference \"", oldMat.mName, "\"" ); + if (oldMat.sceneIndex == SIZE_MAX) { + ASSIMP_LOG_WARN("Could not resolve global material reference \"", oldMat.mName, "\""); oldMat.sceneIndex = 0; } continue; } - aiMaterial* mat = new aiMaterial; + aiMaterial *mat = new aiMaterial; aiString name; - name.Set( oldMat.mName); - mat->AddProperty( &name, AI_MATKEY_NAME); + name.Set(oldMat.mName); + mat->AddProperty(&name, AI_MATKEY_NAME); // Shading model: hard-coded to PHONG, there is no such information in an XFile // FIX (aramis): If the specular exponent is 0, use gouraud shading. This is a bugfix // for some models in the SDK (e.g. good old tiny.x) - int shadeMode = (int)oldMat.mSpecularExponent == 0.0f - ? aiShadingMode_Gouraud : aiShadingMode_Phong; + int shadeMode = (int)oldMat.mSpecularExponent == 0.0f ? aiShadingMode_Gouraud : aiShadingMode_Phong; - mat->AddProperty( &shadeMode, 1, AI_MATKEY_SHADING_MODEL); + mat->AddProperty(&shadeMode, 1, AI_MATKEY_SHADING_MODEL); // material colours // Unclear: there's no ambient colour, but emissive. What to put for ambient? // Probably nothing at all, let the user select a suitable default. - mat->AddProperty( &oldMat.mEmissive, 1, AI_MATKEY_COLOR_EMISSIVE); - mat->AddProperty( &oldMat.mDiffuse, 1, AI_MATKEY_COLOR_DIFFUSE); - mat->AddProperty( &oldMat.mSpecular, 1, AI_MATKEY_COLOR_SPECULAR); - mat->AddProperty( &oldMat.mSpecularExponent, 1, AI_MATKEY_SHININESS); - + mat->AddProperty(&oldMat.mEmissive, 1, AI_MATKEY_COLOR_EMISSIVE); + mat->AddProperty(&oldMat.mDiffuse, 1, AI_MATKEY_COLOR_DIFFUSE); + mat->AddProperty(&oldMat.mSpecular, 1, AI_MATKEY_COLOR_SPECULAR); + mat->AddProperty(&oldMat.mSpecularExponent, 1, AI_MATKEY_SHININESS); // texture, if there is one - if (1 == oldMat.mTextures.size() ) { - const XFile::TexEntry& otex = oldMat.mTextures.back(); + if (1 == oldMat.mTextures.size()) { + const XFile::TexEntry &otex = oldMat.mTextures.back(); if (otex.mName.length()) { // if there is only one texture assume it contains the diffuse color - aiString tex( otex.mName); - if ( otex.mIsNormalMap ) { - mat->AddProperty( &tex, AI_MATKEY_TEXTURE_NORMALS( 0 ) ); + aiString tex(otex.mName); + if (otex.mIsNormalMap) { + mat->AddProperty(&tex, AI_MATKEY_TEXTURE_NORMALS(0)); } else { - mat->AddProperty( &tex, AI_MATKEY_TEXTURE_DIFFUSE( 0 ) ); + mat->AddProperty(&tex, AI_MATKEY_TEXTURE_DIFFUSE(0)); } } } else { // Otherwise ... try to search for typical strings in the // texture's file name like 'bump' or 'diffuse' - unsigned int iHM = 0,iNM = 0,iDM = 0,iSM = 0,iAM = 0,iEM = 0; - for( unsigned int b = 0; b < oldMat.mTextures.size(); ++b ) { - const XFile::TexEntry& otex = oldMat.mTextures[b]; + unsigned int iHM = 0, iNM = 0, iDM = 0, iSM = 0, iAM = 0, iEM = 0; + for (unsigned int b = 0; b < oldMat.mTextures.size(); ++b) { + const XFile::TexEntry &otex = oldMat.mTextures[b]; std::string sz = otex.mName; - if ( !sz.length() ) { + if (!sz.length()) { continue; } // find the file name std::string::size_type s = sz.find_last_of("\\/"); - if ( std::string::npos == s ) { + if (std::string::npos == s) { s = 0; } // cut off the file extension std::string::size_type sExt = sz.find_last_of('.'); - if (std::string::npos != sExt){ + if (std::string::npos != sExt) { sz[sExt] = '\0'; } // convert to lower case for easier comparison - for ( unsigned int c = 0; c < sz.length(); ++c ) { - sz[ c ] = (char) tolower( (unsigned char) sz[ c ] ); + for (unsigned int c = 0; c < sz.length(); ++c) { + sz[c] = (char)tolower((unsigned char)sz[c]); } // Place texture filename property under the corresponding name - aiString tex( oldMat.mTextures[b].mName); + aiString tex(oldMat.mTextures[b].mName); // bump map if (std::string::npos != sz.find("bump", s) || std::string::npos != sz.find("height", s)) { - mat->AddProperty( &tex, AI_MATKEY_TEXTURE_HEIGHT(iHM++)); - } else if (otex.mIsNormalMap || std::string::npos != sz.find( "normal", s) || std::string::npos != sz.find("nm", s)) { - mat->AddProperty( &tex, AI_MATKEY_TEXTURE_NORMALS(iNM++)); - } else if (std::string::npos != sz.find( "spec", s) || std::string::npos != sz.find( "glanz", s)) { - mat->AddProperty( &tex, AI_MATKEY_TEXTURE_SPECULAR(iSM++)); - } else if (std::string::npos != sz.find( "ambi", s) || std::string::npos != sz.find( "env", s)) { - mat->AddProperty( &tex, AI_MATKEY_TEXTURE_AMBIENT(iAM++)); - } else if (std::string::npos != sz.find( "emissive", s) || std::string::npos != sz.find( "self", s)) { - mat->AddProperty( &tex, AI_MATKEY_TEXTURE_EMISSIVE(iEM++)); + mat->AddProperty(&tex, AI_MATKEY_TEXTURE_HEIGHT(iHM++)); + } else if (otex.mIsNormalMap || std::string::npos != sz.find("normal", s) || std::string::npos != sz.find("nm", s)) { + mat->AddProperty(&tex, AI_MATKEY_TEXTURE_NORMALS(iNM++)); + } else if (std::string::npos != sz.find("spec", s) || std::string::npos != sz.find("glanz", s)) { + mat->AddProperty(&tex, AI_MATKEY_TEXTURE_SPECULAR(iSM++)); + } else if (std::string::npos != sz.find("ambi", s) || std::string::npos != sz.find("env", s)) { + mat->AddProperty(&tex, AI_MATKEY_TEXTURE_AMBIENT(iAM++)); + } else if (std::string::npos != sz.find("emissive", s) || std::string::npos != sz.find("self", s)) { + mat->AddProperty(&tex, AI_MATKEY_TEXTURE_EMISSIVE(iEM++)); } else { // Assume it is a diffuse texture - mat->AddProperty( &tex, AI_MATKEY_TEXTURE_DIFFUSE(iDM++)); + mat->AddProperty(&tex, AI_MATKEY_TEXTURE_DIFFUSE(iDM++)); } } } @@ -679,4 +675,6 @@ void XFileImporter::ConvertMaterials( aiScene* pScene, std::vector #include -//#include -//#include -using namespace Assimp; +namespace Assimp { -namespace Assimp { // this has to be in here because LogFunctions is in ::Assimp +static constexpr uint32_t ErrorId = ~0u; template <> const char *LogFunctions::Prefix() { return "XGL: "; } -} // namespace Assimp - -static const aiImporterDesc desc = { - "XGL Importer", - "", - "", - "", - aiImporterFlags_SupportTextFlavour | aiImporterFlags_SupportCompressedFlavour, - 0, - 0, - 0, - 0, - "xgl zgl" -}; +static constexpr aiImporterDesc desc = { + "XGL Importer", "", "", "", + aiImporterFlags_SupportTextFlavour | aiImporterFlags_SupportCompressedFlavour, + 0, 0, 0, 0, "xgl zgl"}; // ------------------------------------------------------------------------------------------------ -// Constructor to be privately used by Importer -XGLImporter::XGLImporter() : - mXmlParser(nullptr), - m_scene(nullptr) { +XGLImporter::XGLImporter() : mXmlParser(nullptr), m_scene(nullptr) { // empty } // ------------------------------------------------------------------------------------------------ -// Destructor, private as well XGLImporter::~XGLImporter() { - delete mXmlParser; + clear(); } // ------------------------------------------------------------------------------------------------ -// Returns whether the class can handle the format of the given file. bool XGLImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /*checkSig*/) const { static const char *tokens[] = { "", "", "" }; return SearchFileHeaderForToken(pIOHandler, pFile, tokens, AI_COUNT_OF(tokens)); } // ------------------------------------------------------------------------------------------------ -// Get a list of all file extensions which are handled by this class const aiImporterDesc *XGLImporter::GetInfo() const { return &desc; } // ------------------------------------------------------------------------------------------------ -// Imports the given file into the given scene structure. void XGLImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler) { - #ifndef ASSIMP_BUILD_NO_COMPRESSED_XGL + clear(); +#ifndef ASSIMP_BUILD_NO_COMPRESSED_XGL std::vector uncompressed; #endif @@ -159,7 +141,7 @@ void XGLImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy std::vector &meshes = scope.meshes_linear; std::vector &materials = scope.materials_linear; - if (!meshes.size() || !materials.size()) { + if (meshes.empty() || materials.empty()) { ThrowException("failed to extract data from XGL file, no meshes loaded"); } @@ -184,6 +166,13 @@ void XGLImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy scope.dismiss(); } +// ------------------------------------------------------------------------------------------------ +void XGLImporter::clear() { + delete mXmlParser; + mXmlParser = nullptr; +} + + // ------------------------------------------------------------------------------------------------ void XGLImporter::ReadWorld(XmlNode &node, TempScope &scope) { for (XmlNode ¤tNode : node.children()) { @@ -199,9 +188,10 @@ void XGLImporter::ReadWorld(XmlNode &node, TempScope &scope) { } aiNode *const nd = ReadObject(node, scope); - if (!nd) { + if (nd == nullptr) { ThrowException("failure reading "); } + if (nd->mName.length == 0) { nd->mName.Set("WORLD"); } @@ -254,15 +244,17 @@ aiNode *XGLImporter::ReadObject(XmlNode &node, TempScope &scope) { const std::string &s = ai_stdStrToLower(child.name()); if (s == "mesh") { const size_t prev = scope.meshes_linear.size(); - bool empty; - if (ReadMesh(child, scope, empty)) { + if (ReadMesh(child, scope)) { const size_t newc = scope.meshes_linear.size(); for (size_t i = 0; i < newc - prev; ++i) { meshes.push_back(static_cast(i + prev)); } - } + } } else if (s == "mat") { - ReadMaterial(child, scope); + const uint32_t matId = ReadMaterial(child, scope); + if (matId == ErrorId) { + ThrowException("Invalid material id detected."); + } } else if (s == "object") { children.push_back(ReadObject(child, scope)); } else if (s == "objectref") { @@ -438,18 +430,25 @@ aiMesh *XGLImporter::ToOutputMesh(const TempMaterialMesh &m) { return mesh.release(); } -// ------------------------------------------------------------------------------------------------ -bool XGLImporter::ReadMesh(XmlNode &node, TempScope &scope, bool &empty) { - TempMesh t; +// ------------------------------------------------------------------------------------------------ +inline static unsigned int generateMeshId(unsigned int meshId, bool nor, bool uv) { + unsigned int currentMeshId = meshId | ((nor ? 1 : 0) << 31) | ((uv ? 1 : 0) << 30); + return currentMeshId; +} + +// ------------------------------------------------------------------------------------------------ +bool XGLImporter::ReadMesh(XmlNode &node, TempScope &scope) { + TempMesh t; + uint32_t matId = 99999; + bool mesh_created = false; std::map bymat; const unsigned int mesh_id = ReadIDAttr(node); - bool empty_mesh = true; for (XmlNode &child : node.children()) { const std::string &s = ai_stdStrToLower(child.name()); if (s == "mat") { - ReadMaterial(child, scope); + matId = ReadMaterial(child, scope); } else if (s == "p") { pugi::xml_attribute attr = child.attribute("ID"); if (attr.empty()) { @@ -477,66 +476,41 @@ bool XGLImporter::ReadMesh(XmlNode &node, TempScope &scope, bool &empty) { } else if (s == "f" || s == "l" || s == "p") { const unsigned int vcount = s == "f" ? 3 : (s == "l" ? 2 : 1); - unsigned int mid = ~0u; - TempFace tf[3]; + unsigned int meshId = ErrorId; + TempFace tempFace[3] = {}; bool has[3] = { false }; - for (XmlNode &sub_child : child.children()) { - const std::string &scn = ai_stdStrToLower(sub_child.name()); - if (scn == "fv1" || scn == "lv1" || scn == "pv1") { - ReadFaceVertex(sub_child, t, tf[0]); - has[0] = true; - } else if (scn == "fv2" || scn == "lv2") { - ReadFaceVertex(sub_child, t, tf[1]); - has[1] = true; - } else if (scn == "fv3") { - ReadFaceVertex(sub_child, t, tf[2]); - has[2] = true; - } else if (scn == "mat") { - if (mid != ~0u) { - LogWarn("only one material tag allowed per "); - } - mid = ResolveMaterialRef(sub_child, scope); - } else if (scn == "matref") { - if (mid != ~0u) { - LogWarn("only one material tag allowed per "); - } - mid = ResolveMaterialRef(sub_child, scope); - } - } - if (has[0] || has[1] || has[2]) { - empty_mesh = false; - } - - if (mid == ~0u) { + meshId = ReadVertices(child, t, tempFace, has, meshId, scope); + if (meshId == ErrorId) { ThrowException("missing material index"); } - bool nor = false; - bool uv = false; + bool nor = false, uv = false; for (unsigned int i = 0; i < vcount; ++i) { if (!has[i]) { ThrowException("missing face vertex data"); } - nor = nor || tf[i].has_normal; - uv = uv || tf[i].has_uv; + nor = nor || tempFace[i].has_normal; + uv = uv || tempFace[i].has_uv; } - if (mid >= (1 << 30)) { + if (meshId >= (1 << 30)) { LogWarn("material indices exhausted, this may cause errors in the output"); } - unsigned int meshId = mid | ((nor ? 1 : 0) << 31) | ((uv ? 1 : 0) << 30); + const unsigned int currentMeshId = generateMeshId(meshId, nor, uv); - TempMaterialMesh &mesh = bymat[meshId]; - mesh.matid = mid; + // Generate the temp mesh + TempMaterialMesh &mesh = bymat[currentMeshId]; + mesh.matid = meshId; + mesh_created = true; for (unsigned int i = 0; i < vcount; ++i) { - mesh.positions.push_back(tf[i].pos); + mesh.positions.push_back(tempFace[i].pos); if (nor) { - mesh.normals.push_back(tf[i].normal); + mesh.normals.push_back(tempFace[i].normal); } if (uv) { - mesh.uvs.push_back(tf[i].uv); + mesh.uvs.push_back(tempFace[i].uv); } mesh.pflags |= 1 << (vcount - 1); @@ -546,25 +520,59 @@ bool XGLImporter::ReadMesh(XmlNode &node, TempScope &scope, bool &empty) { } } - // finally extract output meshes and add them to the scope - using pairt = std::pair; - for (const pairt &p : bymat) { - aiMesh *const m = ToOutputMesh(p.second); - scope.meshes_linear.push_back(m); - - // if this is a definition, keep it on the stack - if (mesh_id != ~0u) { - scope.meshes.insert(std::pair(mesh_id, m)); - } - } - if (empty_mesh) { - LogWarn("Mesh is empty, skipping."); - empty = empty_mesh; - return false; + if (!mesh_created) { + TempMaterialMesh &mesh = bymat[mesh_id]; + mesh.matid = matId; } + // finally extract output meshes and add them to the scope + AppendOutputMeshes(bymat, scope, mesh_id); + // no id == not a reference, insert this mesh right *here* - return mesh_id == ~0u; + return mesh_id == ErrorId; +} + +// ---------------------------------------------------------------------------------------------- +void XGLImporter::AppendOutputMeshes(std::map bymat, TempScope &scope, + const unsigned int mesh_id) { + using pairt = std::pair; + for (const pairt &p : bymat) { + aiMesh *const m = ToOutputMesh(p.second); + scope.meshes_linear.push_back(m); + + // if this is a definition, keep it on the stack + if (mesh_id != ErrorId) { + scope.meshes.insert(std::pair(mesh_id, m)); + } + } +} + +// ---------------------------------------------------------------------------------------------- +unsigned int XGLImporter::ReadVertices(XmlNode &child, TempMesh t, TempFace *tf, bool *has, unsigned int mid, TempScope &scope) { + for (XmlNode &sub_child : child.children()) { + const std::string &scn = ai_stdStrToLower(sub_child.name()); + if (scn == "fv1" || scn == "lv1" || scn == "pv1") { + ReadFaceVertex(sub_child, t, tf[0]); + has[0] = true; + } else if (scn == "fv2" || scn == "lv2") { + ReadFaceVertex(sub_child, t, tf[1]); + has[1] = true; + } else if (scn == "fv3") { + ReadFaceVertex(sub_child, t, tf[2]); + has[2] = true; + } else if (scn == "mat") { + if (mid != ErrorId) { + LogWarn("only one material tag allowed per "); + } + mid = ResolveMaterialRef(sub_child, scope); + } else if (scn == "matref") { + if (mid != ErrorId) { + LogWarn("only one material tag allowed per "); + } + mid = ResolveMaterialRef(sub_child, scope); + } + } + return mid; } // ---------------------------------------------------------------------------------------------- @@ -598,10 +606,10 @@ unsigned int XGLImporter::ResolveMaterialRef(XmlNode &node, TempScope &scope) { } // ------------------------------------------------------------------------------------------------ -void XGLImporter::ReadMaterial(XmlNode &node, TempScope &scope) { +unsigned int XGLImporter::ReadMaterial(XmlNode &node, TempScope &scope) { const unsigned int mat_id = ReadIDAttr(node); - auto *mat(new aiMaterial); + auto *mat = new aiMaterial; for (XmlNode &child : node.children()) { const std::string &s = ai_stdStrToLower(child.name()); if (s == "amb") { @@ -627,6 +635,8 @@ void XGLImporter::ReadMaterial(XmlNode &node, TempScope &scope) { scope.materials[mat_id] = mat; scope.materials_linear.push_back(mat); + + return mat_id; } // ---------------------------------------------------------------------------------------------- @@ -683,7 +693,7 @@ unsigned int XGLImporter::ReadIDAttr(XmlNode &node) { } } - return ~0u; + return ErrorId; } // ------------------------------------------------------------------------------------------------ @@ -712,14 +722,14 @@ unsigned int XGLImporter::ReadIndexFromText(XmlNode &node) { const char *s = v.c_str(); if (!SkipSpaces(&s)) { LogError("unexpected EOL, failed to parse index element"); - return ~0u; + return ErrorId; } - const char *se; + const char *se = nullptr; const unsigned int t = strtoul10(s, &se); if (se == s) { LogError("failed to read index"); - return ~0u; + return ErrorId; } return t; @@ -786,4 +796,6 @@ aiColor3D XGLImporter::ReadCol3(XmlNode &node) { return aiColor3D(v.x, v.y, v.z); } +} // namespace Assimp + #endif // ASSIMP_BUILD_NO_XGL_IMPORTER diff --git a/code/AssetLib/XGL/XGLLoader.h b/code/AssetLib/XGL/XGLLoader.h index ae7ccddc2..f620561d1 100644 --- a/code/AssetLib/XGL/XGLLoader.h +++ b/code/AssetLib/XGL/XGLLoader.h @@ -69,16 +69,20 @@ namespace Assimp { */ class XGLImporter : public BaseImporter, public LogFunctions { public: + /// @brief The class constructor. XGLImporter(); + + /// @brief The class destructor. ~XGLImporter() override; - // ------------------------------------------------------------------- - /** Returns whether the class can handle the format of the given file. - * See BaseImporter::CanRead() for details. */ + /// @brief Returns whether the class can handle the format of the given file. + /// @see BaseImporter::CanRead() for details. */ bool CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const override; protected: + void clear(); + // ------------------------------------------------------------------- /** Return importer meta information. * See #BaseImporter::GetInfo for the details */ @@ -92,10 +96,7 @@ protected: private: struct TempScope { - TempScope() : - light() { - // empty - } + TempScope() : light() {} ~TempScope() { for (aiMesh *m : meshes_linear) { @@ -145,9 +146,7 @@ private: }; struct TempMaterialMesh { - TempMaterialMesh() : - pflags(), - matid() { + TempMaterialMesh() : pflags(), matid() { // empty } @@ -160,9 +159,7 @@ private: }; struct TempFace { - TempFace() : - has_uv(), - has_normal() { + TempFace() : has_uv(), has_normal() { // empty } @@ -175,26 +172,25 @@ private: private: void Cleanup(); - std::string GetElementName(); bool ReadElement(); bool ReadElementUpToClosing(const char *closetag); bool SkipToText(); unsigned int ReadIDAttr(XmlNode &node); - void ReadWorld(XmlNode &node, TempScope &scope); void ReadLighting(XmlNode &node, TempScope &scope); aiLight *ReadDirectionalLight(XmlNode &node); aiNode *ReadObject(XmlNode &node, TempScope &scope); - bool ReadMesh(XmlNode &node, TempScope &scope, bool &empty); - void ReadMaterial(XmlNode &node, TempScope &scope); + bool ReadMesh(XmlNode &node, TempScope &scope); + void AppendOutputMeshes(std::map bymat, TempScope &scope, const unsigned int mesh_id); + unsigned int ReadVertices(XmlNode &child, TempMesh t, TempFace *tf, bool *has, unsigned int mid, TempScope &scope); + unsigned int ReadMaterial(XmlNode &node, TempScope &scope); aiVector2D ReadVec2(XmlNode &node); aiVector3D ReadVec3(XmlNode &node); aiColor3D ReadCol3(XmlNode &node); aiMatrix4x4 ReadTrafo(XmlNode &node); unsigned int ReadIndexFromText(XmlNode &node); float ReadFloat(XmlNode &node); - aiMesh *ToOutputMesh(const TempMaterialMesh &m); void ReadFaceVertex(XmlNode &node, const TempMesh &t, TempFace &out); unsigned int ResolveMaterialRef(XmlNode &node, TempScope &scope); diff --git a/code/AssetLib/glTF/glTFImporter.cpp b/code/AssetLib/glTF/glTFImporter.cpp index 110a2a52f..cd8b7762d 100644 --- a/code/AssetLib/glTF/glTFImporter.cpp +++ b/code/AssetLib/glTF/glTFImporter.cpp @@ -62,11 +62,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. using namespace Assimp; using namespace glTF; -// -// glTFImporter -// - -static const aiImporterDesc desc = { +static constexpr aiImporterDesc desc = { "glTF Importer", "", "", diff --git a/code/AssetLib/glTF2/glTF2Exporter.cpp b/code/AssetLib/glTF2/glTF2Exporter.cpp index d6f778fbe..18a6ae2f4 100644 --- a/code/AssetLib/glTF2/glTF2Exporter.cpp +++ b/code/AssetLib/glTF2/glTF2Exporter.cpp @@ -172,22 +172,6 @@ static void IdentityMatrix4(mat4 &o) { o[15] = 1; } -static bool IsBoneWeightFitted(vec4 &weight) { - return weight[0] + weight[1] + weight[2] + weight[3] >= 1.f; -} - -static int FitBoneWeight(vec4 &weight, float value) { - int i = 0; - for (; i < 4; ++i) { - if (weight[i] < value) { - weight[i] = value; - return i; - } - } - - return -1; -} - template void SetAccessorRange(Ref acc, void *data, size_t count, unsigned int numCompsIn, unsigned int numCompsOut) { @@ -575,7 +559,11 @@ void glTF2Exporter::GetMatTex(const aiMaterial &mat, Ref &texture, unsi aiString tex; // Read texcoord (UV map index) - mat.Get(AI_MATKEY_UVWSRC(tt, slot), texCoord); + // Note: must be an int to be successful. + int tmp = 0; + const auto ok = mat.Get(AI_MATKEY_UVWSRC(tt, slot), tmp); + if (ok == aiReturn_SUCCESS) texCoord = tmp; + if (mat.Get(AI_MATKEY_TEXTURE(tt, slot), tex) == AI_SUCCESS) { std::string path = tex.C_Str(); @@ -1009,23 +997,29 @@ Ref FindSkeletonRootJoint(Ref &skinRef) { return parentNodeRef; } +struct boneIndexWeightPair { + unsigned int indexJoint; + float weight; + bool operator()(boneIndexWeightPair &a, boneIndexWeightPair &b) { + return a.weight > b.weight; + } +}; + void ExportSkin(Asset &mAsset, const aiMesh *aimesh, Ref &meshRef, Ref &bufferRef, Ref &skinRef, - std::vector &inverseBindMatricesData) { + std::vector &inverseBindMatricesData, bool unlimitedBonesPerVertex) { if (aimesh->mNumBones < 1) { return; } // Store the vertex joint and weight data. const size_t NumVerts(aimesh->mNumVertices); - vec4 *vertexJointData = new vec4[NumVerts]; - vec4 *vertexWeightData = new vec4[NumVerts]; int *jointsPerVertex = new int[NumVerts]; + std::vector> allVerticesPairs; + int maxJointsPerVertex = 0; for (size_t i = 0; i < NumVerts; ++i) { jointsPerVertex[i] = 0; - for (size_t j = 0; j < 4; ++j) { - vertexJointData[i][j] = 0; - vertexWeightData[i][j] = 0; - } + std::vector vertexPair; + allVerticesPairs.push_back(vertexPair); } for (unsigned int idx_bone = 0; idx_bone < aimesh->mNumBones; ++idx_bone) { @@ -1055,61 +1049,88 @@ void ExportSkin(Asset &mAsset, const aiMesh *aimesh, Ref &meshRef, Ref(inverseBindMatricesData.size() - 1); } - // aib->mWeights =====> vertexWeightData - for (unsigned int idx_weights = 0; idx_weights < aib->mNumWeights; ++idx_weights) { + // aib->mWeights =====> temp pairs data + for (unsigned int idx_weights = 0; idx_weights < aib->mNumWeights; + ++idx_weights) { unsigned int vertexId = aib->mWeights[idx_weights].mVertexId; float vertWeight = aib->mWeights[idx_weights].mWeight; - - // A vertex can only have at most four joint weights, which ideally sum up to 1 - if (IsBoneWeightFitted(vertexWeightData[vertexId])) { - continue; - } - if (jointsPerVertex[vertexId] > 3) { - int boneIndexFitted = FitBoneWeight(vertexWeightData[vertexId], vertWeight); - if (boneIndexFitted != -1) { - vertexJointData[vertexId][boneIndexFitted] = static_cast(jointNamesIndex); - } - } else { - vertexJointData[vertexId][jointsPerVertex[vertexId]] = static_cast(jointNamesIndex); - vertexWeightData[vertexId][jointsPerVertex[vertexId]] = vertWeight; - - jointsPerVertex[vertexId] += 1; - } + allVerticesPairs[vertexId].push_back({jointNamesIndex, vertWeight}); + jointsPerVertex[vertexId] += 1; + maxJointsPerVertex = + std::max(maxJointsPerVertex, jointsPerVertex[vertexId]); } - } // End: for-loop mNumMeshes - Mesh::Primitive &p = meshRef->primitives.back(); - Ref vertexJointAccessor = ExportData(mAsset, skinRef->id, bufferRef, aimesh->mNumVertices, - vertexJointData, AttribType::VEC4, AttribType::VEC4, ComponentType_FLOAT); - if (vertexJointAccessor) { - size_t offset = vertexJointAccessor->bufferView->byteOffset; - size_t bytesLen = vertexJointAccessor->bufferView->byteLength; - unsigned int s_bytesPerComp = ComponentTypeSize(ComponentType_UNSIGNED_SHORT); - unsigned int bytesPerComp = ComponentTypeSize(vertexJointAccessor->componentType); - size_t s_bytesLen = bytesLen * s_bytesPerComp / bytesPerComp; - Ref buf = vertexJointAccessor->bufferView->buffer; - uint8_t *arrys = new uint8_t[bytesLen]; - unsigned int i = 0; - for (unsigned int j = 0; j < bytesLen; j += bytesPerComp) { - size_t len_p = offset + j; - float f_value = *(float *)&buf->GetPointer()[len_p]; - unsigned short c = static_cast(f_value); - memcpy(&arrys[i * s_bytesPerComp], &c, s_bytesPerComp); - ++i; - } - buf->ReplaceData_joint(offset, bytesLen, arrys, bytesLen); - vertexJointAccessor->componentType = ComponentType_UNSIGNED_SHORT; - vertexJointAccessor->bufferView->byteLength = s_bytesLen; - - p.attributes.joint.push_back(vertexJointAccessor); - delete[] arrys; + if (!unlimitedBonesPerVertex){ + // skinning limited only for 4 bones per vertex, default + maxJointsPerVertex = 4; } - Ref vertexWeightAccessor = ExportData(mAsset, skinRef->id, bufferRef, aimesh->mNumVertices, - vertexWeightData, AttribType::VEC4, AttribType::VEC4, ComponentType_FLOAT); - if (vertexWeightAccessor) { - p.attributes.weight.push_back(vertexWeightAccessor); + // temp pairs data =====> vertexWeightData + size_t numGroups = (maxJointsPerVertex - 1) / 4 + 1; + vec4 *vertexJointData = new vec4[NumVerts * numGroups]; + vec4 *vertexWeightData = new vec4[NumVerts * numGroups]; + for (size_t indexVertex = 0; indexVertex < NumVerts; ++indexVertex) { + // order pairs by weight for each vertex + std::sort(allVerticesPairs[indexVertex].begin(), + allVerticesPairs[indexVertex].end(), + boneIndexWeightPair()); + for (size_t indexGroup = 0; indexGroup < numGroups; ++indexGroup) { + for (size_t indexJoint = 0; indexJoint < 4; ++indexJoint) { + size_t indexBone = indexGroup * 4 + indexJoint; + size_t indexData = indexVertex + NumVerts * indexGroup; + if (indexBone >= allVerticesPairs[indexVertex].size()) { + vertexJointData[indexData][indexJoint] = 0.f; + vertexWeightData[indexData][indexJoint] = 0.f; + } else { + vertexJointData[indexData][indexJoint] = + static_cast( + allVerticesPairs[indexVertex][indexBone].indexJoint); + vertexWeightData[indexData][indexJoint] = + allVerticesPairs[indexVertex][indexBone].weight; + } + } + } + } + + for (size_t idx_group = 0; idx_group < numGroups; ++idx_group) { + Mesh::Primitive &p = meshRef->primitives.back(); + Ref vertexJointAccessor = ExportData( + mAsset, skinRef->id, bufferRef, aimesh->mNumVertices, + vertexJointData + idx_group * NumVerts, + AttribType::VEC4, AttribType::VEC4, ComponentType_FLOAT); + if (vertexJointAccessor) { + size_t offset = vertexJointAccessor->bufferView->byteOffset; + size_t bytesLen = vertexJointAccessor->bufferView->byteLength; + unsigned int s_bytesPerComp = + ComponentTypeSize(ComponentType_UNSIGNED_SHORT); + unsigned int bytesPerComp = + ComponentTypeSize(vertexJointAccessor->componentType); + size_t s_bytesLen = bytesLen * s_bytesPerComp / bytesPerComp; + Ref buf = vertexJointAccessor->bufferView->buffer; + uint8_t *arrys = new uint8_t[bytesLen]; + unsigned int i = 0; + for (unsigned int j = 0; j < bytesLen; j += bytesPerComp) { + size_t len_p = offset + j; + float f_value = *(float *)&buf->GetPointer()[len_p]; + unsigned short c = static_cast(f_value); + memcpy(&arrys[i * s_bytesPerComp], &c, s_bytesPerComp); + ++i; + } + buf->ReplaceData_joint(offset, bytesLen, arrys, bytesLen); + vertexJointAccessor->componentType = ComponentType_UNSIGNED_SHORT; + vertexJointAccessor->bufferView->byteLength = s_bytesLen; + + p.attributes.joint.push_back(vertexJointAccessor); + delete[] arrys; + } + Ref vertexWeightAccessor = ExportData( + mAsset, skinRef->id, bufferRef, aimesh->mNumVertices, + vertexWeightData + idx_group * NumVerts, + AttribType::VEC4, AttribType::VEC4, ComponentType_FLOAT); + if (vertexWeightAccessor) { + p.attributes.weight.push_back(vertexWeightAccessor); + } } delete[] jointsPerVertex; delete[] vertexWeightData; @@ -1247,9 +1268,19 @@ void glTF2Exporter::ExportMeshes() { break; } +// /*************** Skins ****************/ +// if (aim->HasBones()) { +// ExportSkin(*mAsset, aim, m, b, skinRef, inverseBindMatricesData); +// } /*************** Skins ****************/ if (aim->HasBones()) { - ExportSkin(*mAsset, aim, m, b, skinRef, inverseBindMatricesData); + bool unlimitedBonesPerVertex = + this->mProperties->HasPropertyBool( + AI_CONFIG_EXPORT_GLTF_UNLIMITED_SKINNING_BONES_PER_VERTEX) && + this->mProperties->GetPropertyBool( + AI_CONFIG_EXPORT_GLTF_UNLIMITED_SKINNING_BONES_PER_VERTEX); + ExportSkin(*mAsset, aim, m, b, skinRef, inverseBindMatricesData, + unlimitedBonesPerVertex); } /*************** Targets for blendshapes ****************/ diff --git a/code/AssetLib/glTF2/glTF2Importer.cpp b/code/AssetLib/glTF2/glTF2Importer.cpp index 0fed11cef..4bdbe39f1 100644 --- a/code/AssetLib/glTF2/glTF2Importer.cpp +++ b/code/AssetLib/glTF2/glTF2Importer.cpp @@ -82,7 +82,7 @@ struct Tangent { // glTF2Importer // -static const aiImporterDesc desc = { +static constexpr aiImporterDesc desc = { "glTF2 Importer", "", "", diff --git a/code/CMakeLists.txt b/code/CMakeLists.txt index 0fe2291f8..9b0b964c0 100644 --- a/code/CMakeLists.txt +++ b/code/CMakeLists.txt @@ -923,7 +923,7 @@ IF(ASSIMP_HUNTER_ENABLED) hunter_add_package(utf8) find_package(utf8cpp CONFIG REQUIRED) ELSE() - # utf8 is header-only, so Assimp doesn't need to do anything. + INCLUDE_DIRECTORIES("../contrib/utf8cpp/source") ENDIF() # polyclipping @@ -1380,7 +1380,12 @@ ENDIF() IF(NOT ASSIMP_HUNTER_ENABLED) if (UNZIP_FOUND) INCLUDE_DIRECTORIES(${UNZIP_INCLUDE_DIRS}) - TARGET_LINK_LIBRARIES(assimp ${UNZIP_LIBRARIES}) + # TODO if cmake required version has been updated to >3.12.0, collapse this to the second case only + if(${CMAKE_VERSION} VERSION_LESS "3.12.0") + TARGET_LINK_LIBRARIES(assimp ${UNZIP_LIBRARIES}) + else() + TARGET_LINK_LIBRARIES(assimp ${UNZIP_LINK_LIBRARIES}) + endif() else () INCLUDE_DIRECTORIES("../") endif () diff --git a/code/Common/Compression.cpp b/code/Common/Compression.cpp index 3bf306dee..a6a7be7e4 100644 --- a/code/Common/Compression.cpp +++ b/code/Common/Compression.cpp @@ -66,6 +66,10 @@ Compression::Compression() : Compression::~Compression() { ai_assert(mImpl != nullptr); + if (mImpl->mOpen) { + close(); + } + delete mImpl; } @@ -124,7 +128,7 @@ static int getFlushMode(Compression::FlushMode flush) { return z_flush; } -constexpr size_t MYBLOCK = 32786; +static constexpr size_t MYBLOCK = 32786; size_t Compression::decompress(const void *data, size_t in, std::vector &uncompressed) { ai_assert(mImpl != nullptr); diff --git a/code/PostProcessing/ImproveCacheLocality.cpp b/code/PostProcessing/ImproveCacheLocality.cpp index 9336d6b17..d7bb95698 100644 --- a/code/PostProcessing/ImproveCacheLocality.cpp +++ b/code/PostProcessing/ImproveCacheLocality.cpp @@ -3,9 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team - - +Copyright (c) 2006-2023, assimp team All rights reserved. @@ -59,31 +57,31 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include -using namespace Assimp; +namespace Assimp { // ------------------------------------------------------------------------------------------------ // Constructor to be privately used by Importer -ImproveCacheLocalityProcess::ImproveCacheLocalityProcess() -: mConfigCacheDepth(PP_ICL_PTCACHE_SIZE) { +ImproveCacheLocalityProcess::ImproveCacheLocalityProcess() : + mConfigCacheDepth(PP_ICL_PTCACHE_SIZE) { // empty } // ------------------------------------------------------------------------------------------------ // Returns whether the processing step is present in the given flag field. -bool ImproveCacheLocalityProcess::IsActive( unsigned int pFlags) const { +bool ImproveCacheLocalityProcess::IsActive(unsigned int pFlags) const { return (pFlags & aiProcess_ImproveCacheLocality) != 0; } // ------------------------------------------------------------------------------------------------ // Setup configuration -void ImproveCacheLocalityProcess::SetupProperties(const Importer* pImp) { +void ImproveCacheLocalityProcess::SetupProperties(const Importer *pImp) { // AI_CONFIG_PP_ICL_PTCACHE_SIZE controls the target cache size for the optimizer - mConfigCacheDepth = pImp->GetPropertyInteger(AI_CONFIG_PP_ICL_PTCACHE_SIZE,PP_ICL_PTCACHE_SIZE); + mConfigCacheDepth = pImp->GetPropertyInteger(AI_CONFIG_PP_ICL_PTCACHE_SIZE, PP_ICL_PTCACHE_SIZE); } // ------------------------------------------------------------------------------------------------ // Executes the post processing step on the given imported data. -void ImproveCacheLocalityProcess::Execute( aiScene* pScene) { +void ImproveCacheLocalityProcess::Execute(aiScene *pScene) { if (!pScene->mNumMeshes) { ASSIMP_LOG_DEBUG("ImproveCacheLocalityProcess skipped; there are no meshes"); return; @@ -93,11 +91,11 @@ void ImproveCacheLocalityProcess::Execute( aiScene* pScene) { float out = 0.f; unsigned int numf = 0, numm = 0; - for( unsigned int a = 0; a < pScene->mNumMeshes; ++a ){ - const float res = ProcessMesh( pScene->mMeshes[a],a); + for (unsigned int a = 0; a < pScene->mNumMeshes; ++a) { + const float res = ProcessMesh(pScene->mMeshes[a], a); if (res) { numf += pScene->mMeshes[a]->mNumFaces; - out += res; + out += res; ++numm; } } @@ -109,9 +107,54 @@ void ImproveCacheLocalityProcess::Execute( aiScene* pScene) { } } +// ------------------------------------------------------------------------------------------------ +static ai_real calculateInputACMR(aiMesh *pMesh, const aiFace *const pcEnd, + unsigned int configCacheDepth, unsigned int meshNum) { + ai_real fACMR = 0.0f; + unsigned int *piFIFOStack = new unsigned int[configCacheDepth]; + memset(piFIFOStack, 0xff, configCacheDepth * sizeof(unsigned int)); + unsigned int *piCur = piFIFOStack; + const unsigned int *const piCurEnd = piFIFOStack + configCacheDepth; + + // count the number of cache misses + unsigned int iCacheMisses = 0; + for (const aiFace *pcFace = pMesh->mFaces; pcFace != pcEnd; ++pcFace) { + for (unsigned int qq = 0; qq < 3; ++qq) { + bool bInCache = false; + for (unsigned int *pp = piFIFOStack; pp < piCurEnd; ++pp) { + if (*pp == pcFace->mIndices[qq]) { + // the vertex is in cache + bInCache = true; + break; + } + } + if (!bInCache) { + ++iCacheMisses; + if (piCurEnd == piCur) { + piCur = piFIFOStack; + } + *piCur++ = pcFace->mIndices[qq]; + } + } + } + delete[] piFIFOStack; + fACMR = (ai_real)iCacheMisses / pMesh->mNumFaces; + if (3.0 == fACMR) { + char szBuff[128]; // should be sufficiently large in every case + + // the JoinIdenticalVertices process has not been executed on this + // mesh, otherwise this value would normally be at least minimally + // smaller than 3.0 ... + ai_snprintf(szBuff, 128, "Mesh %u: Not suitable for vcache optimization", meshNum); + ASSIMP_LOG_WARN(szBuff); + return static_cast(0.f); + } + return fACMR; +} + // ------------------------------------------------------------------------------------------------ // Improves the cache coherency of a specific mesh -ai_real ImproveCacheLocalityProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshNum) { +ai_real ImproveCacheLocalityProcess::ProcessMesh(aiMesh *pMesh, unsigned int meshNum) { // TODO: rewrite this to use std::vector or boost::shared_array ai_assert(nullptr != pMesh); @@ -126,91 +169,57 @@ ai_real ImproveCacheLocalityProcess::ProcessMesh( aiMesh* pMesh, unsigned int me return static_cast(0.f); } - if(pMesh->mNumVertices <= mConfigCacheDepth) { + if (pMesh->mNumVertices <= mConfigCacheDepth) { return static_cast(0.f); } ai_real fACMR = 3.f; - const aiFace* const pcEnd = pMesh->mFaces+pMesh->mNumFaces; + const aiFace *const pcEnd = pMesh->mFaces + pMesh->mNumFaces; // Input ACMR is for logging purposes only - if (!DefaultLogger::isNullLogger()) { - - unsigned int* piFIFOStack = new unsigned int[mConfigCacheDepth]; - memset(piFIFOStack,0xff,mConfigCacheDepth*sizeof(unsigned int)); - unsigned int* piCur = piFIFOStack; - const unsigned int* const piCurEnd = piFIFOStack + mConfigCacheDepth; - - // count the number of cache misses - unsigned int iCacheMisses = 0; - for (const aiFace* pcFace = pMesh->mFaces;pcFace != pcEnd;++pcFace) { - for (unsigned int qq = 0; qq < 3;++qq) { - bool bInCache = false; - for (unsigned int* pp = piFIFOStack;pp < piCurEnd;++pp) { - if (*pp == pcFace->mIndices[qq]) { - // the vertex is in cache - bInCache = true; - break; - } - } - if (!bInCache) { - ++iCacheMisses; - if (piCurEnd == piCur) { - piCur = piFIFOStack; - } - *piCur++ = pcFace->mIndices[qq]; - } - } - } - delete[] piFIFOStack; - fACMR = (ai_real) iCacheMisses / pMesh->mNumFaces; - if (3.0 == fACMR) { - char szBuff[128]; // should be sufficiently large in every case - - // the JoinIdenticalVertices process has not been executed on this - // mesh, otherwise this value would normally be at least minimally - // smaller than 3.0 ... - ai_snprintf(szBuff,128,"Mesh %u: Not suitable for vcache optimization",meshNum); - ASSIMP_LOG_WARN(szBuff); - return static_cast(0.f); - } + if (!DefaultLogger::isNullLogger()) { + fACMR = calculateInputACMR(pMesh, pcEnd, mConfigCacheDepth, meshNum); } // first we need to build a vertex-triangle adjacency list - VertexTriangleAdjacency adj(pMesh->mFaces,pMesh->mNumFaces, pMesh->mNumVertices,true); + VertexTriangleAdjacency adj(pMesh->mFaces, pMesh->mNumFaces, pMesh->mNumVertices, true); // build a list to store per-vertex caching time stamps - unsigned int* const piCachingStamps = new unsigned int[pMesh->mNumVertices]; - memset(piCachingStamps,0x0,pMesh->mNumVertices*sizeof(unsigned int)); + std::vector piCachingStamps; + piCachingStamps.resize(pMesh->mNumVertices); + memset(&piCachingStamps[0], 0x0, pMesh->mNumVertices * sizeof(unsigned int)); // allocate an empty output index buffer. We store the output indices in one large array. // Since the number of triangles won't change the input faces can be reused. This is how // we save thousands of redundant mini allocations for aiFace::mIndices - const unsigned int iIdxCnt = pMesh->mNumFaces*3; - unsigned int* const piIBOutput = new unsigned int[iIdxCnt]; - unsigned int* piCSIter = piIBOutput; + const unsigned int iIdxCnt = pMesh->mNumFaces * 3; + std::vector piIBOutput; + piIBOutput.resize(iIdxCnt); + std::vector::iterator piCSIter = piIBOutput.begin(); // allocate the flag array to hold the information // whether a face has already been emitted or not - std::vector abEmitted(pMesh->mNumFaces,false); + std::vector abEmitted(pMesh->mNumFaces, false); // dead-end vertex index stack - std::stack > sDeadEndVStack; + std::stack> sDeadEndVStack; // create a copy of the piNumTriPtr buffer - unsigned int* const piNumTriPtr = adj.mLiveTriangles; + unsigned int *const piNumTriPtr = adj.mLiveTriangles; const std::vector piNumTriPtrNoModify(piNumTriPtr, piNumTriPtr + pMesh->mNumVertices); // get the largest number of referenced triangles and allocate the "candidate buffer" - unsigned int iMaxRefTris = 0; { - const unsigned int* piCur = adj.mLiveTriangles; - const unsigned int* const piCurEnd = adj.mLiveTriangles+pMesh->mNumVertices; - for (;piCur != piCurEnd;++piCur) { - iMaxRefTris = std::max(iMaxRefTris,*piCur); + unsigned int iMaxRefTris = 0; + { + const unsigned int *piCur = adj.mLiveTriangles; + const unsigned int *const piCurEnd = adj.mLiveTriangles + pMesh->mNumVertices; + for (; piCur != piCurEnd; ++piCur) { + iMaxRefTris = std::max(iMaxRefTris, *piCur); } } ai_assert(iMaxRefTris > 0); - unsigned int* piCandidates = new unsigned int[iMaxRefTris*3]; + std::vector piCandidates; + piCandidates.resize(iMaxRefTris * 3); unsigned int iCacheMisses = 0; // ................................................................................... @@ -245,23 +254,23 @@ ai_real ImproveCacheLocalityProcess::ProcessMesh( aiMesh* pMesh, unsigned int me int ivdx = 0; int ics = 1; - int iStampCnt = mConfigCacheDepth+1; - while (ivdx >= 0) { + int iStampCnt = mConfigCacheDepth + 1; + while (ivdx >= 0) { unsigned int icnt = piNumTriPtrNoModify[ivdx]; - unsigned int* piList = adj.GetAdjacentTriangles(ivdx); - unsigned int* piCurCandidate = piCandidates; + unsigned int *piList = adj.GetAdjacentTriangles(ivdx); + std::vector::iterator piCurCandidate = piCandidates.begin(); // get all triangles in the neighborhood - for (unsigned int tri = 0; tri < icnt;++tri) { + for (unsigned int tri = 0; tri < icnt; ++tri) { // if they have not yet been emitted, add them to the output IB const unsigned int fidx = *piList++; - if (!abEmitted[fidx]) { + if (!abEmitted[fidx]) { // so iterate through all vertices of the current triangle - const aiFace* pcFace = &pMesh->mFaces[ fidx ]; - unsigned nind = pcFace->mNumIndices; + const aiFace *pcFace = &pMesh->mFaces[fidx]; + const unsigned nind = pcFace->mNumIndices; for (unsigned ind = 0; ind < nind; ind++) { unsigned dp = pcFace->mIndices[ind]; @@ -281,7 +290,7 @@ ai_real ImproveCacheLocalityProcess::ProcessMesh( aiMesh* pMesh, unsigned int me *piCSIter++ = dp; // if the vertex is not yet in cache, set its cache count - if (iStampCnt-piCachingStamps[dp] > mConfigCacheDepth) { + if (iStampCnt - piCachingStamps[dp] > mConfigCacheDepth) { piCachingStamps[dp] = iStampCnt++; ++iCacheMisses; } @@ -297,16 +306,16 @@ ai_real ImproveCacheLocalityProcess::ProcessMesh( aiMesh* pMesh, unsigned int me // get next fanning vertex ivdx = -1; int max_priority = -1; - for (unsigned int* piCur = piCandidates;piCur != piCurCandidate;++piCur) { + for (std::vector::iterator piCur = piCandidates.begin(); piCur != piCurCandidate; ++piCur) { const unsigned int dp = *piCur; // must have live triangles - if (piNumTriPtr[dp] > 0) { + if (piNumTriPtr[dp] > 0) { int priority = 0; // will the vertex be in cache, even after fanning occurs? unsigned int tmp; - if ((tmp = iStampCnt-piCachingStamps[dp]) + 2*piNumTriPtr[dp] <= mConfigCacheDepth) { + if ((tmp = iStampCnt - piCachingStamps[dp]) + 2 * piNumTriPtr[dp] <= mConfigCacheDepth) { priority = tmp; } @@ -324,7 +333,7 @@ ai_real ImproveCacheLocalityProcess::ProcessMesh( aiMesh* pMesh, unsigned int me while (!sDeadEndVStack.empty()) { unsigned int iCachedIdx = sDeadEndVStack.top(); sDeadEndVStack.pop(); - if (piNumTriPtr[ iCachedIdx ] > 0) { + if (piNumTriPtr[iCachedIdx] > 0) { ivdx = iCachedIdx; break; } @@ -333,9 +342,9 @@ ai_real ImproveCacheLocalityProcess::ProcessMesh( aiMesh* pMesh, unsigned int me if (-1 == ivdx) { // well, there isn't such a vertex. Simply get the next vertex in input order and // hope it is not too bad ... - while (ics < (int)pMesh->mNumVertices) { + while (ics < (int)pMesh->mNumVertices) { ++ics; - if (piNumTriPtr[ics] > 0) { + if (piNumTriPtr[ics] > 0) { ivdx = ics; break; } @@ -345,29 +354,29 @@ ai_real ImproveCacheLocalityProcess::ProcessMesh( aiMesh* pMesh, unsigned int me } ai_real fACMR2 = 0.0f; if (!DefaultLogger::isNullLogger()) { - fACMR2 = (float)iCacheMisses / pMesh->mNumFaces; - + fACMR2 = static_cast(iCacheMisses / pMesh->mNumFaces); + const ai_real averageACMR = ((fACMR - fACMR2) / fACMR) * 100.f; // very intense verbose logging ... prepare for much text if there are many meshes - if ( DefaultLogger::get()->getLogSeverity() == Logger::VERBOSE) { - ASSIMP_LOG_VERBOSE_DEBUG("Mesh %u | ACMR in: ", meshNum, " out: ", fACMR, " | ~", fACMR2, ((fACMR - fACMR2) / fACMR) * 100.f); + if (DefaultLogger::get()->getLogSeverity() == Logger::VERBOSE) { + ASSIMP_LOG_VERBOSE_DEBUG("Mesh ", meshNum, "| ACMR in: ", fACMR, " out: ", fACMR2, " | average ACMR ", averageACMR); } - fACMR2 *= pMesh->mNumFaces; } - // sort the output index buffer back to the input array - piCSIter = piIBOutput; - for (aiFace* pcFace = pMesh->mFaces; pcFace != pcEnd;++pcFace) { - unsigned nind = pcFace->mNumIndices; - unsigned * ind = pcFace->mIndices; - if (nind > 0) ind[0] = *piCSIter++; - if (nind > 1) ind[1] = *piCSIter++; - if (nind > 2) ind[2] = *piCSIter++; - } - // delete temporary storage - delete[] piCachingStamps; - delete[] piIBOutput; - delete[] piCandidates; + // sort the output index buffer back to the input array + piCSIter = piIBOutput.begin(); + for (aiFace *pcFace = pMesh->mFaces; pcFace != pcEnd; ++pcFace) { + unsigned nind = pcFace->mNumIndices; + unsigned *ind = pcFace->mIndices; + if (nind > 0) + ind[0] = *piCSIter++; + if (nind > 1) + ind[1] = *piCSIter++; + if (nind > 2) + ind[2] = *piCSIter++; + } return fACMR2; } + +} // namespace Assimp diff --git a/code/PostProcessing/PretransformVertices.cpp b/code/PostProcessing/PretransformVertices.cpp index 87af2297d..aff6e535a 100644 --- a/code/PostProcessing/PretransformVertices.cpp +++ b/code/PostProcessing/PretransformVertices.cpp @@ -290,12 +290,6 @@ void PretransformVertices::ComputeAbsoluteTransform(aiNode *pcNode) { } } -static void normalizeVectorArray(aiVector3D *vectorArrayIn, aiVector3D *vectorArrayOut, size_t numVectors) { - for (size_t i=0; iHasNormals()) { - normalizeVectorArray(mesh->mNormals, mesh->mNormals, mesh->mNumVertices); + for (unsigned int i = 0; i < mesh->mNumVertices; ++i) { + mesh->mNormals[i] = (m * mesh->mNormals[i]).Normalize(); + } } + if (mesh->HasTangentsAndBitangents()) { for (unsigned int i = 0; i < mesh->mNumVertices; ++i) { mesh->mTangents[i] = (m * mesh->mTangents[i]).Normalize(); diff --git a/contrib/zlib/zconf.h.included b/contrib/zlib/zconf.h.included index 352f552b8..2271dc5f5 100644 --- a/contrib/zlib/zconf.h.included +++ b/contrib/zlib/zconf.h.included @@ -40,6 +40,9 @@ # define crc32 z_crc32 # define crc32_combine z_crc32_combine # define crc32_combine64 z_crc32_combine64 +# define crc32_combine_gen z_crc32_combine_gen +# define crc32_combine_gen64 z_crc32_combine_gen64 +# define crc32_combine_op z_crc32_combine_op # define crc32_z z_crc32_z # define deflate z_deflate # define deflateBound z_deflateBound @@ -351,6 +354,9 @@ # ifdef FAR # undef FAR # endif +# ifndef WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN +# endif # include /* No need for _export, use ZLIB.DEF instead. */ /* For complete Windows compatibility, use WINAPI, not __stdcall. */ @@ -469,11 +475,18 @@ typedef uLong FAR uLongf; # undef _LARGEFILE64_SOURCE #endif -#if defined(__WATCOMC__) && !defined(Z_HAVE_UNISTD_H) -# define Z_HAVE_UNISTD_H +#ifndef Z_HAVE_UNISTD_H +# ifdef __WATCOMC__ +# define Z_HAVE_UNISTD_H +# endif +#endif +#ifndef Z_HAVE_UNISTD_H +# if defined(_LARGEFILE64_SOURCE) && !defined(_WIN32) +# define Z_HAVE_UNISTD_H +# endif #endif #ifndef Z_SOLO -# if defined(Z_HAVE_UNISTD_H) || defined(_LARGEFILE64_SOURCE) +# if defined(Z_HAVE_UNISTD_H) # include /* for SEEK_*, off_t, and _LFS64_LARGEFILE */ # ifdef VMS # include /* for off_t */ diff --git a/include/assimp/BaseImporter.h b/include/assimp/BaseImporter.h index d0b173171..f9df32b32 100644 --- a/include/assimp/BaseImporter.h +++ b/include/assimp/BaseImporter.h @@ -63,6 +63,7 @@ struct aiImporterDesc; namespace Assimp { +// Forward declarations class Importer; class IOSystem; class BaseProcess; @@ -73,6 +74,9 @@ class IOStream; #define AI_MAKE_MAGIC(string) ((uint32_t)((string[0] << 24) + \ (string[1] << 16) + (string[2] << 8) + string[3])) +using UByteBuffer = std::vector; +using ByteBuffer = std::vector; + // --------------------------------------------------------------------------- /** FOR IMPORTER PLUGINS ONLY: The BaseImporter defines a common interface * for all importer worker classes. diff --git a/include/assimp/ParsingUtils.h b/include/assimp/ParsingUtils.h index b08f23227..7e7fb161c 100644 --- a/include/assimp/ParsingUtils.h +++ b/include/assimp/ParsingUtils.h @@ -70,7 +70,6 @@ namespace Assimp { static const unsigned int BufferSize = 4096; - // --------------------------------------------------------------------------------- template AI_FORCE_INLINE bool IsUpper(char_t in) { diff --git a/include/assimp/config.h.in b/include/assimp/config.h.in index 97551e602..cb46d8057 100644 --- a/include/assimp/config.h.in +++ b/include/assimp/config.h.in @@ -1085,6 +1085,19 @@ enum aiComponent */ #define AI_CONFIG_USE_GLTF_PBR_SPECULAR_GLOSSINESS "USE_GLTF_PBR_SPECULAR_GLOSSINESS" +/** @brief Specifies whether to apply a limit on the number of four bones per vertex in skinning + * + * When this flag is not defined, all bone weights and indices are limited to a + * maximum of four bones for each vertex (attributes JOINT_0 and WEIGHT_0 only). + * By enabling this flag, the number of bones per vertex is unlimited. + * In both cases, indices and bone weights are sorted by weight in descending order. + * In the case of the limit of up to four bones, a maximum of the four largest values are exported. + * Weights are not normalized. + * Property type: Bool. Default value: false. + */ +#define AI_CONFIG_EXPORT_GLTF_UNLIMITED_SKINNING_BONES_PER_VERTEX \ + "USE_UNLIMITED_BONES_PER VERTEX" + /** * @brief Specifies the blob name, assimp uses for exporting. * diff --git a/include/assimp/mesh.h b/include/assimp/mesh.h index 3ef94e606..45f50d5a5 100644 --- a/include/assimp/mesh.h +++ b/include/assimp/mesh.h @@ -59,6 +59,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #ifdef __cplusplus +#include + extern "C" { #endif @@ -872,11 +874,15 @@ struct aiMesh { // DO NOT REMOVE THIS ADDITIONAL CHECK if (mNumBones && mBones) { + std::unordered_set bones; for (unsigned int a = 0; a < mNumBones; a++) { if (mBones[a]) { - delete mBones[a]; + bones.insert(mBones[a]); } } + for (const aiBone *bone: bones) { + delete bone; + } delete[] mBones; } diff --git a/include/assimp/vector3.h b/include/assimp/vector3.h index 5d0962b6a..eb940e7f9 100644 --- a/include/assimp/vector3.h +++ b/include/assimp/vector3.h @@ -151,6 +151,8 @@ public: typedef aiVector3t aiVector3D; +typedef aiVector3t aiVector3f; +typedef aiVector3t aiVector3d; #else diff --git a/samples/SimpleTexturedDirectx11/CMakeLists.txt b/samples/SimpleTexturedDirectx11/CMakeLists.txt index de83734ba..f64923179 100644 --- a/samples/SimpleTexturedDirectx11/CMakeLists.txt +++ b/samples/SimpleTexturedDirectx11/CMakeLists.txt @@ -19,6 +19,7 @@ INCLUDE_DIRECTORIES( ${Assimp_SOURCE_DIR}/include ${Assimp_SOURCE_DIR}/code ${SAMPLES_SHARED_CODE_DIR} + ${Assimp_SOURCE_DIR}/contrib/utf8cpp/source ) LINK_DIRECTORIES( diff --git a/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/main.cpp b/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/main.cpp index 4da5820a1..ec031a594 100644 --- a/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/main.cpp +++ b/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/main.cpp @@ -23,6 +23,7 @@ #include #include #include +#include #include "ModelLoader.h" #include "SafeRelease.hpp" diff --git a/samples/SimpleTexturedOpenGL/CMakeLists.txt b/samples/SimpleTexturedOpenGL/CMakeLists.txt index 70837e87c..a10a15101 100644 --- a/samples/SimpleTexturedOpenGL/CMakeLists.txt +++ b/samples/SimpleTexturedOpenGL/CMakeLists.txt @@ -21,6 +21,7 @@ INCLUDE_DIRECTORIES( ${OPENGL_INCLUDE_DIR} ${GLUT_INCLUDE_DIR} ${SAMPLES_SHARED_CODE_DIR} + ${Assimp_SOURCE_DIR}/contrib/utf8cpp/source ) LINK_DIRECTORIES( diff --git a/samples/SimpleTexturedOpenGL/SimpleTexturedOpenGL/src/model_loading.cpp b/samples/SimpleTexturedOpenGL/SimpleTexturedOpenGL/src/model_loading.cpp index 7d730a630..f6d3097fe 100644 --- a/samples/SimpleTexturedOpenGL/SimpleTexturedOpenGL/src/model_loading.cpp +++ b/samples/SimpleTexturedOpenGL/SimpleTexturedOpenGL/src/model_loading.cpp @@ -17,6 +17,7 @@ #include #include #include +#include #ifdef _MSC_VER #pragma warning(disable: 4100) // Disable warning 'unreferenced formal parameter' diff --git a/test/models/glTF2/simple_skin/quad_skin.glb b/test/models/glTF2/simple_skin/quad_skin.glb new file mode 100644 index 000000000..407cebc76 Binary files /dev/null and b/test/models/glTF2/simple_skin/quad_skin.glb differ diff --git a/test/unit/utBlendImportAreaLight.cpp b/test/unit/utBlendImportAreaLight.cpp index 4a16e662c..470d80737 100644 --- a/test/unit/utBlendImportAreaLight.cpp +++ b/test/unit/utBlendImportAreaLight.cpp @@ -48,6 +48,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. class BlendImportAreaLight : public ::testing::Test { public: + BlendImportAreaLight() : + im(nullptr) {} + ~BlendImportAreaLight() override = default; void SetUp() override { im = new Assimp::Importer(); } diff --git a/test/unit/utBlenderWork.cpp b/test/unit/utBlenderWork.cpp index b20720521..977877250 100644 --- a/test/unit/utBlenderWork.cpp +++ b/test/unit/utBlenderWork.cpp @@ -48,11 +48,14 @@ using namespace ::Assimp; class BlenderWorkTest : public ::testing::Test { public: - virtual void SetUp() { + BlenderWorkTest() : im(nullptr) {} + ~BlenderWorkTest() override = default; + + void SetUp() override { im = new Assimp::Importer(); } - virtual void TearDown() { + void TearDown() override { delete im; } diff --git a/test/unit/utglTF2ImportExport.cpp b/test/unit/utglTF2ImportExport.cpp index ba1c859ad..6778e2679 100644 --- a/test/unit/utglTF2ImportExport.cpp +++ b/test/unit/utglTF2ImportExport.cpp @@ -43,6 +43,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include +#include #include #include #include @@ -504,6 +505,143 @@ TEST_F(utglTF2ImportExport, bug_import_simple_skin) { EXPECT_NE(nullptr, scene); } +bool checkSkinnedScene(const aiScene *scene){ + float eps = 0.001f; + bool result = true; + EXPECT_EQ(scene->mNumMeshes, 1u); + EXPECT_EQ(scene->mMeshes[0]->mNumBones, 10u); + EXPECT_EQ(scene->mMeshes[0]->mNumVertices, 4u); + EXPECT_LT(abs(scene->mMeshes[0]->mVertices[0].x - -1), eps); + EXPECT_LT(abs(scene->mMeshes[0]->mVertices[0].y - -1), eps); + EXPECT_LT(abs(scene->mMeshes[0]->mVertices[0].z - 0), eps); + EXPECT_LT(abs(scene->mMeshes[0]->mVertices[1].x - 1), eps); + EXPECT_LT(abs(scene->mMeshes[0]->mVertices[1].y - -1), eps); + EXPECT_LT(abs(scene->mMeshes[0]->mVertices[1].z - 0), eps); + EXPECT_LT(abs(scene->mMeshes[0]->mVertices[2].x - 1), eps); + EXPECT_LT(abs(scene->mMeshes[0]->mVertices[2].y - 1), eps); + EXPECT_LT(abs(scene->mMeshes[0]->mVertices[2].z - 0), eps); + EXPECT_LT(abs(scene->mMeshes[0]->mVertices[3].x - -1), eps); + EXPECT_LT(abs(scene->mMeshes[0]->mVertices[3].y - 1), eps); + EXPECT_LT(abs(scene->mMeshes[0]->mVertices[3].z - 0), eps); + + unsigned int numWeights[] = {4u, 4u, 4u, 4u, 2u , 1u, 1u, 2u, 1u, 1u}; + float weights[10][4] = {{0.207f, 0.291f, 0.057f, 0.303f}, + {0.113f, 0.243f, 0.499f, 0.251f}, + {0.005f, 0.010f, 0.041f, 0.093f}, + {0.090f, 0.234f, 0.404f, 0.243f}, + {0.090f, 0.222f, 0.000f, 0.000f}, + {0.216f, 0.000f, 0.000f, 0.000f}, + {0.058f, 0.000f, 0.000f, 0.000f}, + {0.086f, 0.000f, 0.000f, 0.111f}, + {0.088f, 0.000f, 0.000f, 0.000f}, + {0.049f, 0.000f, 0.000f, 0.000f}}; + for (size_t boneIndex = 0; boneIndex < 10u; ++boneIndex) { + EXPECT_EQ(scene->mMeshes[0]->mBones[boneIndex]->mNumWeights, numWeights[boneIndex]); + std::map map; + for (size_t jointIndex = 0; jointIndex < scene->mMeshes[0]->mBones[boneIndex]->mNumWeights; ++jointIndex){ + auto key = scene->mMeshes[0]->mBones[boneIndex]->mWeights[jointIndex].mVertexId; + auto weight = scene->mMeshes[0]->mBones[boneIndex]->mWeights[jointIndex].mWeight; + map[key] = weight; + } + + for (unsigned int jointIndex = 0; jointIndex < scene->mMeshes[0]->mBones[boneIndex]->mNumWeights; ++jointIndex) { + auto weight = map[jointIndex]; + EXPECT_LT(abs(ai_real(weight) - ai_real(weights[boneIndex][jointIndex])), 0.002); + } + } + + return result; +} + +void checkSkinnedSceneLimited(const aiScene *scene){ + float eps = 0.001f; + EXPECT_EQ(scene->mNumMeshes, 1u); + EXPECT_EQ(scene->mMeshes[0]->mNumBones, 10u); + EXPECT_EQ(scene->mMeshes[0]->mNumVertices, 4u); + EXPECT_LT(abs(scene->mMeshes[0]->mVertices[0].x - -1), eps); + EXPECT_LT(abs(scene->mMeshes[0]->mVertices[0].y - -1), eps); + EXPECT_LT(abs(scene->mMeshes[0]->mVertices[0].z - 0), eps); + EXPECT_LT(abs(scene->mMeshes[0]->mVertices[1].x - 1), eps); + EXPECT_LT(abs(scene->mMeshes[0]->mVertices[1].y - -1), eps); + EXPECT_LT(abs(scene->mMeshes[0]->mVertices[1].z - 0), eps); + EXPECT_LT(abs(scene->mMeshes[0]->mVertices[2].x - 1), eps); + EXPECT_LT(abs(scene->mMeshes[0]->mVertices[2].y - 1), eps); + EXPECT_LT(abs(scene->mMeshes[0]->mVertices[2].z - 0), eps); + EXPECT_LT(abs(scene->mMeshes[0]->mVertices[3].x - -1), eps); + EXPECT_LT(abs(scene->mMeshes[0]->mVertices[3].y - 1), eps); + EXPECT_LT(abs(scene->mMeshes[0]->mVertices[3].z - 0), eps); + + unsigned int numWeights[] = {4u, 4u, 1u, 4u, 1u , 1u, 1u, 1u, 1u, 1u}; + float weights[10][4] = {{0.207f, 0.291f, 0.057f, 0.303f}, + {0.113f, 0.243f, 0.499f, 0.251f}, + {0.000f, 0.000f, 0.041f, 0.000f}, + {0.090f, 0.234f, 0.404f, 0.243f}, + {0.000f, 0.222f, 0.000f, 0.000f}, + {0.216f, 0.000f, 0.000f, 0.000f}, + {0.000f, 0.000f, 0.000f, 0.000f}, + {0.000f, 0.000f, 0.000f, 0.111f}, + {0.000f, 0.000f, 0.000f, 0.000f}, + {0.000f, 0.000f, 0.000f, 0.000f}}; + for (unsigned int boneIndex = 0; boneIndex < 10u; ++boneIndex) { + EXPECT_EQ(scene->mMeshes[0]->mBones[boneIndex]->mNumWeights, numWeights[boneIndex]); + std::map map; + for (unsigned int jointIndex = 0; jointIndex < scene->mMeshes[0]->mBones[boneIndex]->mNumWeights; ++jointIndex){ + auto key = scene->mMeshes[0]->mBones[boneIndex]->mWeights[jointIndex].mVertexId; + auto weight = scene->mMeshes[0]->mBones[boneIndex]->mWeights[jointIndex].mWeight; + map[key] = weight; + } + for (unsigned int jointIndex = 0; jointIndex < scene->mMeshes[0]->mBones[boneIndex]->mNumWeights; ++jointIndex) { + auto weight = map[jointIndex]; + EXPECT_LT(std::abs(ai_real(weight) - ai_real(weights[boneIndex][jointIndex])), 0.002); + } + } +} + +TEST_F(utglTF2ImportExport, bug_import_simple_skin2) { + Assimp::Importer importer; + Assimp::Exporter exporter; + const aiScene *scene = importer.ReadFile( + ASSIMP_TEST_MODELS_DIR "/glTF2/simple_skin/quad_skin.glb", + aiProcess_ValidateDataStructure); + checkSkinnedScene(scene); + + ASSERT_EQ(aiReturn_SUCCESS, exporter.Export(scene, "glb2", + ASSIMP_TEST_MODELS_DIR "/glTF2/simple_skin/quad_four_out.glb")); + ASSERT_EQ(aiReturn_SUCCESS, exporter.Export(scene, "gltf2", + ASSIMP_TEST_MODELS_DIR "/glTF2/simple_skin/quad_four_out.gltf")); + + // enable more than four bones per vertex + Assimp::ExportProperties properties = Assimp::ExportProperties(); + properties.SetPropertyBool( + AI_CONFIG_EXPORT_GLTF_UNLIMITED_SKINNING_BONES_PER_VERTEX, true); + ASSERT_EQ(aiReturn_SUCCESS, exporter.Export(scene, "glb2", + ASSIMP_TEST_MODELS_DIR "/glTF2/simple_skin/quad_all_out.glb", 0u, &properties)); + ASSERT_EQ(aiReturn_SUCCESS, exporter.Export(scene, "gltf2", + ASSIMP_TEST_MODELS_DIR "/glTF2/simple_skin/quad_all_out.gltf", 0u, &properties)); + + // check skinning data of both exported files for limited number bones per vertex + const aiScene *limitedSceneImported = importer.ReadFile( + ASSIMP_TEST_MODELS_DIR "/glTF2/simple_skin/quad_four_out.gltf", + aiProcess_ValidateDataStructure); + checkSkinnedSceneLimited(limitedSceneImported); + limitedSceneImported = importer.ReadFile( + ASSIMP_TEST_MODELS_DIR "/glTF2/simple_skin/quad_four_out.glb", + aiProcess_ValidateDataStructure); + checkSkinnedSceneLimited(limitedSceneImported); + + // check skinning data of both exported files for unlimited number bones per vertex + const aiScene *sceneImported = importer.ReadFile( + ASSIMP_TEST_MODELS_DIR "/glTF2/simple_skin/quad_all_out.gltf", + aiProcess_ValidateDataStructure); + checkSkinnedScene(sceneImported); + sceneImported = importer.ReadFile( + ASSIMP_TEST_MODELS_DIR "/glTF2/simple_skin/quad_all_out.glb", + aiProcess_ValidateDataStructure); + checkSkinnedScene(sceneImported); + + +} + TEST_F(utglTF2ImportExport, import_cameras) { Assimp::Importer importer; const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/glTF2/cameras/Cameras.gltf",