diff --git a/CMakeLists.txt b/CMakeLists.txt index 0f0e5a793..20c735c4c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -138,7 +138,7 @@ IF (WIN32) ELSE() OPTION( ASSIMP_BUILD_ZLIB "Build your own zlib" - OFF + ON ) ENDIF() diff --git a/code/AssetLib/3DS/3DSHelper.h b/code/AssetLib/3DS/3DSHelper.h index 06c36bfeb..2279d105c 100644 --- a/code/AssetLib/3DS/3DSHelper.h +++ b/code/AssetLib/3DS/3DSHelper.h @@ -397,10 +397,6 @@ struct Material { Material(const Material &other) = default; - Material(Material &&other) AI_NO_EXCEPT = default; - - Material &operator=(Material &&other) AI_NO_EXCEPT = default; - virtual ~Material() = default; //! Name of the material diff --git a/code/AssetLib/3DS/3DSLoader.cpp b/code/AssetLib/3DS/3DSLoader.cpp index 769e8a6ee..aa29956df 100644 --- a/code/AssetLib/3DS/3DSLoader.cpp +++ b/code/AssetLib/3DS/3DSLoader.cpp @@ -266,8 +266,15 @@ void Discreet3DSImporter::ParseMainChunk() { }; ASSIMP_3DS_END_CHUNK(); +#if defined(__clang__) +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunreachable-code-return" +#endif // recursively continue processing this hierarchy level return ParseMainChunk(); +#if defined(__clang__) +#pragma clang diagnostic pop +#endif } // ------------------------------------------------------------------------------------------------ diff --git a/code/AssetLib/3DS/3DSLoader.h b/code/AssetLib/3DS/3DSLoader.h index f47fcfef9..6bd73f412 100644 --- a/code/AssetLib/3DS/3DSLoader.h +++ b/code/AssetLib/3DS/3DSLoader.h @@ -68,7 +68,7 @@ using namespace D3DS; class Discreet3DSImporter : public BaseImporter { public: Discreet3DSImporter(); - ~Discreet3DSImporter(); + ~Discreet3DSImporter() override; // ------------------------------------------------------------------- /** Returns whether the class can handle the format of the given file. diff --git a/code/AssetLib/3MF/3MFTypes.h b/code/AssetLib/3MF/3MFTypes.h index 02238ceab..8207b568b 100644 --- a/code/AssetLib/3MF/3MFTypes.h +++ b/code/AssetLib/3MF/3MFTypes.h @@ -93,7 +93,7 @@ public: // empty } - ~EmbeddedTexture() = default; + ~EmbeddedTexture() override = default; ResourceType getType() const override { return ResourceType::RT_EmbeddedTexture2D; @@ -110,7 +110,7 @@ public: // empty } - ~Texture2DGroup() = default; + ~Texture2DGroup() override = default; ResourceType getType() const override { return ResourceType::RT_Texture2DGroup; @@ -127,7 +127,7 @@ public: // empty } - ~BaseMaterials() = default; + ~BaseMaterials() override = default; ResourceType getType() const override { return ResourceType::RT_BaseMaterials; @@ -152,7 +152,7 @@ public: // empty } - ~Object() = default; + ~Object() override = default; ResourceType getType() const override { return ResourceType::RT_Object; diff --git a/code/AssetLib/AMF/AMFImporter.hpp b/code/AssetLib/AMF/AMFImporter.hpp index 601eae4e4..27f733043 100644 --- a/code/AssetLib/AMF/AMFImporter.hpp +++ b/code/AssetLib/AMF/AMFImporter.hpp @@ -282,11 +282,11 @@ public: 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; - void Throw_CloseNotFound(const std::string &nodeName); - void Throw_IncorrectAttr(const std::string &nodeName, const std::string &pAttrName); - void Throw_IncorrectAttrValue(const std::string &nodeName, const std::string &pAttrName); - void Throw_MoreThanOnceDefined(const std::string &nodeName, const std::string &pNodeType, const std::string &pDescription); - void Throw_ID_NotFound(const std::string &pID) 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); diff --git a/code/AssetLib/ASE/ASELoader.cpp b/code/AssetLib/ASE/ASELoader.cpp index 951e8539d..4617c9ed4 100644 --- a/code/AssetLib/ASE/ASELoader.cpp +++ b/code/AssetLib/ASE/ASELoader.cpp @@ -44,7 +44,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef ASSIMP_BUILD_NO_ASE_IMPORTER - #ifndef ASSIMP_BUILD_NO_3DS_IMPORTER // internal headers @@ -322,21 +321,6 @@ void ASEImporter::BuildAnimations(const std::vector &nodes) { aiNodeAnim *nd = pcAnim->mChannels[iNum++] = new aiNodeAnim(); nd->mNodeName.Set(me->mName + ".Target"); - // If there is no input position channel we will need - // to supply the default position from the node's - // local transformation matrix. - /*TargetAnimationHelper helper; - if (me->mAnim.akeyPositions.empty()) - { - aiMatrix4x4& mat = (*i)->mTransform; - helper.SetFixedMainAnimationChannel(aiVector3D( - mat.a4, mat.b4, mat.c4)); - } - else helper.SetMainAnimationChannel (&me->mAnim.akeyPositions); - helper.SetTargetAnimationChannel (&me->mTargetAnim.akeyPositions); - - helper.Process(&me->mTargetAnim.akeyPositions);*/ - // Allocate the key array and fill it nd->mNumPositionKeys = (unsigned int)me->mTargetAnim.akeyPositions.size(); nd->mPositionKeys = new aiVectorKey[nd->mNumPositionKeys]; diff --git a/code/AssetLib/ASE/ASEParser.cpp b/code/AssetLib/ASE/ASEParser.cpp index 839d308de..8e7ca63d7 100644 --- a/code/AssetLib/ASE/ASEParser.cpp +++ b/code/AssetLib/ASE/ASEParser.cpp @@ -304,7 +304,6 @@ void Parser::Parse() { } AI_ASE_HANDLE_TOP_LEVEL_SECTION(); } - return; } // ------------------------------------------------------------------------------------------------ @@ -734,7 +733,6 @@ void Parser::ParseLV3MapBlock(Texture &map) { } AI_ASE_HANDLE_SECTION("3", "*MAP_XXXXXX"); } - return; } // ------------------------------------------------------------------------------------------------ @@ -859,7 +857,6 @@ void Parser::ParseLV1ObjectBlock(ASE::BaseNode &node) { } AI_ASE_HANDLE_TOP_LEVEL_SECTION(); } - return; } // ------------------------------------------------------------------------------------------------ @@ -883,7 +880,6 @@ void Parser::ParseLV2CameraSettingsBlock(ASE::Camera &camera) { } AI_ASE_HANDLE_SECTION("2", "CAMERA_SETTINGS"); } - return; } // ------------------------------------------------------------------------------------------------ @@ -1189,7 +1185,6 @@ void Parser::ParseLV2NodeTransformBlock(ASE::BaseNode &mesh) { } AI_ASE_HANDLE_SECTION("2", "*NODE_TM"); } - return; } // ------------------------------------------------------------------------------------------------ void Parser::ParseLV2MeshBlock(ASE::Mesh &mesh) { @@ -1310,7 +1305,6 @@ void Parser::ParseLV2MeshBlock(ASE::Mesh &mesh) { } AI_ASE_HANDLE_SECTION("2", "*MESH"); } - return; } // ------------------------------------------------------------------------------------------------ void Parser::ParseLV3MeshWeightsBlock(ASE::Mesh &mesh) { @@ -1344,7 +1338,6 @@ void Parser::ParseLV3MeshWeightsBlock(ASE::Mesh &mesh) { } AI_ASE_HANDLE_SECTION("3", "*MESH_WEIGHTS"); } - return; } // ------------------------------------------------------------------------------------------------ void Parser::ParseLV4MeshBones(unsigned int iNumBones, ASE::Mesh &mesh) { @@ -1414,7 +1407,6 @@ void Parser::ParseLV4MeshBonesVertices(unsigned int iNumVertices, ASE::Mesh &mes } AI_ASE_HANDLE_SECTION("4", "*MESH_BONE_VERTEX"); } - return; } // ------------------------------------------------------------------------------------------------ void Parser::ParseLV3MeshVertexListBlock( @@ -1443,7 +1435,6 @@ void Parser::ParseLV3MeshVertexListBlock( } AI_ASE_HANDLE_SECTION("3", "*MESH_VERTEX_LIST"); } - return; } // ------------------------------------------------------------------------------------------------ void Parser::ParseLV3MeshFaceListBlock(unsigned int iNumFaces, ASE::Mesh &mesh) { @@ -1470,7 +1461,6 @@ void Parser::ParseLV3MeshFaceListBlock(unsigned int iNumFaces, ASE::Mesh &mesh) } AI_ASE_HANDLE_SECTION("3", "*MESH_FACE_LIST"); } - return; } // ------------------------------------------------------------------------------------------------ void Parser::ParseLV3MeshTListBlock(unsigned int iNumVertices, @@ -1503,7 +1493,6 @@ void Parser::ParseLV3MeshTListBlock(unsigned int iNumVertices, } AI_ASE_HANDLE_SECTION("3", "*MESH_TVERT_LIST"); } - return; } // ------------------------------------------------------------------------------------------------ void Parser::ParseLV3MeshTFaceListBlock(unsigned int iNumFaces, @@ -1532,7 +1521,6 @@ void Parser::ParseLV3MeshTFaceListBlock(unsigned int iNumFaces, } AI_ASE_HANDLE_SECTION("3", "*MESH_TFACE_LIST"); } - return; } // ------------------------------------------------------------------------------------------------ void Parser::ParseLV3MappingChannel(unsigned int iChannel, ASE::Mesh &mesh) { @@ -1567,7 +1555,6 @@ void Parser::ParseLV3MappingChannel(unsigned int iChannel, ASE::Mesh &mesh) { } AI_ASE_HANDLE_SECTION("3", "*MESH_MAPPING_CHANNEL"); } - return; } // ------------------------------------------------------------------------------------------------ void Parser::ParseLV3MeshCListBlock(unsigned int iNumVertices, ASE::Mesh &mesh) { @@ -1595,7 +1582,6 @@ void Parser::ParseLV3MeshCListBlock(unsigned int iNumVertices, ASE::Mesh &mesh) } AI_ASE_HANDLE_SECTION("3", "*MESH_CVERTEX_LIST"); } - return; } // ------------------------------------------------------------------------------------------------ void Parser::ParseLV3MeshCFaceListBlock(unsigned int iNumFaces, ASE::Mesh &mesh) { @@ -1623,7 +1609,6 @@ void Parser::ParseLV3MeshCFaceListBlock(unsigned int iNumFaces, ASE::Mesh &mesh) } AI_ASE_HANDLE_SECTION("3", "*MESH_CFACE_LIST"); } - return; } // ------------------------------------------------------------------------------------------------ void Parser::ParseLV3MeshNormalListBlock(ASE::Mesh &sMesh) { @@ -1681,7 +1666,6 @@ void Parser::ParseLV3MeshNormalListBlock(ASE::Mesh &sMesh) { } AI_ASE_HANDLE_SECTION("3", "*MESH_NORMALS"); } - return; } // ------------------------------------------------------------------------------------------------ void Parser::ParseLV4MeshFace(ASE::Face &out) { diff --git a/code/AssetLib/Assjson/cencode.c b/code/AssetLib/Assjson/cencode.c index 614a2671f..ec771536d 100644 --- a/code/AssetLib/Assjson/cencode.c +++ b/code/AssetLib/Assjson/cencode.c @@ -7,7 +7,7 @@ For details, see http://sourceforge.net/projects/libb64 #include "cencode.h" // changed from -const int CHARS_PER_LINE = 72; +static const int CHARS_PER_LINE = 72; #ifdef _MSC_VER #pragma warning(push) diff --git a/code/AssetLib/Blender/BlenderCustomData.cpp b/code/AssetLib/Blender/BlenderCustomData.cpp index c74a6bb75..2359482e1 100644 --- a/code/AssetLib/Blender/BlenderCustomData.cpp +++ b/code/AssetLib/Blender/BlenderCustomData.cpp @@ -96,7 +96,8 @@ struct CustomDataTypeDescription { * other (like CD_ORCO, ...) uses arrays of rawtypes or even arrays of Structures * use a special readfunction for that cases */ -std::array customDataTypeDescriptions = { { DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(MVert), +static std::array customDataTypeDescriptions = { { + DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(MVert), DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION, DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION, DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(MEdge), diff --git a/code/AssetLib/Collada/ColladaParser.cpp b/code/AssetLib/Collada/ColladaParser.cpp index cce6a0db6..fcadd08a7 100644 --- a/code/AssetLib/Collada/ColladaParser.cpp +++ b/code/AssetLib/Collada/ColladaParser.cpp @@ -1855,7 +1855,6 @@ size_t ColladaParser::ReadPrimitives(XmlNode &node, Mesh &pMesh, std::vectormRootNode->mName.Set(unique_name); // root has ID 0 - ConvertNodes(0L, mSceneOut->mRootNode, mSceneOut->mRootNode, aiMatrix4x4()); + ConvertNodes(0L, mSceneOut->mRootNode, mSceneOut->mRootNode); } static std::string getAncestorBaseName(const aiNode *node) { @@ -196,7 +196,7 @@ struct FBXConverter::PotentialNode { /// todo: get bone from stack /// todo: make map of aiBone* to aiNode* /// then update convert clusters to the new format -void FBXConverter::ConvertNodes(uint64_t id, aiNode *parent, aiNode *root_node, const aiMatrix4x4 &globalTransform) { +void FBXConverter::ConvertNodes(uint64_t id, aiNode *parent, aiNode *root_node) { const std::vector &conns = doc.GetConnectionsByDestinationSequenced(id, "Model"); std::vector nodes; @@ -290,15 +290,14 @@ void FBXConverter::ConvertNodes(uint64_t id, aiNode *parent, aiNode *root_node, } // recursion call - child nodes - aiMatrix4x4 newGlobalMatrix = globalTransform * nodes_chain.front().mNode->mTransformation; - ConvertNodes(model->ID(), last_parent, root_node, newGlobalMatrix); + ConvertNodes(model->ID(), last_parent, root_node); if (doc.Settings().readLights) { ConvertLights(*model, node_name); } if (doc.Settings().readCameras) { - ConvertCameras(*model, node_name, newGlobalMatrix); + ConvertCameras(*model, node_name); } nodes.push_back(std::move(nodes_chain.front())); @@ -328,14 +327,12 @@ void FBXConverter::ConvertLights(const Model &model, const std::string &orig_nam } } -void FBXConverter::ConvertCameras(const Model &model, - const std::string &orig_name, - const aiMatrix4x4 &transform) { +void FBXConverter::ConvertCameras(const Model &model, const std::string &orig_name) { const std::vector &node_attrs = model.GetAttributes(); for (const NodeAttribute *attr : node_attrs) { const Camera *const cam = dynamic_cast(attr); if (cam) { - ConvertCamera(*cam, orig_name, transform); + ConvertCamera(*cam, orig_name); } } } @@ -416,9 +413,7 @@ void FBXConverter::ConvertLight(const Light &light, const std::string &orig_name } } -void FBXConverter::ConvertCamera(const Camera &cam, - const std::string &orig_name, - aiMatrix4x4 transform) { +void FBXConverter::ConvertCamera(const Camera &cam, const std::string &orig_name) { cameras.push_back(new aiCamera()); aiCamera *const out_camera = cameras.back(); @@ -426,16 +421,11 @@ void FBXConverter::ConvertCamera(const Camera &cam, out_camera->mAspect = cam.AspectWidth() / cam.AspectHeight(); - aiVector3D pos = cam.Position(); - out_camera->mLookAt = cam.InterestPosition(); - out_camera->mUp = pos + cam.UpVector(); - transform.Inverse(); - pos *= transform; - out_camera->mLookAt *= transform; - out_camera->mUp *= transform; - out_camera->mLookAt -= pos; - out_camera->mUp -= pos; + // NOTE: Camera mPosition, mLookAt and mUp must be set to default here. + // All transformations to the camera will be handled by its node in the scenegraph. out_camera->mPosition = aiVector3D(0.0f); + out_camera->mLookAt = aiVector3D(1.0f, 0.0f, 0.0f); + out_camera->mUp = aiVector3D(0.0f, 1.0f, 0.0f); out_camera->mHorizontalFOV = AI_DEG_TO_RAD(cam.FieldOfView()); diff --git a/code/AssetLib/FBX/FBXConverter.h b/code/AssetLib/FBX/FBXConverter.h index b9b6c46b0..41acb6ffe 100644 --- a/code/AssetLib/FBX/FBXConverter.h +++ b/code/AssetLib/FBX/FBXConverter.h @@ -134,22 +134,19 @@ private: // ------------------------------------------------------------------------------------------------ // collect and assign child nodes - void ConvertNodes(uint64_t id, aiNode *parent, aiNode *root_node, - const aiMatrix4x4 &globalTransform); + void ConvertNodes(uint64_t id, aiNode *parent, aiNode *root_node); // ------------------------------------------------------------------------------------------------ void ConvertLights(const Model& model, const std::string &orig_name ); // ------------------------------------------------------------------------------------------------ - void ConvertCameras(const Model& model, const std::string &orig_name, - const aiMatrix4x4 &transform); + void ConvertCameras(const Model& model, const std::string &orig_name ); // ------------------------------------------------------------------------------------------------ void ConvertLight( const Light& light, const std::string &orig_name ); // ------------------------------------------------------------------------------------------------ - void ConvertCamera(const Camera& cam, const std::string &orig_name, - aiMatrix4x4 transform); + void ConvertCamera( const Camera& cam, const std::string &orig_name ); // ------------------------------------------------------------------------------------------------ void GetUniqueName( const std::string &name, std::string& uniqueName ); diff --git a/code/AssetLib/FBX/FBXDocument.cpp b/code/AssetLib/FBX/FBXDocument.cpp index ea39a9a00..657f30f8c 100644 --- a/code/AssetLib/FBX/FBXDocument.cpp +++ b/code/AssetLib/FBX/FBXDocument.cpp @@ -243,7 +243,7 @@ FileGlobalSettings::FileGlobalSettings(const Document &doc, std::shared_ptrCompound(); for(const ElementMap::value_type& el : sobjects.Elements()) { @@ -387,7 +393,7 @@ void Document::ReadObjects() { delete foundObject->second; } - objects[id] = new LazyObject(id, *el.second, *this); + objects[id] = new_LazyObject(id, *el.second, *this); // grab all animation stacks upfront since there is no listing of them if(!strcmp(el.first.c_str(),"AnimationStack")) { @@ -454,8 +460,10 @@ void Document::ReadPropertyTemplates() { } // ------------------------------------------------------------------------------------------------ -void Document::ReadConnections() { - const Scope& sc = parser.GetRootScope(); +void Document::ReadConnections() +{ + StackAllocator &allocator = parser.GetAllocator(); + const Scope &sc = parser.GetRootScope(); // read property templates from "Definitions" section const Element* const econns = sc["Connections"]; if(!econns || !econns->Compound()) { @@ -494,7 +502,7 @@ void Document::ReadConnections() { } // add new connection - const Connection* const c = new Connection(insertionOrder++,src,dest,prop,*this); + const Connection* const c = new_Connection(insertionOrder++,src,dest,prop,*this); src_connections.insert(ConnectionMap::value_type(src,c)); dest_connections.insert(ConnectionMap::value_type(dest,c)); } diff --git a/code/AssetLib/FBX/FBXDocument.h b/code/AssetLib/FBX/FBXDocument.h index 821d4d5cb..e229eef52 100644 --- a/code/AssetLib/FBX/FBXDocument.h +++ b/code/AssetLib/FBX/FBXDocument.h @@ -81,6 +81,10 @@ class BlendShape; class Skin; class Cluster; +#define new_LazyObject new (allocator.Allocate(sizeof(LazyObject))) LazyObject +#define new_Connection new (allocator.Allocate(sizeof(Connection))) Connection +#define delete_LazyObject(_p) (_p)->~LazyObject() +#define delete_Connection(_p) (_p)->~Connection() /** Represents a delay-parsed FBX objects. Many objects in the scene * are not needed by assimp, so it makes no sense to parse them @@ -1073,7 +1077,7 @@ private: /** DOM root for a FBX file */ class Document { public: - Document(const Parser& parser, const ImportSettings& settings); + Document(Parser& parser, const ImportSettings& settings); ~Document(); @@ -1157,7 +1161,7 @@ private: const ImportSettings& settings; ObjectMap objects; - const Parser& parser; + Parser& parser; PropertyTemplateMap templates; ConnectionMap src_connections; diff --git a/code/AssetLib/FBX/FBXImporter.cpp b/code/AssetLib/FBX/FBXImporter.cpp index e4f5f9dd4..56e0f38e9 100644 --- a/code/AssetLib/FBX/FBXImporter.cpp +++ b/code/AssetLib/FBX/FBXImporter.cpp @@ -152,19 +152,19 @@ void FBXImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy // broad-phase tokenized pass in which we identify the core // syntax elements of FBX (brackets, commas, key:value mappings) TokenList tokens; - try { - + Assimp::StackAllocator tempAllocator; + try { bool is_binary = false; if (!strncmp(begin, "Kaydara FBX Binary", 18)) { is_binary = true; - TokenizeBinary(tokens, begin, contents.size()); + TokenizeBinary(tokens, begin, contents.size(), tempAllocator); } else { - Tokenize(tokens, begin); + Tokenize(tokens, begin, tempAllocator); } // use this information to construct a very rudimentary // parse-tree representing the FBX scope structure - Parser parser(tokens, is_binary); + Parser parser(tokens, tempAllocator, is_binary); // take the raw parse-tree and convert it to a FBX DOM Document doc(parser, mSettings); @@ -183,10 +183,12 @@ void FBXImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy // assimp universal format (M) SetFileScale(size_relative_to_cm * 0.01f); - std::for_each(tokens.begin(), tokens.end(), Util::delete_fun()); - } catch (std::exception &) { - std::for_each(tokens.begin(), tokens.end(), Util::delete_fun()); - throw; + // This collection does not own the memory for the tokens, but we need to call their d'tor + std::for_each(tokens.begin(), tokens.end(), Util::destructor_fun()); + + } catch (std::exception &) { + std::for_each(tokens.begin(), tokens.end(), Util::destructor_fun()); + throw; } } diff --git a/code/AssetLib/FBX/FBXMaterial.cpp b/code/AssetLib/FBX/FBXMaterial.cpp index 2677d652a..2f575a511 100644 --- a/code/AssetLib/FBX/FBXMaterial.cpp +++ b/code/AssetLib/FBX/FBXMaterial.cpp @@ -138,20 +138,6 @@ Material::Material(uint64_t id, const Element& element, const Document& doc, con // ------------------------------------------------------------------------------------------------ Material::~Material() = default; - aiVector2D uvTrans; - aiVector2D uvScaling; - ai_real uvRotation; - - std::string type; - std::string relativeFileName; - std::string fileName; - std::string alphaSource; - std::shared_ptr props; - - unsigned int crop[4]{}; - - const Video* media; - // ------------------------------------------------------------------------------------------------ Texture::Texture(uint64_t id, const Element& element, const Document& doc, const std::string& name) : Object(id,element,name), diff --git a/code/AssetLib/FBX/FBXParser.cpp b/code/AssetLib/FBX/FBXParser.cpp index d71321452..c7b579665 100644 --- a/code/AssetLib/FBX/FBXParser.cpp +++ b/code/AssetLib/FBX/FBXParser.cpp @@ -88,6 +88,7 @@ namespace { // ------------------------------------------------------------------------------------------------ + AI_WONT_RETURN void ParseError(const std::string& message, TokenPtr token) AI_WONT_RETURN_SUFFIX; void ParseError(const std::string& message, TokenPtr token) { if(token) { @@ -115,8 +116,11 @@ namespace Assimp { namespace FBX { // ------------------------------------------------------------------------------------------------ -Element::Element(const Token& key_token, Parser& parser) : key_token(key_token) { +Element::Element(const Token& key_token, Parser& parser) : + key_token(key_token), compound(nullptr) +{ TokenPtr n = nullptr; + StackAllocator &allocator = parser.GetAllocator(); do { n = parser.AdvanceToNextToken(); if(!n) { @@ -145,7 +149,7 @@ Element::Element(const Token& key_token, Parser& parser) : key_token(key_token) } if (n->Type() == TokenType_OPEN_BRACKET) { - compound.reset(new Scope(parser)); + compound = new_Scope(parser); // current token should be a TOK_CLOSE_BRACKET n = parser.CurrentToken(); @@ -163,6 +167,15 @@ Element::Element(const Token& key_token, Parser& parser) : key_token(key_token) } // ------------------------------------------------------------------------------------------------ +Element::~Element() +{ + if (compound) { + delete_Scope(compound); + } + + // no need to delete tokens, they are owned by the parser +} + Scope::Scope(Parser& parser,bool topLevel) { if(!topLevel) { @@ -172,6 +185,7 @@ Scope::Scope(Parser& parser,bool topLevel) } } + StackAllocator &allocator = parser.GetAllocator(); TokenPtr n = parser.AdvanceToNextToken(); if (n == nullptr) { ParseError("unexpected end of file"); @@ -188,36 +202,45 @@ Scope::Scope(Parser& parser,bool topLevel) ParseError("unexpected content: empty string."); } - elements.insert(ElementMap::value_type(str,new_Element(*n,parser))); + auto *element = new_Element(*n, parser); // Element() should stop at the next Key token (or right after a Close token) n = parser.CurrentToken(); if (n == nullptr) { if (topLevel) { + elements.insert(ElementMap::value_type(str, element)); return; } + delete element; ParseError("unexpected end of file",parser.LastToken()); + } else { + elements.insert(ElementMap::value_type(str, element)); } } } // ------------------------------------------------------------------------------------------------ -Scope::~Scope() { - for(ElementMap::value_type& v : elements) { - delete v.second; +Scope::~Scope() +{ + // This collection does not own the memory for the elements, but we need to call their d'tor: + + for (ElementMap::value_type &v : elements) { + delete_Element(v.second); } } // ------------------------------------------------------------------------------------------------ -Parser::Parser (const TokenList& tokens, bool is_binary) -: tokens(tokens) -, last() -, current() -, cursor(tokens.begin()) -, is_binary(is_binary) +Parser::Parser(const TokenList &tokens, StackAllocator &allocator, bool is_binary) : + tokens(tokens), allocator(allocator), last(), current(), cursor(tokens.begin()), is_binary(is_binary) { ASSIMP_LOG_DEBUG("Parsing FBX tokens"); - root.reset(new Scope(*this,true)); + root = new_Scope(*this, true); +} + +// ------------------------------------------------------------------------------------------------ +Parser::~Parser() +{ + delete_Scope(root); } // ------------------------------------------------------------------------------------------------ diff --git a/code/AssetLib/FBX/FBXParser.h b/code/AssetLib/FBX/FBXParser.h index fd5c5a181..5f231738d 100644 --- a/code/AssetLib/FBX/FBXParser.h +++ b/code/AssetLib/FBX/FBXParser.h @@ -52,6 +52,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include +#include "Common/StackAllocator.h" #include "FBXCompileConfig.h" #include "FBXTokenizer.h" @@ -63,14 +64,14 @@ class Parser; class Element; // XXX should use C++11's unique_ptr - but assimp's need to keep working with 03 -typedef std::vector< Scope* > ScopeList; -typedef std::fbx_unordered_multimap< std::string, Element* > ElementMap; - -typedef std::pair ElementCollection; - -# define new_Scope new Scope -# define new_Element new Element +using ScopeList = std::vector; +using ElementMap = std::fbx_unordered_multimap< std::string, Element*>; +using ElementCollection = std::pair; +#define new_Scope new (allocator.Allocate(sizeof(Scope))) Scope +#define new_Element new (allocator.Allocate(sizeof(Element))) Element +#define delete_Scope(_p) (_p)->~Scope() +#define delete_Element(_p) (_p)->~Element() /** FBX data entity that consists of a key:value tuple. * @@ -82,15 +83,16 @@ typedef std::pair Element * @endverbatim * * As can be seen in this sample, elements can contain nested #Scope - * as their trailing member. **/ + * as their trailing member. +**/ class Element { public: Element(const Token& key_token, Parser& parser); - ~Element() = default; + ~Element(); const Scope* Compound() const { - return compound.get(); + return compound; } const Token& KeyToken() const { @@ -104,7 +106,7 @@ public: private: const Token& key_token; TokenList tokens; - std::unique_ptr compound; + Scope* compound; }; /** FBX data entity that consists of a 'scope', a collection @@ -159,8 +161,8 @@ class Parser public: /** Parse given a token list. Does not take ownership of the tokens - * the objects must persist during the entire parser lifetime */ - Parser (const TokenList& tokens,bool is_binary); - ~Parser() = default; + Parser(const TokenList &tokens, StackAllocator &allocator, bool is_binary); + ~Parser(); const Scope& GetRootScope() const { return *root; @@ -170,6 +172,10 @@ public: return is_binary; } + StackAllocator &GetAllocator() { + return allocator; + } + private: friend class Scope; friend class Element; @@ -180,10 +186,10 @@ private: private: const TokenList& tokens; - + StackAllocator &allocator; TokenPtr last, current; TokenList::const_iterator cursor; - std::unique_ptr root; + Scope *root; const bool is_binary; }; diff --git a/code/AssetLib/FBX/FBXTokenizer.cpp b/code/AssetLib/FBX/FBXTokenizer.cpp index f63e687e8..45d5e7750 100644 --- a/code/AssetLib/FBX/FBXTokenizer.cpp +++ b/code/AssetLib/FBX/FBXTokenizer.cpp @@ -94,7 +94,8 @@ AI_WONT_RETURN void TokenizeError(const std::string& message, unsigned int line, // process a potential data token up to 'cur', adding it to 'output_tokens'. // ------------------------------------------------------------------------------------------------ -void ProcessDataToken( TokenList& output_tokens, const char*& start, const char*& end, +void ProcessDataToken(TokenList &output_tokens, StackAllocator &token_allocator, + const char*& start, const char*& end, unsigned int line, unsigned int column, TokenType type = TokenType_DATA, @@ -131,8 +132,7 @@ void ProcessDataToken( TokenList& output_tokens, const char*& start, const char* } // ------------------------------------------------------------------------------------------------ -void Tokenize(TokenList& output_tokens, const char* input) -{ +void Tokenize(TokenList &output_tokens, const char *input, StackAllocator &token_allocator) { ai_assert(input); ASSIMP_LOG_DEBUG("Tokenizing ASCII FBX file"); @@ -164,7 +164,7 @@ void Tokenize(TokenList& output_tokens, const char* input) in_double_quotes = false; token_end = cur; - ProcessDataToken(output_tokens,token_begin,token_end,line,column); + ProcessDataToken(output_tokens, token_allocator, token_begin, token_end, line, column); pending_data_token = false; } continue; @@ -181,30 +181,30 @@ void Tokenize(TokenList& output_tokens, const char* input) continue; case ';': - ProcessDataToken(output_tokens,token_begin,token_end,line,column); + ProcessDataToken(output_tokens, token_allocator, token_begin, token_end, line, column); comment = true; continue; case '{': - ProcessDataToken(output_tokens,token_begin,token_end, line, column); + ProcessDataToken(output_tokens, token_allocator, token_begin, token_end, line, column); output_tokens.push_back(new_Token(cur,cur+1,TokenType_OPEN_BRACKET,line,column)); continue; case '}': - ProcessDataToken(output_tokens,token_begin,token_end,line,column); + ProcessDataToken(output_tokens, token_allocator, token_begin, token_end, line, column); output_tokens.push_back(new_Token(cur,cur+1,TokenType_CLOSE_BRACKET,line,column)); continue; case ',': if (pending_data_token) { - ProcessDataToken(output_tokens,token_begin,token_end,line,column,TokenType_DATA,true); + ProcessDataToken(output_tokens, token_allocator, token_begin, token_end, line, column, TokenType_DATA, true); } output_tokens.push_back(new_Token(cur,cur+1,TokenType_COMMA,line,column)); continue; case ':': if (pending_data_token) { - ProcessDataToken(output_tokens,token_begin,token_end,line,column,TokenType_KEY,true); + ProcessDataToken(output_tokens, token_allocator, token_begin, token_end, line, column, TokenType_KEY, true); } else { TokenizeError("unexpected colon", line, column); @@ -226,7 +226,7 @@ void Tokenize(TokenList& output_tokens, const char* input) } } - ProcessDataToken(output_tokens,token_begin,token_end,line,column,type); + ProcessDataToken(output_tokens, token_allocator, token_begin, token_end, line, column, type); } pending_data_token = false; diff --git a/code/AssetLib/FBX/FBXTokenizer.h b/code/AssetLib/FBX/FBXTokenizer.h index 79f71229b..05a0725bd 100644 --- a/code/AssetLib/FBX/FBXTokenizer.h +++ b/code/AssetLib/FBX/FBXTokenizer.h @@ -47,6 +47,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define INCLUDED_AI_FBX_TOKENIZER_H #include "FBXCompileConfig.h" +#include "Common/StackAllocator.h" #include #include #include @@ -157,7 +158,8 @@ private: typedef const Token* TokenPtr; typedef std::vector< TokenPtr > TokenList; -#define new_Token new Token +#define new_Token new (token_allocator.Allocate(sizeof(Token))) Token +#define delete_Token(_p) (_p)->~Token() /** Main FBX tokenizer function. Transform input buffer into a list of preprocessed tokens. @@ -167,7 +169,7 @@ typedef std::vector< TokenPtr > TokenList; * @param output_tokens Receives a list of all tokens in the input data. * @param input_buffer Textual input buffer to be processed, 0-terminated. * @throw DeadlyImportError if something goes wrong */ -void Tokenize(TokenList& output_tokens, const char* input); +void Tokenize(TokenList &output_tokens, const char *input, StackAllocator &tokenAllocator); /** Tokenizer function for binary FBX files. @@ -178,7 +180,7 @@ void Tokenize(TokenList& output_tokens, const char* input); * @param input_buffer Binary input buffer to be processed. * @param length Length of input buffer, in bytes. There is no 0-terminal. * @throw DeadlyImportError if something goes wrong */ -void TokenizeBinary(TokenList& output_tokens, const char* input, size_t length); +void TokenizeBinary(TokenList &output_tokens, const char *input, size_t length, StackAllocator &tokenAllocator); } // ! FBX diff --git a/code/AssetLib/FBX/FBXUtil.h b/code/AssetLib/FBX/FBXUtil.h index 0e0bb75be..4674a5054 100644 --- a/code/AssetLib/FBX/FBXUtil.h +++ b/code/AssetLib/FBX/FBXUtil.h @@ -66,6 +66,17 @@ struct delete_fun } }; +/** helper for std::for_each to call the destructor on all items in a container without freeing their heap*/ +template +struct destructor_fun { + void operator()(const volatile T* del) { + if (del) { + del->~T(); + } + } +}; + + /** Get a string representation for a #TokenType. */ const char* TokenTypeString(TokenType t); diff --git a/code/AssetLib/HMP/HMPLoader.h b/code/AssetLib/HMP/HMPLoader.h index 95ce0a9eb..4d5f5f22f 100644 --- a/code/AssetLib/HMP/HMPLoader.h +++ b/code/AssetLib/HMP/HMPLoader.h @@ -86,7 +86,7 @@ protected: // ------------------------------------------------------------------- /** Import a HMP4 file */ - void InternReadFile_HMP4(); + AI_WONT_RETURN void InternReadFile_HMP4() AI_WONT_RETURN_SUFFIX; // ------------------------------------------------------------------- /** Import a HMP5 file diff --git a/code/AssetLib/IFC/IFCUtil.cpp b/code/AssetLib/IFC/IFCUtil.cpp index 6cf104833..eb636d735 100644 --- a/code/AssetLib/IFC/IFCUtil.cpp +++ b/code/AssetLib/IFC/IFCUtil.cpp @@ -48,6 +48,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "AssetLib/IFC/IFCUtil.h" #include "Common/PolyTools.h" +#include "Geometry/GeometryUtils.h" #include "PostProcessing/ProcessHelper.h" namespace Assimp { @@ -235,7 +236,7 @@ IfcVector3 TempMesh::ComputeLastPolygonNormal(bool normalize) const { struct CompareVector { bool operator () (const IfcVector3& a, const IfcVector3& b) const { IfcVector3 d = a - b; - IfcFloat eps = ai_epsilon; + constexpr IfcFloat eps = ai_epsilon; return d.x < -eps || (std::abs(d.x) < eps && d.y < -eps) || (std::abs(d.x) < eps && std::abs(d.y) < eps && d.z < -eps); } }; diff --git a/code/AssetLib/LWO/LWOBLoader.cpp b/code/AssetLib/LWO/LWOBLoader.cpp index a61e49a7f..e49adcf98 100644 --- a/code/AssetLib/LWO/LWOBLoader.cpp +++ b/code/AssetLib/LWO/LWOBLoader.cpp @@ -65,7 +65,6 @@ void LWOImporter::LoadLWOBFile() if (mFileBuffer + head.length > end) { throw DeadlyImportError("LWOB: Invalid chunk length"); - break; } uint8_t* const next = mFileBuffer+head.length; switch (head.type) diff --git a/code/AssetLib/LWO/LWOLoader.cpp b/code/AssetLib/LWO/LWOLoader.cpp index 1bf39b2da..7e93b65f8 100644 --- a/code/AssetLib/LWO/LWOLoader.cpp +++ b/code/AssetLib/LWO/LWOLoader.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, @@ -51,6 +49,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "AssetLib/LWO/LWOLoader.h" #include "PostProcessing/ConvertToLHProcess.h" #include "PostProcessing/ProcessHelper.h" +#include "Geometry/GeometryUtils.h" #include #include @@ -528,7 +527,6 @@ void LWOImporter::ComputeNormals(aiMesh *mesh, const std::vector & continue; vNormals += v; } - mesh->mNormals[idx] = vNormals.Normalize(); } } } @@ -549,7 +547,6 @@ void LWOImporter::ComputeNormals(aiMesh *mesh, const std::vector & const aiVector3D &v = faceNormals[*a]; vNormals += v; } - vNormals.Normalize(); for (std::vector::const_iterator a = poResult.begin(); a != poResult.end(); ++a) { mesh->mNormals[*a] = vNormals; vertexDone[*a] = true; @@ -557,6 +554,7 @@ void LWOImporter::ComputeNormals(aiMesh *mesh, const std::vector & } } } + GeometryUtils::normalizeVectorArray(mesh->mNormals, mesh->mNormals, mesh->mNumVertices); } // ------------------------------------------------------------------------------------------------ @@ -1486,7 +1484,6 @@ void LWOImporter::LoadLWO2File() { if (mFileBuffer + head.length > end) { throw DeadlyImportError("LWO2: Chunk length points behind the file"); - break; } uint8_t *const next = mFileBuffer + head.length; mFileBuffer += bufOffset; diff --git a/code/AssetLib/MD5/MD5Parser.h b/code/AssetLib/MD5/MD5Parser.h index bb4843cf9..ad7367e2a 100644 --- a/code/AssetLib/MD5/MD5Parser.h +++ b/code/AssetLib/MD5/MD5Parser.h @@ -365,9 +365,7 @@ public: static void ReportWarning (const char* warn, unsigned int line); - void ReportError (const char* error) { - return ReportError(error, lineNumber); - } + AI_WONT_RETURN void ReportError (const char* error) AI_WONT_RETURN_SUFFIX; void ReportWarning (const char* warn) { return ReportWarning(warn, lineNumber); @@ -404,6 +402,9 @@ private: unsigned int lineNumber; }; +inline void MD5Parser::ReportError(const char* error) { + ReportError(error, lineNumber); +} // ------------------------------------------------------------------- inline bool MD5Parser::SkipLine(const char* in, const char** out) { ++lineNumber; diff --git a/code/AssetLib/MDL/MDLLoader.h b/code/AssetLib/MDL/MDLLoader.h index b7d87e88d..433100938 100644 --- a/code/AssetLib/MDL/MDLLoader.h +++ b/code/AssetLib/MDL/MDLLoader.h @@ -139,7 +139,7 @@ protected: // ------------------------------------------------------------------- /** Import a CS:S/HL2 MDL file (not fully implemented) */ - void InternReadFile_HL2( ); + AI_WONT_RETURN void InternReadFile_HL2( ) AI_WONT_RETURN_SUFFIX; // ------------------------------------------------------------------- /** Check whether a given position is inside the valid range diff --git a/code/AssetLib/MMD/MMDPmxParser.h b/code/AssetLib/MMD/MMDPmxParser.h index f2e387975..424fc725a 100644 --- a/code/AssetLib/MMD/MMDPmxParser.h +++ b/code/AssetLib/MMD/MMDPmxParser.h @@ -46,6 +46,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include +#include #include "MMDCpp14.h" namespace pmx @@ -730,7 +731,7 @@ namespace pmx std::unique_ptr anchers; int pin_vertex_count; std::unique_ptr pin_vertices; - void Read(std::istream *stream, PmxSetting *setting); + AI_WONT_RETURN void Read(std::istream *stream, PmxSetting *setting) AI_WONT_RETURN_SUFFIX; }; class PmxModel diff --git a/code/AssetLib/Obj/ObjFileImporter.cpp b/code/AssetLib/Obj/ObjFileImporter.cpp index 189757815..cf4515794 100644 --- a/code/AssetLib/Obj/ObjFileImporter.cpp +++ b/code/AssetLib/Obj/ObjFileImporter.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2020, assimp team +Copyright (c) 2006-2023, assimp team All rights reserved. @@ -84,7 +84,6 @@ ObjFileImporter::ObjFileImporter() : // Destructor. ObjFileImporter::~ObjFileImporter() { delete m_pRootObject; - m_pRootObject = nullptr; } // ------------------------------------------------------------------------------------------------ @@ -270,7 +269,7 @@ aiNode *ObjFileImporter::createNodes(const ObjFile::Model *pModel, const ObjFile for (size_t i = 0; i < pObject->m_Meshes.size(); ++i) { unsigned int meshId = pObject->m_Meshes[i]; aiMesh *pMesh = createTopology(pModel, pObject, meshId); - if (pMesh) { + if (pMesh != nullptr) { if (pMesh->mNumFaces > 0) { MeshArray.push_back(pMesh); } else { @@ -324,14 +323,13 @@ aiMesh *ObjFileImporter::createTopology(const ObjFile::Model *pModel, const ObjF return nullptr; } - std::unique_ptr pMesh(new aiMesh); + aiMesh *pMesh = new aiMesh; if (!pObjMesh->m_name.empty()) { pMesh->mName.Set(pObjMesh->m_name); } for (size_t index = 0; index < pObjMesh->m_Faces.size(); index++) { const ObjFile::Face *inp = pObjMesh->m_Faces[index]; - //ai_assert(nullptr != inp); if (inp->mPrimitiveType == aiPrimitiveType_LINE) { pMesh->mNumFaces += static_cast(inp->m_vertices.size() - 1); @@ -387,9 +385,9 @@ aiMesh *ObjFileImporter::createTopology(const ObjFile::Model *pModel, const ObjF } // Create mesh vertices - createVertexArray(pModel, pData, meshIndex, pMesh.get(), uiIdxCount); + createVertexArray(pModel, pData, meshIndex, pMesh, uiIdxCount); - return pMesh.release(); + return pMesh; } // ------------------------------------------------------------------------------------------------ diff --git a/code/AssetLib/Obj/ObjFileParser.cpp b/code/AssetLib/Obj/ObjFileParser.cpp index c7121083a..ed416dc93 100644 --- a/code/AssetLib/Obj/ObjFileParser.cpp +++ b/code/AssetLib/Obj/ObjFileParser.cpp @@ -236,7 +236,7 @@ void ObjFileParser::parseFile(IOStreamBuffer &streamBuffer) { getNameNoSpace(m_DataIt, m_DataItEnd, name); insideCstype = name == "cstype"; goto pf_skip_line; - } break; + } default: { pf_skip_line: diff --git a/code/AssetLib/Ogre/OgreXmlSerializer.cpp b/code/AssetLib/Ogre/OgreXmlSerializer.cpp index a8faaec34..8a1b88510 100644 --- a/code/AssetLib/Ogre/OgreXmlSerializer.cpp +++ b/code/AssetLib/Ogre/OgreXmlSerializer.cpp @@ -57,7 +57,7 @@ namespace Assimp { namespace Ogre { //AI_WONT_RETURN void ThrowAttibuteError(const XmlParser *reader, const std::string &name, const std::string &error = "") AI_WONT_RETURN_SUFFIX; - +AI_WONT_RETURN void ThrowAttibuteError(const std::string &nodeName, const std::string &name, const std::string &error) AI_WONT_RETURN_SUFFIX; AI_WONT_RETURN void ThrowAttibuteError(const std::string &nodeName, const std::string &name, const std::string &error) { if (!error.empty()) { throw DeadlyImportError(error, " in node '", nodeName, "' and attribute '", name, "'"); @@ -128,7 +128,6 @@ bool OgreXmlSerializer::ReadAttribute(XmlNode &xmlNode, const char *name) } ThrowAttibuteError(xmlNode.name(), name, "Boolean value is expected to be 'true' or 'false', encountered '" + value + "'"); - return false; } // Mesh XML constants diff --git a/code/AssetLib/OpenGEX/OpenGEXImporter.cpp b/code/AssetLib/OpenGEX/OpenGEXImporter.cpp index 1bd981656..16268ead5 100644 --- a/code/AssetLib/OpenGEX/OpenGEXImporter.cpp +++ b/code/AssetLib/OpenGEX/OpenGEXImporter.cpp @@ -460,14 +460,12 @@ void OpenGEXImporter::handleMetricNode(DDLNode *node, aiScene * /*pScene*/) { void OpenGEXImporter::handleNameNode(DDLNode *node, aiScene * /*pScene*/) { if (nullptr == m_currentNode) { throw DeadlyImportError("No current node for name."); - return; } Value *val(node->getValue()); if (nullptr != val) { if (Value::ValueType::ddl_string != val->m_type) { throw DeadlyImportError("OpenGEX: invalid data type for value in node name."); - return; } const std::string name(val->getString()); @@ -508,7 +506,6 @@ static void getRefNames(DDLNode *node, std::vector &names) { void OpenGEXImporter::handleObjectRefNode(DDLNode *node, aiScene * /*pScene*/) { if (nullptr == m_currentNode) { throw DeadlyImportError("No parent node for name."); - return; } std::vector objRefNames; @@ -532,7 +529,6 @@ void OpenGEXImporter::handleObjectRefNode(DDLNode *node, aiScene * /*pScene*/) { void OpenGEXImporter::handleMaterialRefNode(ODDLParser::DDLNode *node, aiScene * /*pScene*/) { if (nullptr == m_currentNode) { throw DeadlyImportError("No parent node for name."); - return; } std::vector matRefNames; @@ -672,14 +668,12 @@ static void setMatrix(aiNode *node, DataArrayList *transformData) { void OpenGEXImporter::handleTransformNode(ODDLParser::DDLNode *node, aiScene * /*pScene*/) { if (nullptr == m_currentNode) { throw DeadlyImportError("No parent node for name."); - return; } DataArrayList *transformData(node->getDataArrayList()); if (nullptr != transformData) { if (transformData->m_numItems != 16) { throw DeadlyImportError("Invalid number of data for transform matrix."); - return; } setMatrix(m_currentNode, transformData); } @@ -835,7 +829,6 @@ static void copyColor4DArray(size_t numItems, DataArrayList *vaList, aiColor4D * void OpenGEXImporter::handleVertexArrayNode(ODDLParser::DDLNode *node, aiScene * /*pScene*/) { if (nullptr == node) { throw DeadlyImportError("No parent node for name."); - return; } Property *prop = node->getProperties(); @@ -876,12 +869,10 @@ void OpenGEXImporter::handleVertexArrayNode(ODDLParser::DDLNode *node, aiScene * void OpenGEXImporter::handleIndexArrayNode(ODDLParser::DDLNode *node, aiScene * /*pScene*/) { if (nullptr == node) { throw DeadlyImportError("No parent node for name."); - return; } if (nullptr == m_currentMesh) { throw DeadlyImportError("No current mesh for index data found."); - return; } DataArrayList *vaList = node->getDataArrayList(); diff --git a/code/AssetLib/Q3D/Q3DLoader.cpp b/code/AssetLib/Q3D/Q3DLoader.cpp index a91788c78..22d1065de 100644 --- a/code/AssetLib/Q3D/Q3DLoader.cpp +++ b/code/AssetLib/Q3D/Q3DLoader.cpp @@ -382,11 +382,10 @@ void Q3DImporter::InternReadFile(const std::string &pFile, // TODO goto outer; - } break; + } default: throw DeadlyImportError("Quick3D: Unknown chunk"); - break; }; } outer: diff --git a/code/AssetLib/Raw/RawLoader.h b/code/AssetLib/Raw/RawLoader.h index 6e4c4d110..54314f728 100644 --- a/code/AssetLib/Raw/RawLoader.h +++ b/code/AssetLib/Raw/RawLoader.h @@ -58,7 +58,7 @@ namespace Assimp { class RAWImporter : public BaseImporter { public: RAWImporter(); - ~RAWImporter(); + ~RAWImporter() override; // ------------------------------------------------------------------- /** 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 323a69a00..9f299180b 100644 --- a/code/AssetLib/SIB/SIBImporter.cpp +++ b/code/AssetLib/SIB/SIBImporter.cpp @@ -85,7 +85,7 @@ static const aiImporterDesc desc = { struct SIBChunk { uint32_t Tag; uint32_t Size; -} PACK_STRUCT; +}; enum { POS, diff --git a/code/AssetLib/Unreal/UnrealLoader.h b/code/AssetLib/Unreal/UnrealLoader.h index a931a86dd..fda784cfb 100644 --- a/code/AssetLib/Unreal/UnrealLoader.h +++ b/code/AssetLib/Unreal/UnrealLoader.h @@ -56,7 +56,7 @@ namespace Assimp { class UnrealImporter : public BaseImporter { public: UnrealImporter(); - ~UnrealImporter(); + ~UnrealImporter() override; // ------------------------------------------------------------------- /** @brief Returns whether we can handle the format of the given file diff --git a/code/AssetLib/X/XFileImporter.cpp b/code/AssetLib/X/XFileImporter.cpp index 32865e8a8..1474ad808 100644 --- a/code/AssetLib/X/XFileImporter.cpp +++ b/code/AssetLib/X/XFileImporter.cpp @@ -578,7 +578,7 @@ void XFileImporter::ConvertMaterials( aiScene* pScene, std::vectormMaterials[b]->Get( AI_MATKEY_NAME, name); if( strcmp( name.C_Str(), oldMat.mName.data()) == 0 ) { - oldMat.sceneIndex = a; + oldMat.sceneIndex = b; break; } } diff --git a/code/AssetLib/X/XFileParser.cpp b/code/AssetLib/X/XFileParser.cpp index 8786c3166..770c75a77 100644 --- a/code/AssetLib/X/XFileParser.cpp +++ b/code/AssetLib/X/XFileParser.cpp @@ -839,7 +839,6 @@ void XFileParser::ParseDataObjectAnimationKey(AnimBone *pAnimBone) { default: ThrowException("Unknown key type ", keyType, " in animation."); - break; } // end switch // key separator diff --git a/code/AssetLib/X3D/X3DExporter.hpp b/code/AssetLib/X3D/X3DExporter.hpp index e77aa6877..babf552dd 100644 --- a/code/AssetLib/X3D/X3DExporter.hpp +++ b/code/AssetLib/X3D/X3DExporter.hpp @@ -58,8 +58,6 @@ class X3DExporter { Value(value) { // empty } - - SAttribute(SAttribute &&rhs) AI_NO_EXCEPT = default; }; /***********************************************/ diff --git a/code/AssetLib/X3D/X3DImporter.hpp b/code/AssetLib/X3D/X3DImporter.hpp index 8852b71ec..705a2472e 100644 --- a/code/AssetLib/X3D/X3DImporter.hpp +++ b/code/AssetLib/X3D/X3DImporter.hpp @@ -55,6 +55,18 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include namespace Assimp { +AI_WONT_RETURN inline void Throw_ArgOutOfRange(const std::string &argument) AI_WONT_RETURN_SUFFIX; +AI_WONT_RETURN inline void Throw_CloseNotFound(const std::string &node) AI_WONT_RETURN_SUFFIX; +AI_WONT_RETURN inline void Throw_ConvertFail_Str2ArrF(const std::string &nodeName, const std::string &pAttrValue) AI_WONT_RETURN_SUFFIX; +AI_WONT_RETURN inline void Throw_ConvertFail_Str2ArrD(const std::string &nodeName, const std::string &pAttrValue) AI_WONT_RETURN_SUFFIX; +AI_WONT_RETURN inline void Throw_ConvertFail_Str2ArrB(const std::string &nodeName, const std::string &pAttrValue) AI_WONT_RETURN_SUFFIX; +AI_WONT_RETURN inline void Throw_ConvertFail_Str2ArrI(const std::string &nodeName, const std::string &pAttrValue) AI_WONT_RETURN_SUFFIX; +AI_WONT_RETURN inline void Throw_DEF_And_USE(const std::string &nodeName) AI_WONT_RETURN_SUFFIX; +AI_WONT_RETURN inline void Throw_IncorrectAttr(const std::string &nodeName, const std::string &pAttrName) AI_WONT_RETURN_SUFFIX; +AI_WONT_RETURN inline void Throw_IncorrectAttrValue(const std::string &nodeName, const std::string &pAttrName) AI_WONT_RETURN_SUFFIX; +AI_WONT_RETURN inline void Throw_MoreThanOnceDefined(const std::string &nodeName, const std::string &pNodeType, const std::string &pDescription) AI_WONT_RETURN_SUFFIX; +AI_WONT_RETURN inline void Throw_TagCountIncorrect(const std::string &pNode) AI_WONT_RETURN_SUFFIX; +AI_WONT_RETURN inline void Throw_USE_NotFound(const std::string &nodeName, const std::string &pAttrValue) AI_WONT_RETURN_SUFFIX; inline void Throw_ArgOutOfRange(const std::string &argument) { throw DeadlyImportError("Argument value is out of range for: \"" + argument + "\"."); diff --git a/code/AssetLib/X3D/X3DXmlHelper.cpp b/code/AssetLib/X3D/X3DXmlHelper.cpp index ff24b74b3..7ed2e8237 100644 --- a/code/AssetLib/X3D/X3DXmlHelper.cpp +++ b/code/AssetLib/X3D/X3DXmlHelper.cpp @@ -12,7 +12,6 @@ bool X3DXmlHelper::getColor3DAttribute(XmlNode &node, const char *attributeName, tokenize(val, values, " "); if (values.size() != 3) { Throw_ConvertFail_Str2ArrF(node.name(), attributeName); - return false; } auto it = values.begin(); color.r = stof(*it++); @@ -30,7 +29,6 @@ bool X3DXmlHelper::getVector2DAttribute(XmlNode &node, const char *attributeName tokenize(val, values, " "); if (values.size() != 2) { Throw_ConvertFail_Str2ArrF(node.name(), attributeName); - return false; } auto it = values.begin(); color.x = stof(*it++); @@ -47,7 +45,6 @@ bool X3DXmlHelper::getVector3DAttribute(XmlNode &node, const char *attributeName tokenize(val, values, " "); if (values.size() != 3) { Throw_ConvertFail_Str2ArrF(node.name(), attributeName); - return false; } auto it = values.begin(); color.x = stof(*it++); diff --git a/code/AssetLib/glTF2/glTF2Asset.h b/code/AssetLib/glTF2/glTF2Asset.h index 9bb821afc..15a8fcc87 100644 --- a/code/AssetLib/glTF2/glTF2Asset.h +++ b/code/AssetLib/glTF2/glTF2Asset.h @@ -484,7 +484,7 @@ private: public: Buffer(); - ~Buffer(); + ~Buffer() override; void Read(Value &obj, Asset &r); diff --git a/code/CMakeLists.txt b/code/CMakeLists.txt index 6f74823df..fad39a216 100644 --- a/code/CMakeLists.txt +++ b/code/CMakeLists.txt @@ -194,6 +194,8 @@ SET( Common_SRCS Common/ScenePreprocessor.cpp Common/ScenePreprocessor.h Common/SkeletonMeshBuilder.cpp + Common/StackAllocator.h + Common/StackAllocator.inl Common/StandardShapes.cpp Common/TargetAnimation.cpp Common/TargetAnimation.h @@ -1211,7 +1213,6 @@ IF (ASSIMP_WARNINGS_AS_ERRORS) -Wno-undef -Wno-suggest-destructor-override -Wno-suggest-override - -Wno-inconsistent-missing-destructor-override -Wno-zero-as-null-pointer-constant -Wno-global-constructors -Wno-exit-time-destructors @@ -1235,19 +1236,14 @@ IF (ASSIMP_WARNINGS_AS_ERRORS) -Wno-header-hygiene -Wno-tautological-value-range-compare -Wno-tautological-type-limit-compare - -Wno-missing-noreturn -Wno-missing-variable-declarations -Wno-extra-semi -Wno-nonportable-system-include-path -Wno-undefined-reinterpret-cast -Wno-shift-sign-overflow - -Wno-deprecated-copy-with-user-provided-dtor - -Wno-deprecated-copy-with-dtor -Wno-deprecated -Wno-format-nonliteral -Wno-comma - -Wno-unreachable-code-break - -Wno-unreachable-code-return -Wno-implicit-fallthrough -Wno-unused-template -Wno-undefined-func-template diff --git a/code/Common/SceneCombiner.cpp b/code/Common/SceneCombiner.cpp index 0f5386b26..0188f5dea 100644 --- a/code/Common/SceneCombiner.cpp +++ b/code/Common/SceneCombiner.cpp @@ -1349,6 +1349,9 @@ void SceneCombiner::Copy(aiMetadata **_dest, const aiMetadata *src) { case AI_AIVECTOR3D: out.mData = new aiVector3D(*static_cast(in.mData)); break; + case AI_AIMETADATA: + out.mData = new aiMetadata(*static_cast(in.mData)); + break; default: ai_assert(false); break; diff --git a/code/Common/StackAllocator.h b/code/Common/StackAllocator.h new file mode 100644 index 000000000..191010cac --- /dev/null +++ b/code/Common/StackAllocator.h @@ -0,0 +1,92 @@ +/* +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, +with or without modification, are permitted provided that the +following conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +---------------------------------------------------------------------- +*/ + +/** @file StackAllocator.h + * @brief A very bare-bone allocator class that is suitable when + * allocating many small objects, e.g. during parsing. + * Individual objects are not freed, instead only the whole memory + * can be deallocated. + */ +#ifndef AI_STACK_ALLOCATOR_H_INC +#define AI_STACK_ALLOCATOR_H_INC + +#include +#include +#include + +namespace Assimp { + +/** @brief A very bare-bone allocator class that is suitable when + * allocating many small objects, e.g. during parsing. + * Individual objects are not freed, instead only the whole memory + * can be deallocated. +*/ +class StackAllocator { +public: + /// @brief Constructs the allocator + inline StackAllocator(); + /// @brief Destructs the allocator and frees all memory + inline ~StackAllocator(); + + // non copyable + StackAllocator(const StackAllocator &) = delete; + StackAllocator &operator=(const StackAllocator &) = delete; + + /// @brief Returns a pointer to byteSize bytes of heap memory that persists + /// for the lifetime of the allocator (or until FreeAll is called). + inline void *Allocate(size_t byteSize); + + /// @brief Releases all the memory owned by this allocator. + // Memory provided through function Allocate is not valid anymore after this function has been called. + inline void FreeAll(); + +private: + constexpr const static size_t g_maxBytesPerBlock = 64 * 1024 * 1024; // The maximum size (in bytes) of a block + constexpr const static size_t g_startBytesPerBlock = 16 * 1024; // Size of the first block. Next blocks will double in size until maximum size of g_maxBytesPerBlock + size_t m_blockAllocationSize = g_startBytesPerBlock; // Block size of the current block + size_t m_subIndex = g_maxBytesPerBlock; // The current byte offset in the current block + std::vector m_storageBlocks; // A list of blocks +}; + +} // namespace Assimp + +#include "StackAllocator.inl" + +#endif // include guard diff --git a/code/Common/StackAllocator.inl b/code/Common/StackAllocator.inl new file mode 100644 index 000000000..2c3164ca7 --- /dev/null +++ b/code/Common/StackAllocator.inl @@ -0,0 +1,82 @@ +/* +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, +with or without modification, are permitted provided that the +following conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +---------------------------------------------------------------------- +*/ + +#include "StackAllocator.h" +#include + +using namespace Assimp; + +inline StackAllocator::StackAllocator() { +} + +inline StackAllocator::~StackAllocator() { + FreeAll(); +} + +inline void *StackAllocator::Allocate(size_t byteSize) { + if (m_subIndex + byteSize > m_blockAllocationSize) // start a new block + { + // double block size every time, up to maximum of g_maxBytesPerBlock. + // Block size must be at least as large as byteSize, but we want to use this for small allocations anyway. + m_blockAllocationSize = std::max(std::min(m_blockAllocationSize * 2, g_maxBytesPerBlock), byteSize); + uint8_t *data = new uint8_t[m_blockAllocationSize]; + m_storageBlocks.emplace_back(data); + m_subIndex = byteSize; + return data; + } + + uint8_t *data = m_storageBlocks.back(); + data += m_subIndex; + m_subIndex += byteSize; + + return data; +} + +inline void StackAllocator::FreeAll() { + for (size_t i = 0; i < m_storageBlocks.size(); i++) { + delete [] m_storageBlocks[i]; + } + std::vector empty; + m_storageBlocks.swap(empty); + // start over: + m_blockAllocationSize = g_startBytesPerBlock; + m_subIndex = g_maxBytesPerBlock; +} diff --git a/code/Common/ZipArchiveIOSystem.cpp b/code/Common/ZipArchiveIOSystem.cpp index d0c2f3204..51a250810 100644 --- a/code/Common/ZipArchiveIOSystem.cpp +++ b/code/Common/ZipArchiveIOSystem.cpp @@ -68,7 +68,7 @@ class ZipFile : public IOStream { public: std::string m_Filename; - virtual ~ZipFile(); + virtual ~ZipFile() override; // IOStream interface size_t Read(void *pvBuffer, size_t pSize, size_t pCount) override; diff --git a/code/Geometry/GeometryUtils.cpp b/code/Geometry/GeometryUtils.cpp index ab735aa6e..cec1e74c5 100644 --- a/code/Geometry/GeometryUtils.cpp +++ b/code/Geometry/GeometryUtils.cpp @@ -45,35 +45,59 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. namespace Assimp { +// ------------------------------------------------------------------------------------------------ ai_real GeometryUtils::heron( ai_real a, ai_real b, ai_real c ) { - ai_real s = (a + b + c) / 2; - ai_real area = pow((s * ( s - a ) * ( s - b ) * ( s - c ) ), (ai_real)0.5 ); + const ai_real s = (a + b + c) / 2; + const ai_real area = pow((s * ( s - a ) * ( s - b ) * ( s - c ) ), (ai_real)0.5 ); return area; } -ai_real GeometryUtils::distance3D( const aiVector3D &vA, aiVector3D &vB ) { +// ------------------------------------------------------------------------------------------------ +ai_real GeometryUtils::distance3D( const aiVector3D &vA, const aiVector3D &vB ) { const ai_real lx = ( vB.x - vA.x ); const ai_real ly = ( vB.y - vA.y ); const ai_real lz = ( vB.z - vA.z ); - ai_real a = lx*lx + ly*ly + lz*lz; - ai_real d = pow( a, (ai_real)0.5 ); + const ai_real a = lx*lx + ly*ly + lz*lz; + const ai_real d = pow( a, (ai_real)0.5 ); return d; } +// ------------------------------------------------------------------------------------------------ ai_real GeometryUtils::calculateAreaOfTriangle( const aiFace& face, aiMesh* mesh ) { ai_real area = 0; - aiVector3D vA( mesh->mVertices[ face.mIndices[ 0 ] ] ); - aiVector3D vB( mesh->mVertices[ face.mIndices[ 1 ] ] ); - aiVector3D vC( mesh->mVertices[ face.mIndices[ 2 ] ] ); + const aiVector3D vA( mesh->mVertices[ face.mIndices[ 0 ] ] ); + const aiVector3D vB( mesh->mVertices[ face.mIndices[ 1 ] ] ); + const aiVector3D vC( mesh->mVertices[ face.mIndices[ 2 ] ] ); - ai_real a( distance3D( vA, vB ) ); - ai_real b( distance3D( vB, vC ) ); - ai_real c( distance3D( vC, vA ) ); + const ai_real a = distance3D( vA, vB ); + const ai_real b = distance3D( vB, vC ); + const ai_real c = distance3D( vC, vA ); area = heron( a, b, c ); return area; } +// ------------------------------------------------------------------------------------------------ +// Check whether a ray intersects a plane and find the intersection point +bool GeometryUtils::PlaneIntersect(const aiRay& ray, const aiVector3D& planePos, + const aiVector3D& planeNormal, aiVector3D& pos) { + const ai_real b = planeNormal * (planePos - ray.pos); + ai_real h = ray.dir * planeNormal; + if ((h < 10e-5 && h > -10e-5) || (h = b/h) < 0) + return false; + + pos = ray.pos + (ray.dir * h); + return true; +} + +// ------------------------------------------------------------------------------------------------ +void GeometryUtils::normalizeVectorArray(aiVector3D *vectorArrayIn, aiVector3D *vectorArrayOut, + size_t numVectors) { + for (size_t i=0; i #include #include -#include namespace Assimp { -/// The default class constructor. -ArmaturePopulate::ArmaturePopulate() = default; +static bool IsBoneNode(const aiString &bone_name, std::vector &bones) { + for (aiBone *bone : bones) { + if (bone->mName == bone_name) { + return true; + } + } -/// The class destructor. -ArmaturePopulate::~ArmaturePopulate() = default; + return false; +} bool ArmaturePopulate::IsActive(unsigned int pFlags) const { return (pFlags & aiProcess_PopulateArmatureData) != 0; @@ -70,7 +73,7 @@ void ArmaturePopulate::Execute(aiScene *out) { BuildBoneList(out->mRootNode, out->mRootNode, out, bones); BuildNodeList(out->mRootNode, nodes); - BuildBoneStack(out->mRootNode, out->mRootNode, out, bones, bone_stack, nodes); + BuildBoneStack(out->mRootNode, out, bones, bone_stack, nodes); ASSIMP_LOG_DEBUG("Bone stack size: ", bone_stack.size()); @@ -78,9 +81,8 @@ void ArmaturePopulate::Execute(aiScene *out) { aiBone *bone = kvp.first; aiNode *bone_node = kvp.second; ASSIMP_LOG_VERBOSE_DEBUG("active node lookup: ", bone->mName.C_Str()); + // lcl transform grab - done in generate_nodes :) - - // bone->mOffsetMatrix = bone_node->mTransformation; aiNode *armature = GetArmatureRoot(bone_node, bones); ai_assert(armature); @@ -159,8 +161,7 @@ void ArmaturePopulate::BuildNodeList(const aiNode *current_node, // A bone stack allows us to have multiple armatures, with the same bone names // A bone stack allows us also to retrieve bones true transform even with // duplicate names :) -void ArmaturePopulate::BuildBoneStack(aiNode *, - const aiNode *root_node, +void ArmaturePopulate::BuildBoneStack(const aiNode *root_node, const aiScene*, const std::vector &bones, std::map &bone_stack, @@ -196,8 +197,7 @@ void ArmaturePopulate::BuildBoneStack(aiNode *, // This is required to be detected for a bone initially, it will recurse up // until it cannot find another bone and return the node No known failure // points. (yet) -aiNode *ArmaturePopulate::GetArmatureRoot(aiNode *bone_node, - std::vector &bone_list) { +aiNode *ArmaturePopulate::GetArmatureRoot(aiNode *bone_node, std::vector &bone_list) { while (nullptr != bone_node) { if (!IsBoneNode(bone_node->mName, bone_list)) { ASSIMP_LOG_VERBOSE_DEBUG("GetArmatureRoot() Found valid armature: ", bone_node->mName.C_Str()); @@ -212,18 +212,6 @@ aiNode *ArmaturePopulate::GetArmatureRoot(aiNode *bone_node, return nullptr; } -// Simple IsBoneNode check if this could be a bone -bool ArmaturePopulate::IsBoneNode(const aiString &bone_name, - std::vector &bones) { - for (aiBone *bone : bones) { - if (bone->mName == bone_name) { - return true; - } - } - - return false; -} - // Pop this node by name from the stack if found // Used in multiple armature situations with duplicate node / bone names // Known flaw: cannot have nodes with bone names, will be fixed in later release diff --git a/code/PostProcessing/ArmaturePopulate.h b/code/PostProcessing/ArmaturePopulate.h index 530932f48..52d3adfef 100644 --- a/code/PostProcessing/ArmaturePopulate.h +++ b/code/PostProcessing/ArmaturePopulate.h @@ -69,10 +69,10 @@ namespace Assimp { class ASSIMP_API ArmaturePopulate : public BaseProcess { public: /// The default class constructor. - ArmaturePopulate(); + ArmaturePopulate() = default; /// The class destructor. - virtual ~ArmaturePopulate(); + virtual ~ArmaturePopulate() = default; /// Overwritten, @see BaseProcess virtual bool IsActive( unsigned int pFlags ) const; @@ -86,9 +86,6 @@ public: static aiNode *GetArmatureRoot(aiNode *bone_node, std::vector &bone_list); - static bool IsBoneNode(const aiString &bone_name, - std::vector &bones); - static aiNode *GetNodeFromStack(const aiString &node_name, std::vector &nodes); @@ -99,7 +96,7 @@ public: const aiScene *scene, std::vector &bones); - static void BuildBoneStack(aiNode *current_node, const aiNode *root_node, + static void BuildBoneStack(const aiNode *root_node, const aiScene *scene, const std::vector &bones, std::map &bone_stack, @@ -108,5 +105,4 @@ public: } // Namespace Assimp - #endif // SCALE_PROCESS_H_ diff --git a/code/PostProcessing/ComputeUVMappingProcess.cpp b/code/PostProcessing/ComputeUVMappingProcess.cpp index a5472668b..f75dc5952 100644 --- a/code/PostProcessing/ComputeUVMappingProcess.cpp +++ b/code/PostProcessing/ComputeUVMappingProcess.cpp @@ -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, @@ -42,8 +41,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. /** @file GenUVCoords step */ - #include "ComputeUVMappingProcess.h" +#include "Geometry/GeometryUtils.h" #include "ProcessHelper.h" #include @@ -51,39 +50,25 @@ using namespace Assimp; namespace { - const static aiVector3D base_axis_y(0.0,1.0,0.0); - const static aiVector3D base_axis_x(1.0,0.0,0.0); - const static aiVector3D base_axis_z(0.0,0.0,1.0); - const static ai_real angle_epsilon = ai_real( 0.95 ); -} +const static aiVector3D base_axis_y(0.0, 1.0, 0.0); +const static aiVector3D base_axis_x(1.0, 0.0, 0.0); +const static aiVector3D base_axis_z(0.0, 0.0, 1.0); +const static ai_real angle_epsilon = ai_real(0.95); +} // namespace // ------------------------------------------------------------------------------------------------ // Returns whether the processing step is present in the given flag field. -bool ComputeUVMappingProcess::IsActive( unsigned int pFlags) const -{ - return (pFlags & aiProcess_GenUVCoords) != 0; -} - -// ------------------------------------------------------------------------------------------------ -// Check whether a ray intersects a plane and find the intersection point -inline bool PlaneIntersect(const aiRay& ray, const aiVector3D& planePos, - const aiVector3D& planeNormal, aiVector3D& pos) -{ - const ai_real b = planeNormal * (planePos - ray.pos); - ai_real h = ray.dir * planeNormal; - if ((h < 10e-5 && h > -10e-5) || (h = b/h) < 0) - return false; - - pos = ray.pos + (ray.dir * h); - return true; +bool ComputeUVMappingProcess::IsActive(unsigned int pFlags) const { + return (pFlags & aiProcess_GenUVCoords) != 0; } // ------------------------------------------------------------------------------------------------ // Find the first empty UV channel in a mesh -inline unsigned int FindEmptyUVChannel (aiMesh* mesh) -{ - for (unsigned int m = 0; m < AI_MAX_NUMBER_OF_TEXTURECOORDS;++m) - if (!mesh->mTextureCoords[m])return m; +inline unsigned int FindEmptyUVChannel(aiMesh *mesh) { + for (unsigned int m = 0; m < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++m) + if (!mesh->mTextureCoords[m]) { + return m; + } ASSIMP_LOG_ERROR("Unable to compute UV coordinates, no free UV slot found"); return UINT_MAX; @@ -91,22 +76,22 @@ inline unsigned int FindEmptyUVChannel (aiMesh* mesh) // ------------------------------------------------------------------------------------------------ // Try to remove UV seams -void RemoveUVSeams (aiMesh* mesh, aiVector3D* out) -{ +void RemoveUVSeams(aiMesh *mesh, aiVector3D *out) { // TODO: just a very rough algorithm. I think it could be done // much easier, but I don't know how and am currently too tired to // to think about a better solution. - const static ai_real LOWER_LIMIT = ai_real( 0.1 ); - const static ai_real UPPER_LIMIT = ai_real( 0.9 ); + const static ai_real LOWER_LIMIT = ai_real(0.1); + const static ai_real UPPER_LIMIT = ai_real(0.9); - const static ai_real LOWER_EPSILON = ai_real( 10e-3 ); - const static ai_real UPPER_EPSILON = ai_real( 1.0-10e-3 ); + const static ai_real LOWER_EPSILON = ai_real(10e-3); + const static ai_real UPPER_EPSILON = ai_real(1.0 - 10e-3); - for (unsigned int fidx = 0; fidx < mesh->mNumFaces;++fidx) - { - const aiFace& face = mesh->mFaces[fidx]; - if (face.mNumIndices < 3) continue; // triangles and polygons only, please + for (unsigned int fidx = 0; fidx < mesh->mNumFaces; ++fidx) { + const aiFace &face = mesh->mFaces[fidx]; + if (face.mNumIndices < 3) { + continue; // triangles and polygons only, please + } unsigned int smallV = face.mNumIndices, large = smallV; bool zero = false, one = false, round_to_zero = false; @@ -115,20 +100,18 @@ void RemoveUVSeams (aiMesh* mesh, aiVector3D* out) // but the assumption that a face with at least one very small // on the one side and one very large U coord on the other side // lies on a UV seam should work for most cases. - for (unsigned int n = 0; n < face.mNumIndices;++n) - { - if (out[face.mIndices[n]].x < LOWER_LIMIT) - { + for (unsigned int n = 0; n < face.mNumIndices; ++n) { + if (out[face.mIndices[n]].x < LOWER_LIMIT) { smallV = n; // If we have a U value very close to 0 we can't // round the others to 0, too. if (out[face.mIndices[n]].x <= LOWER_EPSILON) zero = true; - else round_to_zero = true; + else + round_to_zero = true; } - if (out[face.mIndices[n]].x > UPPER_LIMIT) - { + if (out[face.mIndices[n]].x > UPPER_LIMIT) { large = n; // If we have a U value very close to 1 we can't @@ -137,10 +120,8 @@ void RemoveUVSeams (aiMesh* mesh, aiVector3D* out) one = true; } } - if (smallV != face.mNumIndices && large != face.mNumIndices) - { - for (unsigned int n = 0; n < face.mNumIndices;++n) - { + if (smallV != face.mNumIndices && large != face.mNumIndices) { + for (unsigned int n = 0; n < face.mNumIndices; ++n) { // If the u value is over the upper limit and no other u // value of that face is 0, round it to 0 if (out[face.mIndices[n]].x > UPPER_LIMIT && !zero) @@ -156,9 +137,8 @@ void RemoveUVSeams (aiMesh* mesh, aiVector3D* out) // Due to numerical inaccuracies one U coord becomes 0, the // other 1. But we do still have a third UV coord to determine // to which side we must round to. - else if (one && zero) - { - if (round_to_zero && out[face.mIndices[n]].x >= UPPER_EPSILON) + else if (one && zero) { + if (round_to_zero && out[face.mIndices[n]].x >= UPPER_EPSILON) out[face.mIndices[n]].x = 0.0; else if (!round_to_zero && out[face.mIndices[n]].x <= LOWER_EPSILON) out[face.mIndices[n]].x = 1.0; @@ -169,8 +149,7 @@ void RemoveUVSeams (aiMesh* mesh, aiVector3D* out) } // ------------------------------------------------------------------------------------------------ -void ComputeUVMappingProcess::ComputeSphereMapping(aiMesh* mesh,const aiVector3D& axis, aiVector3D* out) -{ +void ComputeUVMappingProcess::ComputeSphereMapping(aiMesh *mesh, const aiVector3D &axis, aiVector3D *out) { aiVector3D center, min, max; FindMeshCenter(mesh, center, min, max); @@ -178,7 +157,7 @@ void ComputeUVMappingProcess::ComputeSphereMapping(aiMesh* mesh,const aiVector3D // currently the mapping axis will always be one of x,y,z, except if the // PretransformVertices step is used (it transforms the meshes into worldspace, // thus changing the mapping axis) - if (axis * base_axis_x >= angle_epsilon) { + if (axis * base_axis_x >= angle_epsilon) { // For each point get a normalized projection vector in the sphere, // get its longitude and latitude and map them to their respective @@ -192,58 +171,54 @@ void ComputeUVMappingProcess::ComputeSphereMapping(aiMesh* mesh,const aiVector3D // Thus we can derive: // lat = arcsin (z) // lon = arctan (y/x) - for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt) { - const aiVector3D diff = (mesh->mVertices[pnt]-center).Normalize(); - out[pnt] = aiVector3D((std::atan2(diff.z, diff.y) + AI_MATH_PI_F ) / AI_MATH_TWO_PI_F, - (std::asin (diff.x) + AI_MATH_HALF_PI_F) / AI_MATH_PI_F, 0.0); + for (unsigned int pnt = 0; pnt < mesh->mNumVertices; ++pnt) { + const aiVector3D diff = (mesh->mVertices[pnt] - center).Normalize(); + out[pnt] = aiVector3D((std::atan2(diff.z, diff.y) + AI_MATH_PI_F) / AI_MATH_TWO_PI_F, + (std::asin(diff.x) + AI_MATH_HALF_PI_F) / AI_MATH_PI_F, 0.0); } - } - else if (axis * base_axis_y >= angle_epsilon) { + } else if (axis * base_axis_y >= angle_epsilon) { // ... just the same again - for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt) { - const aiVector3D diff = (mesh->mVertices[pnt]-center).Normalize(); - out[pnt] = aiVector3D((std::atan2(diff.x, diff.z) + AI_MATH_PI_F ) / AI_MATH_TWO_PI_F, - (std::asin (diff.y) + AI_MATH_HALF_PI_F) / AI_MATH_PI_F, 0.0); + for (unsigned int pnt = 0; pnt < mesh->mNumVertices; ++pnt) { + const aiVector3D diff = (mesh->mVertices[pnt] - center).Normalize(); + out[pnt] = aiVector3D((std::atan2(diff.x, diff.z) + AI_MATH_PI_F) / AI_MATH_TWO_PI_F, + (std::asin(diff.y) + AI_MATH_HALF_PI_F) / AI_MATH_PI_F, 0.0); } - } - else if (axis * base_axis_z >= angle_epsilon) { + } else if (axis * base_axis_z >= angle_epsilon) { // ... just the same again - for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt) { - const aiVector3D diff = (mesh->mVertices[pnt]-center).Normalize(); - out[pnt] = aiVector3D((std::atan2(diff.y, diff.x) + AI_MATH_PI_F ) / AI_MATH_TWO_PI_F, - (std::asin (diff.z) + AI_MATH_HALF_PI_F) / AI_MATH_PI_F, 0.0); + for (unsigned int pnt = 0; pnt < mesh->mNumVertices; ++pnt) { + const aiVector3D diff = (mesh->mVertices[pnt] - center).Normalize(); + out[pnt] = aiVector3D((std::atan2(diff.y, diff.x) + AI_MATH_PI_F) / AI_MATH_TWO_PI_F, + (std::asin(diff.z) + AI_MATH_HALF_PI_F) / AI_MATH_PI_F, 0.0); } } // slower code path in case the mapping axis is not one of the coordinate system axes - else { + else { aiMatrix4x4 mTrafo; - aiMatrix4x4::FromToMatrix(axis,base_axis_y,mTrafo); + aiMatrix4x4::FromToMatrix(axis, base_axis_y, mTrafo); // again the same, except we're applying a transformation now - for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt) { - const aiVector3D diff = ((mTrafo*mesh->mVertices[pnt])-center).Normalize(); - out[pnt] = aiVector3D((std::atan2(diff.y, diff.x) + AI_MATH_PI_F ) / AI_MATH_TWO_PI_F, - (std::asin(diff.z) + AI_MATH_HALF_PI_F) / AI_MATH_PI_F, 0.0); + for (unsigned int pnt = 0; pnt < mesh->mNumVertices; ++pnt) { + const aiVector3D diff = ((mTrafo * mesh->mVertices[pnt]) - center).Normalize(); + out[pnt] = aiVector3D((std::atan2(diff.y, diff.x) + AI_MATH_PI_F) / AI_MATH_TWO_PI_F, + (std::asin(diff.z) + AI_MATH_HALF_PI_F) / AI_MATH_PI_F, 0.0); } } - // Now find and remove UV seams. A seam occurs if a face has a tcoord // close to zero on the one side, and a tcoord close to one on the // other side. - RemoveUVSeams(mesh,out); + RemoveUVSeams(mesh, out); } // ------------------------------------------------------------------------------------------------ -void ComputeUVMappingProcess::ComputeCylinderMapping(aiMesh* mesh,const aiVector3D& axis, aiVector3D* out) -{ +void ComputeUVMappingProcess::ComputeCylinderMapping(aiMesh *mesh, const aiVector3D &axis, aiVector3D *out) { aiVector3D center, min, max; // If the axis is one of x,y,z run a faster code path. It's worth the extra effort ... // currently the mapping axis will always be one of x,y,z, except if the // PretransformVertices step is used (it transforms the meshes into worldspace, // thus changing the mapping axis) - if (axis * base_axis_x >= angle_epsilon) { + if (axis * base_axis_x >= angle_epsilon) { FindMeshCenter(mesh, center, min, max); const ai_real diff = max.x - min.x; @@ -251,116 +226,110 @@ void ComputeUVMappingProcess::ComputeCylinderMapping(aiMesh* mesh,const aiVector // directly to the texture V axis. The other axis is derived from // the angle between ( p.x - c.x, p.y - c.y ) and (1,0), where // 'c' is the center point of the mesh. - for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt) { - const aiVector3D& pos = mesh->mVertices[pnt]; - aiVector3D& uv = out[pnt]; + for (unsigned int pnt = 0; pnt < mesh->mNumVertices; ++pnt) { + const aiVector3D &pos = mesh->mVertices[pnt]; + aiVector3D &uv = out[pnt]; uv.y = (pos.x - min.x) / diff; - uv.x = (std::atan2( pos.z - center.z, pos.y - center.y) +(ai_real)AI_MATH_PI ) / (ai_real)AI_MATH_TWO_PI; + uv.x = (std::atan2(pos.z - center.z, pos.y - center.y) + (ai_real)AI_MATH_PI) / (ai_real)AI_MATH_TWO_PI; } - } - else if (axis * base_axis_y >= angle_epsilon) { + } else if (axis * base_axis_y >= angle_epsilon) { FindMeshCenter(mesh, center, min, max); const ai_real diff = max.y - min.y; // just the same ... - for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt) { - const aiVector3D& pos = mesh->mVertices[pnt]; - aiVector3D& uv = out[pnt]; + for (unsigned int pnt = 0; pnt < mesh->mNumVertices; ++pnt) { + const aiVector3D &pos = mesh->mVertices[pnt]; + aiVector3D &uv = out[pnt]; uv.y = (pos.y - min.y) / diff; - uv.x = (std::atan2( pos.x - center.x, pos.z - center.z) +(ai_real)AI_MATH_PI ) / (ai_real)AI_MATH_TWO_PI; + uv.x = (std::atan2(pos.x - center.x, pos.z - center.z) + (ai_real)AI_MATH_PI) / (ai_real)AI_MATH_TWO_PI; } - } - else if (axis * base_axis_z >= angle_epsilon) { + } else if (axis * base_axis_z >= angle_epsilon) { FindMeshCenter(mesh, center, min, max); const ai_real diff = max.z - min.z; // just the same ... - for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt) { - const aiVector3D& pos = mesh->mVertices[pnt]; - aiVector3D& uv = out[pnt]; + for (unsigned int pnt = 0; pnt < mesh->mNumVertices; ++pnt) { + const aiVector3D &pos = mesh->mVertices[pnt]; + aiVector3D &uv = out[pnt]; uv.y = (pos.z - min.z) / diff; - uv.x = (std::atan2( pos.y - center.y, pos.x - center.x) +(ai_real)AI_MATH_PI ) / (ai_real)AI_MATH_TWO_PI; + uv.x = (std::atan2(pos.y - center.y, pos.x - center.x) + (ai_real)AI_MATH_PI) / (ai_real)AI_MATH_TWO_PI; } } // slower code path in case the mapping axis is not one of the coordinate system axes else { aiMatrix4x4 mTrafo; - aiMatrix4x4::FromToMatrix(axis,base_axis_y,mTrafo); - FindMeshCenterTransformed(mesh, center, min, max,mTrafo); + aiMatrix4x4::FromToMatrix(axis, base_axis_y, mTrafo); + FindMeshCenterTransformed(mesh, center, min, max, mTrafo); const ai_real diff = max.y - min.y; // again the same, except we're applying a transformation now - for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt){ - const aiVector3D pos = mTrafo* mesh->mVertices[pnt]; - aiVector3D& uv = out[pnt]; + for (unsigned int pnt = 0; pnt < mesh->mNumVertices; ++pnt) { + const aiVector3D pos = mTrafo * mesh->mVertices[pnt]; + aiVector3D &uv = out[pnt]; uv.y = (pos.y - min.y) / diff; - uv.x = (std::atan2( pos.x - center.x, pos.z - center.z) +(ai_real)AI_MATH_PI ) / (ai_real)AI_MATH_TWO_PI; + uv.x = (std::atan2(pos.x - center.x, pos.z - center.z) + (ai_real)AI_MATH_PI) / (ai_real)AI_MATH_TWO_PI; } } // Now find and remove UV seams. A seam occurs if a face has a tcoord // close to zero on the one side, and a tcoord close to one on the // other side. - RemoveUVSeams(mesh,out); + RemoveUVSeams(mesh, out); } // ------------------------------------------------------------------------------------------------ -void ComputeUVMappingProcess::ComputePlaneMapping(aiMesh* mesh,const aiVector3D& axis, aiVector3D* out) -{ - ai_real diffu,diffv; +void ComputeUVMappingProcess::ComputePlaneMapping(aiMesh *mesh, const aiVector3D &axis, aiVector3D *out) { + ai_real diffu, diffv; aiVector3D center, min, max; // If the axis is one of x,y,z run a faster code path. It's worth the extra effort ... // currently the mapping axis will always be one of x,y,z, except if the // PretransformVertices step is used (it transforms the meshes into worldspace, // thus changing the mapping axis) - if (axis * base_axis_x >= angle_epsilon) { + if (axis * base_axis_x >= angle_epsilon) { FindMeshCenter(mesh, center, min, max); diffu = max.z - min.z; diffv = max.y - min.y; - for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt) { - const aiVector3D& pos = mesh->mVertices[pnt]; - out[pnt].Set((pos.z - min.z) / diffu,(pos.y - min.y) / diffv,0.0); + for (unsigned int pnt = 0; pnt < mesh->mNumVertices; ++pnt) { + const aiVector3D &pos = mesh->mVertices[pnt]; + out[pnt].Set((pos.z - min.z) / diffu, (pos.y - min.y) / diffv, 0.0); } - } - else if (axis * base_axis_y >= angle_epsilon) { + } else if (axis * base_axis_y >= angle_epsilon) { FindMeshCenter(mesh, center, min, max); diffu = max.x - min.x; diffv = max.z - min.z; - for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt) { - const aiVector3D& pos = mesh->mVertices[pnt]; - out[pnt].Set((pos.x - min.x) / diffu,(pos.z - min.z) / diffv,0.0); + for (unsigned int pnt = 0; pnt < mesh->mNumVertices; ++pnt) { + const aiVector3D &pos = mesh->mVertices[pnt]; + out[pnt].Set((pos.x - min.x) / diffu, (pos.z - min.z) / diffv, 0.0); } - } - else if (axis * base_axis_z >= angle_epsilon) { + } else if (axis * base_axis_z >= angle_epsilon) { FindMeshCenter(mesh, center, min, max); diffu = max.x - min.x; diffv = max.y - min.y; - for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt) { - const aiVector3D& pos = mesh->mVertices[pnt]; - out[pnt].Set((pos.x - min.x) / diffu,(pos.y - min.y) / diffv,0.0); + for (unsigned int pnt = 0; pnt < mesh->mNumVertices; ++pnt) { + const aiVector3D &pos = mesh->mVertices[pnt]; + out[pnt].Set((pos.x - min.x) / diffu, (pos.y - min.y) / diffv, 0.0); } } // slower code path in case the mapping axis is not one of the coordinate system axes - else - { + else { aiMatrix4x4 mTrafo; - aiMatrix4x4::FromToMatrix(axis,base_axis_y,mTrafo); - FindMeshCenterTransformed(mesh, center, min, max,mTrafo); + aiMatrix4x4::FromToMatrix(axis, base_axis_y, mTrafo); + FindMeshCenterTransformed(mesh, center, min, max, mTrafo); diffu = max.x - min.x; diffv = max.z - min.z; // again the same, except we're applying a transformation now - for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt) { + for (unsigned int pnt = 0; pnt < mesh->mNumVertices; ++pnt) { const aiVector3D pos = mTrafo * mesh->mVertices[pnt]; - out[pnt].Set((pos.x - min.x) / diffu,(pos.z - min.z) / diffv,0.0); + out[pnt].Set((pos.x - min.x) / diffu, (pos.z - min.z) / diffv, 0.0); } } @@ -368,14 +337,12 @@ void ComputeUVMappingProcess::ComputePlaneMapping(aiMesh* mesh,const aiVector3D& } // ------------------------------------------------------------------------------------------------ -void ComputeUVMappingProcess::ComputeBoxMapping( aiMesh*, aiVector3D* ) -{ +void ComputeUVMappingProcess::ComputeBoxMapping(aiMesh *, aiVector3D *) { ASSIMP_LOG_ERROR("Mapping type currently not implemented"); } // ------------------------------------------------------------------------------------------------ -void ComputeUVMappingProcess::Execute( aiScene* pScene) -{ +void ComputeUVMappingProcess::Execute(aiScene *pScene) { ASSIMP_LOG_DEBUG("GenUVCoordsProcess begin"); char buffer[1024]; @@ -386,23 +353,18 @@ void ComputeUVMappingProcess::Execute( aiScene* pScene) /* Iterate through all materials and search for non-UV mapped textures */ - for (unsigned int i = 0; i < pScene->mNumMaterials;++i) - { + for (unsigned int i = 0; i < pScene->mNumMaterials; ++i) { mappingStack.clear(); - aiMaterial* mat = pScene->mMaterials[i]; - for (unsigned int a = 0; a < mat->mNumProperties;++a) - { - aiMaterialProperty* prop = mat->mProperties[a]; - if (!::strcmp( prop->mKey.data, "$tex.mapping")) - { - aiTextureMapping& mapping = *((aiTextureMapping*)prop->mData); - if (aiTextureMapping_UV != mapping) - { - if (!DefaultLogger::isNullLogger()) - { + aiMaterial *mat = pScene->mMaterials[i]; + for (unsigned int a = 0; a < mat->mNumProperties; ++a) { + aiMaterialProperty *prop = mat->mProperties[a]; + if (!::strcmp(prop->mKey.data, "$tex.mapping")) { + aiTextureMapping &mapping = *((aiTextureMapping *)prop->mData); + if (aiTextureMapping_UV != mapping) { + if (!DefaultLogger::isNullLogger()) { ai_snprintf(buffer, 1024, "Found non-UV mapped texture (%s,%u). Mapping type: %s", - aiTextureTypeToString((aiTextureType)prop->mSemantic),prop->mIndex, - MappingTypeToString(mapping)); + aiTextureTypeToString((aiTextureType)prop->mSemantic), prop->mIndex, + MappingTypeToString(mapping)); ASSIMP_LOG_INFO(buffer); } @@ -410,70 +372,62 @@ void ComputeUVMappingProcess::Execute( aiScene* pScene) if (aiTextureMapping_OTHER == mapping) continue; - MappingInfo info (mapping); + MappingInfo info(mapping); // Get further properties - currently only the major axis - for (unsigned int a2 = 0; a2 < mat->mNumProperties;++a2) - { - aiMaterialProperty* prop2 = mat->mProperties[a2]; + for (unsigned int a2 = 0; a2 < mat->mNumProperties; ++a2) { + aiMaterialProperty *prop2 = mat->mProperties[a2]; if (prop2->mSemantic != prop->mSemantic || prop2->mIndex != prop->mIndex) continue; - if ( !::strcmp( prop2->mKey.data, "$tex.mapaxis")) { - info.axis = *((aiVector3D*)prop2->mData); + if (!::strcmp(prop2->mKey.data, "$tex.mapaxis")) { + info.axis = *((aiVector3D *)prop2->mData); break; } } - unsigned int idx( 99999999 ); + unsigned int idx(99999999); // Check whether we have this mapping mode already - std::list::iterator it = std::find (mappingStack.begin(),mappingStack.end(), info); - if (mappingStack.end() != it) - { + std::list::iterator it = std::find(mappingStack.begin(), mappingStack.end(), info); + if (mappingStack.end() != it) { idx = (*it).uv; - } - else - { + } else { /* We have found a non-UV mapped texture. Now - * we need to find all meshes using this material - * that we can compute UV channels for them. - */ - for (unsigned int m = 0; m < pScene->mNumMeshes;++m) - { - aiMesh* mesh = pScene->mMeshes[m]; + * we need to find all meshes using this material + * that we can compute UV channels for them. + */ + for (unsigned int m = 0; m < pScene->mNumMeshes; ++m) { + aiMesh *mesh = pScene->mMeshes[m]; unsigned int outIdx = 0; - if ( mesh->mMaterialIndex != i || ( outIdx = FindEmptyUVChannel(mesh) ) == UINT_MAX || - !mesh->mNumVertices) - { + if (mesh->mMaterialIndex != i || (outIdx = FindEmptyUVChannel(mesh)) == UINT_MAX || + !mesh->mNumVertices) { continue; } // Allocate output storage - aiVector3D* p = mesh->mTextureCoords[outIdx] = new aiVector3D[mesh->mNumVertices]; + aiVector3D *p = mesh->mTextureCoords[outIdx] = new aiVector3D[mesh->mNumVertices]; - switch (mapping) - { + switch (mapping) { case aiTextureMapping_SPHERE: - ComputeSphereMapping(mesh,info.axis,p); + ComputeSphereMapping(mesh, info.axis, p); break; case aiTextureMapping_CYLINDER: - ComputeCylinderMapping(mesh,info.axis,p); + ComputeCylinderMapping(mesh, info.axis, p); break; case aiTextureMapping_PLANE: - ComputePlaneMapping(mesh,info.axis,p); + ComputePlaneMapping(mesh, info.axis, p); break; case aiTextureMapping_BOX: - ComputeBoxMapping(mesh,p); + ComputeBoxMapping(mesh, p); break; default: ai_assert(false); } - if (m && idx != outIdx) - { + if (m && idx != outIdx) { ASSIMP_LOG_WARN("UV index mismatch. Not all meshes assigned to " - "this material have equal numbers of UV channels. The UV index stored in " - "the material structure does therefore not apply for all meshes. "); + "this material have equal numbers of UV channels. The UV index stored in " + "the material structure does therefore not apply for all meshes. "); } idx = outIdx; } @@ -483,7 +437,7 @@ void ComputeUVMappingProcess::Execute( aiScene* pScene) // Update the material property list mapping = aiTextureMapping_UV; - ((aiMaterial*)mat)->AddProperty(&idx,1,AI_MATKEY_UVWSRC(prop->mSemantic,prop->mIndex)); + ((aiMaterial *)mat)->AddProperty(&idx, 1, AI_MATKEY_UVWSRC(prop->mSemantic, prop->mIndex)); } } } diff --git a/code/PostProcessing/ConvertToLHProcess.cpp b/code/PostProcessing/ConvertToLHProcess.cpp index 08e3fe48a..80abf84a5 100644 --- a/code/PostProcessing/ConvertToLHProcess.cpp +++ b/code/PostProcessing/ConvertToLHProcess.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, @@ -113,6 +111,12 @@ void MakeLeftHandedProcess::Execute(aiScene *pScene) { ProcessAnimation(nodeAnim); } } + + // process the cameras accordingly + for( unsigned int a = 0; a < pScene->mNumCameras; ++a) + { + ProcessCamera(pScene->mCameras[a]); + } ASSIMP_LOG_DEBUG("MakeLeftHandedProcess finished"); } @@ -219,18 +223,18 @@ void MakeLeftHandedProcess::ProcessAnimation(aiNodeAnim *pAnim) { // rotation keys for (unsigned int a = 0; a < pAnim->mNumRotationKeys; a++) { - /* That's the safe version, but the float errors add up. So we try the short version instead - aiMatrix3x3 rotmat = pAnim->mRotationKeys[a].mValue.GetMatrix(); - rotmat.a3 = -rotmat.a3; rotmat.b3 = -rotmat.b3; - rotmat.c1 = -rotmat.c1; rotmat.c2 = -rotmat.c2; - aiQuaternion rotquat( rotmat); - pAnim->mRotationKeys[a].mValue = rotquat; - */ pAnim->mRotationKeys[a].mValue.x *= -1.0f; pAnim->mRotationKeys[a].mValue.y *= -1.0f; } } +// ------------------------------------------------------------------------------------------------ +// Converts a single camera to left handed coordinates. +void MakeLeftHandedProcess::ProcessCamera( aiCamera* pCam) +{ + pCam->mLookAt = ai_real(2.0f) * pCam->mPosition - pCam->mLookAt; +} + #endif // !! ASSIMP_BUILD_NO_MAKELEFTHANDED_PROCESS #ifndef ASSIMP_BUILD_NO_FLIPUVS_PROCESS // # FlipUVsProcess diff --git a/code/PostProcessing/ConvertToLHProcess.h b/code/PostProcessing/ConvertToLHProcess.h index d0532277d..ea001b95b 100644 --- a/code/PostProcessing/ConvertToLHProcess.h +++ b/code/PostProcessing/ConvertToLHProcess.h @@ -58,6 +58,7 @@ struct aiMesh; struct aiNodeAnim; struct aiNode; struct aiMaterial; +struct aiCamera; namespace Assimp { @@ -109,6 +110,14 @@ protected: * @param pAnim The bone animation to transform */ void ProcessAnimation( aiNodeAnim* pAnim); + + // ------------------------------------------------------------------- + /** Converts a single camera to left handed coordinates. + * The camera viewing direction is inverted by reflecting mLookAt + * across mPosition. + * @param pCam The camera to convert + */ + void ProcessCamera( aiCamera* pCam); }; diff --git a/code/PostProcessing/DeboneProcess.cpp b/code/PostProcessing/DeboneProcess.cpp index 2a8499dc5..e91196ce2 100644 --- a/code/PostProcessing/DeboneProcess.cpp +++ b/code/PostProcessing/DeboneProcess.cpp @@ -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, @@ -87,7 +86,7 @@ void DeboneProcess::Execute( aiScene* pScene) { if(!!mNumBonesCanDoWithout && (!mAllOrNone||mNumBonesCanDoWithout==mNumBones)) { for(unsigned int a = 0; a < pScene->mNumMeshes; a++) { if(splitList[a]) { - numSplits++; + ++numSplits; } } } @@ -119,8 +118,8 @@ void DeboneProcess::Execute( aiScene* pScene) { aiNode *theNode = find ? pScene->mRootNode->FindNode(*find) : nullptr; std::pair push_pair(static_cast(meshes.size()),theNode); - mSubMeshIndices[a].push_back(push_pair); - meshes.push_back(newMeshes[b].first); + mSubMeshIndices[a].emplace_back(push_pair); + meshes.emplace_back(newMeshes[b].first); out+=newMeshes[b].first->mNumBones; } @@ -360,9 +359,7 @@ void DeboneProcess::UpdateNode(aiNode* pNode) const { unsigned int m = static_cast(pNode->mNumMeshes), n = static_cast(mSubMeshIndices.size()); // first pass, look for meshes which have not moved - for(unsigned int a=0;amMeshes[a]; const std::vector< std::pair< unsigned int,aiNode* > > &subMeshes = mSubMeshIndices[srcIndex]; unsigned int nSubmeshes = static_cast(subMeshes.size()); @@ -376,8 +373,7 @@ void DeboneProcess::UpdateNode(aiNode* pNode) const { // second pass, collect deboned meshes - for(unsigned int a=0;a > &subMeshes = mSubMeshIndices[a]; unsigned int nSubmeshes = static_cast(subMeshes.size()); diff --git a/code/PostProcessing/DropFaceNormalsProcess.cpp b/code/PostProcessing/DropFaceNormalsProcess.cpp index 223482374..c5f6333e0 100644 --- a/code/PostProcessing/DropFaceNormalsProcess.cpp +++ b/code/PostProcessing/DropFaceNormalsProcess.cpp @@ -42,27 +42,26 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /** @file Implementation of the post processing step to drop face -* normals for all imported faces. -*/ - + * normals for all imported faces. + */ #include "DropFaceNormalsProcess.h" +#include #include #include #include -#include using namespace Assimp; // ------------------------------------------------------------------------------------------------ // Returns whether the processing step is present in the given flag field. -bool DropFaceNormalsProcess::IsActive( unsigned int pFlags) const { - return (pFlags & aiProcess_DropNormals) != 0; +bool DropFaceNormalsProcess::IsActive(unsigned int pFlags) const { + return (pFlags & aiProcess_DropNormals) != 0; } // ------------------------------------------------------------------------------------------------ // Executes the post processing step on the given imported data. -void DropFaceNormalsProcess::Execute( aiScene* pScene) { +void DropFaceNormalsProcess::Execute(aiScene *pScene) { ASSIMP_LOG_DEBUG("DropFaceNormalsProcess begin"); if (pScene->mFlags & AI_SCENE_FLAGS_NON_VERBOSE_FORMAT) { @@ -70,21 +69,21 @@ void DropFaceNormalsProcess::Execute( aiScene* pScene) { } bool bHas = false; - for( unsigned int a = 0; a < pScene->mNumMeshes; a++) { - bHas |= this->DropMeshFaceNormals( pScene->mMeshes[a]); + for (unsigned int a = 0; a < pScene->mNumMeshes; a++) { + bHas |= this->DropMeshFaceNormals(pScene->mMeshes[a]); } - if (bHas) { + if (bHas) { ASSIMP_LOG_INFO("DropFaceNormalsProcess finished. " - "Face normals have been removed"); + "Face normals have been removed"); } else { ASSIMP_LOG_DEBUG("DropFaceNormalsProcess finished. " - "No normals were present"); + "No normals were present"); } } // ------------------------------------------------------------------------------------------------ // Executes the post processing step on the given imported data. -bool DropFaceNormalsProcess::DropMeshFaceNormals (aiMesh* mesh) { +bool DropFaceNormalsProcess::DropMeshFaceNormals(aiMesh *mesh) { ai_assert(nullptr != mesh); if (nullptr == mesh->mNormals) { diff --git a/code/PostProcessing/FindDegenerates.cpp b/code/PostProcessing/FindDegenerates.cpp index 5874c17d2..d9c14425c 100644 --- a/code/PostProcessing/FindDegenerates.cpp +++ b/code/PostProcessing/FindDegenerates.cpp @@ -41,11 +41,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. /** @file FindDegenerates.cpp * @brief Implementation of the FindDegenerates post-process step. -*/ + */ -#include "ProcessHelper.h" #include "FindDegenerates.h" #include "Geometry/GeometryUtils.h" +#include "ProcessHelper.h" #include @@ -54,35 +54,35 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. using namespace Assimp; // Correct node indices to meshes and remove references to deleted mesh -static void updateSceneGraph(aiNode* pNode, const std::unordered_map& meshMap); +static void updateSceneGraph(aiNode *pNode, const std::unordered_map &meshMap); // ------------------------------------------------------------------------------------------------ // Constructor to be privately used by Importer FindDegeneratesProcess::FindDegeneratesProcess() : - mConfigRemoveDegenerates( false ), - mConfigCheckAreaOfTriangle( false ){ + mConfigRemoveDegenerates(false), + mConfigCheckAreaOfTriangle(false) { // empty } // ------------------------------------------------------------------------------------------------ // Returns whether the processing step is present in the given flag field. -bool FindDegeneratesProcess::IsActive( unsigned int pFlags) const { +bool FindDegeneratesProcess::IsActive(unsigned int pFlags) const { return 0 != (pFlags & aiProcess_FindDegenerates); } // ------------------------------------------------------------------------------------------------ // Setup import configuration -void FindDegeneratesProcess::SetupProperties(const Importer* pImp) { +void FindDegeneratesProcess::SetupProperties(const Importer *pImp) { // Get the current value of AI_CONFIG_PP_FD_REMOVE - mConfigRemoveDegenerates = (0 != pImp->GetPropertyInteger(AI_CONFIG_PP_FD_REMOVE,0)); - mConfigCheckAreaOfTriangle = ( 0 != pImp->GetPropertyInteger(AI_CONFIG_PP_FD_CHECKAREA) ); + mConfigRemoveDegenerates = (0 != pImp->GetPropertyInteger(AI_CONFIG_PP_FD_REMOVE, 0)); + mConfigCheckAreaOfTriangle = (0 != pImp->GetPropertyInteger(AI_CONFIG_PP_FD_CHECKAREA)); } // ------------------------------------------------------------------------------------------------ // Executes the post processing step on the given imported data. -void FindDegeneratesProcess::Execute( aiScene* pScene) { +void FindDegeneratesProcess::Execute(aiScene *pScene) { ASSIMP_LOG_DEBUG("FindDegeneratesProcess begin"); - if ( nullptr == pScene) { + if (nullptr == pScene) { return; } @@ -112,7 +112,7 @@ void FindDegeneratesProcess::Execute( aiScene* pScene) { ASSIMP_LOG_DEBUG("FindDegeneratesProcess finished"); } -static void updateSceneGraph(aiNode* pNode, const std::unordered_map& meshMap) { +static void updateSceneGraph(aiNode *pNode, const std::unordered_map &meshMap) { unsigned int targetIndex = 0; for (unsigned i = 0; i < pNode->mNumMeshes; ++i) { const unsigned int sourceMeshIndex = pNode->mMeshes[i]; @@ -123,7 +123,7 @@ static void updateSceneGraph(aiNode* pNode, const std::unordered_mapmNumMeshes = targetIndex; - //recurse to all children + // recurse to all children for (unsigned i = 0; i < pNode->mNumChildren; ++i) { updateSceneGraph(pNode->mChildren[i], meshMap); } @@ -131,17 +131,17 @@ static void updateSceneGraph(aiNode* pNode, const std::unordered_mapmPrimitiveTypes = 0; std::vector remove_me; if (mConfigRemoveDegenerates) { - remove_me.resize( mesh->mNumFaces, false ); + remove_me.resize(mesh->mNumFaces, false); } unsigned int deg = 0, limit; - for ( unsigned int a = 0; a < mesh->mNumFaces; ++a ) { - aiFace& face = mesh->mFaces[a]; + for (unsigned int a = 0; a < mesh->mNumFaces; ++a) { + aiFace &face = mesh->mFaces[a]; bool first = true; // check whether the face contains degenerated entries @@ -151,43 +151,43 @@ bool FindDegeneratesProcess::ExecuteOnMesh( aiMesh* mesh) { // double points may not come directly after another. limit = face.mNumIndices; if (face.mNumIndices > 4) { - limit = std::min( limit, i+2 ); + limit = std::min(limit, i + 2); } - for (unsigned int t = i+1; t < limit; ++t) { - if (mesh->mVertices[face.mIndices[ i ] ] == mesh->mVertices[ face.mIndices[ t ] ]) { + for (unsigned int t = i + 1; t < limit; ++t) { + if (mesh->mVertices[face.mIndices[i]] == mesh->mVertices[face.mIndices[t]]) { // we have found a matching vertex position // remove the corresponding index from the array --face.mNumIndices; --limit; for (unsigned int m = t; m < face.mNumIndices; ++m) { - face.mIndices[ m ] = face.mIndices[ m+1 ]; + face.mIndices[m] = face.mIndices[m + 1]; } --t; // NOTE: we set the removed vertex index to an unique value // to make sure the developer gets notified when his // application attempts to access this data. - face.mIndices[ face.mNumIndices ] = 0xdeadbeef; + face.mIndices[face.mNumIndices] = 0xdeadbeef; - if(first) { + if (first) { ++deg; first = false; } - if ( mConfigRemoveDegenerates ) { - remove_me[ a ] = true; + if (mConfigRemoveDegenerates) { + remove_me[a] = true; goto evil_jump_outside; // hrhrhrh ... yeah, this rocks baby! } } } - if ( mConfigCheckAreaOfTriangle ) { - if ( face.mNumIndices == 3 ) { - ai_real area = GeometryUtils::calculateAreaOfTriangle( face, mesh ); + if (mConfigCheckAreaOfTriangle) { + if (face.mNumIndices == 3) { + ai_real area = GeometryUtils::calculateAreaOfTriangle(face, mesh); if (area < ai_epsilon) { - if ( mConfigRemoveDegenerates ) { - remove_me[ a ] = true; + if (mConfigRemoveDegenerates) { + remove_me[a] = true; ++deg; goto evil_jump_outside; } @@ -199,8 +199,7 @@ bool FindDegeneratesProcess::ExecuteOnMesh( aiMesh* mesh) { } // We need to update the primitive flags array of the mesh. - switch (face.mNumIndices) - { + switch (face.mNumIndices) { case 1u: mesh->mPrimitiveTypes |= aiPrimitiveType_POINT; break; @@ -214,30 +213,28 @@ bool FindDegeneratesProcess::ExecuteOnMesh( aiMesh* mesh) { mesh->mPrimitiveTypes |= aiPrimitiveType_POLYGON; break; }; -evil_jump_outside: + evil_jump_outside: continue; } // If AI_CONFIG_PP_FD_REMOVE is true, remove degenerated faces from the import if (mConfigRemoveDegenerates && deg) { unsigned int n = 0; - for (unsigned int a = 0; a < mesh->mNumFaces; ++a) - { - aiFace& face_src = mesh->mFaces[a]; + for (unsigned int a = 0; a < mesh->mNumFaces; ++a) { + aiFace &face_src = mesh->mFaces[a]; if (!remove_me[a]) { - aiFace& face_dest = mesh->mFaces[n++]; + aiFace &face_dest = mesh->mFaces[n++]; // Do a manual copy, keep the index array face_dest.mNumIndices = face_src.mNumIndices; - face_dest.mIndices = face_src.mIndices; + face_dest.mIndices = face_src.mIndices; if (&face_src != &face_dest) { // clear source face_src.mNumIndices = 0; face_src.mIndices = nullptr; } - } - else { + } else { // Otherwise delete it if we don't need this face delete[] face_src.mIndices; face_src.mIndices = nullptr; @@ -247,15 +244,15 @@ evil_jump_outside: // Just leave the rest of the array unreferenced, we don't care for now mesh->mNumFaces = n; if (!mesh->mNumFaces) { - //The whole mesh consists of degenerated faces - //signal upward, that this mesh should be deleted. + // The whole mesh consists of degenerated faces + // signal upward, that this mesh should be deleted. ASSIMP_LOG_VERBOSE_DEBUG("FindDegeneratesProcess removed a mesh full of degenerated primitives"); return true; } } if (deg && !DefaultLogger::isNullLogger()) { - ASSIMP_LOG_WARN( "Found ", deg, " degenerated primitives"); + ASSIMP_LOG_WARN("Found ", deg, " degenerated primitives"); } return false; } diff --git a/code/PostProcessing/PretransformVertices.cpp b/code/PostProcessing/PretransformVertices.cpp index 16548f09c..87af2297d 100644 --- a/code/PostProcessing/PretransformVertices.cpp +++ b/code/PostProcessing/PretransformVertices.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,9 +39,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. --------------------------------------------------------------------------- */ -/** @file PretransformVertices.cpp - * @brief Implementation of the "PretransformVertices" post processing step -*/ +/// @file PretransformVertices.cpp +/// @brief Implementation of the "PretransformVertices" post processing step #include "PretransformVertices.h" #include "ConvertToLHProcess.h" @@ -57,16 +54,44 @@ using namespace Assimp; #define AI_PTVS_VERTEX 0x0 #define AI_PTVS_FACE 0x1 +namespace { + +// Get a bitwise combination identifying the vertex format of a mesh +static unsigned int GetMeshVFormat(aiMesh *pcMesh) { + // the vertex format is stored in aiMesh::mBones for later retrieval. + // there isn't a good reason to compute it a few hundred times + // from scratch. The pointer is unused as animations are lost + // during PretransformVertices. + if (pcMesh->mBones) + return (unsigned int)(uint64_t)pcMesh->mBones; + + const unsigned int iRet = GetMeshVFormatUnique(pcMesh); + + // store the value for later use + pcMesh->mBones = (aiBone **)(uint64_t)iRet; + return iRet; +} + +// Get a list of all vertex formats that occur for a given material index +// The output list contains duplicate elements +static void GetVFormatList(const aiScene *pcScene, unsigned int iMat, std::list &aiOut) { + for (unsigned int i = 0; i < pcScene->mNumMeshes; ++i) { + aiMesh *pcMesh = pcScene->mMeshes[i]; + if (iMat == pcMesh->mMaterialIndex) { + aiOut.push_back(GetMeshVFormat(pcMesh)); + } + } +} + +} // ------------------------------------------------------------------------------------------------ // Constructor to be privately used by Importer PretransformVertices::PretransformVertices() : - configKeepHierarchy(false), - configNormalize(false), - configTransform(false), - configTransformation(), - mConfigPointCloud(false) { - // empty -} + mConfigKeepHierarchy(false), + mConfigNormalize(false), + mConfigTransform(false), + mConfigTransformation(), + mConfigPointCloud(false) {} // ------------------------------------------------------------------------------------------------ // Returns whether the processing step is present in the given flag field. @@ -79,11 +104,11 @@ bool PretransformVertices::IsActive(unsigned int pFlags) const { void PretransformVertices::SetupProperties(const Importer *pImp) { // Get the current value of AI_CONFIG_PP_PTV_KEEP_HIERARCHY, AI_CONFIG_PP_PTV_NORMALIZE, // AI_CONFIG_PP_PTV_ADD_ROOT_TRANSFORMATION and AI_CONFIG_PP_PTV_ROOT_TRANSFORMATION - configKeepHierarchy = (0 != pImp->GetPropertyInteger(AI_CONFIG_PP_PTV_KEEP_HIERARCHY, 0)); - configNormalize = (0 != pImp->GetPropertyInteger(AI_CONFIG_PP_PTV_NORMALIZE, 0)); - configTransform = (0 != pImp->GetPropertyInteger(AI_CONFIG_PP_PTV_ADD_ROOT_TRANSFORMATION, 0)); + mConfigKeepHierarchy = (0 != pImp->GetPropertyInteger(AI_CONFIG_PP_PTV_KEEP_HIERARCHY, 0)); + mConfigNormalize = (0 != pImp->GetPropertyInteger(AI_CONFIG_PP_PTV_NORMALIZE, 0)); + mConfigTransform = (0 != pImp->GetPropertyInteger(AI_CONFIG_PP_PTV_ADD_ROOT_TRANSFORMATION, 0)); - configTransformation = pImp->GetPropertyMatrix(AI_CONFIG_PP_PTV_ROOT_TRANSFORMATION, aiMatrix4x4()); + mConfigTransformation = pImp->GetPropertyMatrix(AI_CONFIG_PP_PTV_ROOT_TRANSFORMATION, aiMatrix4x4()); mConfigPointCloud = pImp->GetPropertyBool(AI_CONFIG_EXPORT_POINT_CLOUDS); } @@ -99,25 +124,7 @@ unsigned int PretransformVertices::CountNodes(const aiNode *pcNode) const { } // ------------------------------------------------------------------------------------------------ -// Get a bitwise combination identifying the vertex format of a mesh -unsigned int PretransformVertices::GetMeshVFormat(aiMesh *pcMesh) const { - // the vertex format is stored in aiMesh::mBones for later retrieval. - // there isn't a good reason to compute it a few hundred times - // from scratch. The pointer is unused as animations are lost - // during PretransformVertices. - if (pcMesh->mBones) - return (unsigned int)(uint64_t)pcMesh->mBones; - - const unsigned int iRet = GetMeshVFormatUnique(pcMesh); - - // store the value for later use - pcMesh->mBones = (aiBone **)(uint64_t)iRet; - return iRet; -} - -// ------------------------------------------------------------------------------------------------ -// Count the number of vertices in the whole scene and a given -// material index +// Count the number of vertices in the whole scene and a given material index void PretransformVertices::CountVerticesAndFaces(const aiScene *pcScene, const aiNode *pcNode, unsigned int iMat, unsigned int iVFormat, unsigned int *piFaces, unsigned int *piVertices) const { for (unsigned int i = 0; i < pcNode->mNumMeshes; ++i) { @@ -128,8 +135,7 @@ void PretransformVertices::CountVerticesAndFaces(const aiScene *pcScene, const a } } for (unsigned int i = 0; i < pcNode->mNumChildren; ++i) { - CountVerticesAndFaces(pcScene, pcNode->mChildren[i], iMat, - iVFormat, piFaces, piVertices); + CountVerticesAndFaces(pcScene, pcNode->mChildren[i], iMat, iVFormat, piFaces, piVertices); } } @@ -272,19 +278,6 @@ void PretransformVertices::CollectData(const aiScene *pcScene, const aiNode *pcN } } -// ------------------------------------------------------------------------------------------------ -// Get a list of all vertex formats that occur for a given material index -// The output list contains duplicate elements -void PretransformVertices::GetVFormatList(const aiScene *pcScene, unsigned int iMat, - std::list &aiOut) const { - for (unsigned int i = 0; i < pcScene->mNumMeshes; ++i) { - aiMesh *pcMesh = pcScene->mMeshes[i]; - if (iMat == pcMesh->mMaterialIndex) { - aiOut.push_back(GetMeshVFormat(pcMesh)); - } - } -} - // ------------------------------------------------------------------------------------------------ // Compute the absolute transformation matrices of each node void PretransformVertices::ComputeAbsoluteTransform(aiNode *pcNode) { @@ -297,39 +290,44 @@ void PretransformVertices::ComputeAbsoluteTransform(aiNode *pcNode) { } } +static void normalizeVectorArray(aiVector3D *vectorArrayIn, aiVector3D *vectorArrayOut, size_t numVectors) { + for (size_t i=0; iHasFaces() && mat.Determinant() < 0) { - // Reverse the mesh face winding order - FlipWindingOrderProcess::ProcessMesh(mesh); + // Check for odd negative scale (mirror) + if (mesh->HasFaces() && mat.Determinant() < 0) { + // Reverse the mesh face winding order + FlipWindingOrderProcess::ProcessMesh(mesh); + } + + // Update positions + if (mesh->HasPositions()) { + for (unsigned int i = 0; i < mesh->mNumVertices; ++i) { + mesh->mVertices[i] = mat * mesh->mVertices[i]; } + } - // Update positions - if (mesh->HasPositions()) { + // Update normals and tangents + if (mesh->HasNormals() || mesh->HasTangentsAndBitangents()) { + const aiMatrix3x3 m = aiMatrix3x3(mat).Inverse().Transpose(); + + if (mesh->HasNormals()) { + normalizeVectorArray(mesh->mNormals, mesh->mNormals, mesh->mNumVertices); + } + if (mesh->HasTangentsAndBitangents()) { for (unsigned int i = 0; i < mesh->mNumVertices; ++i) { - mesh->mVertices[i] = mat * mesh->mVertices[i]; - } - } - - // Update normals and tangents - if (mesh->HasNormals() || mesh->HasTangentsAndBitangents()) { - const aiMatrix3x3 m = aiMatrix3x3(mat).Inverse().Transpose(); - - if (mesh->HasNormals()) { - 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(); - mesh->mBitangents[i] = (m * mesh->mBitangents[i]).Normalize(); - } + mesh->mTangents[i] = (m * mesh->mTangents[i]).Normalize(); + mesh->mBitangents[i] = (m * mesh->mBitangents[i]).Normalize(); } } } @@ -352,40 +350,41 @@ void PretransformVertices::BuildWCSMeshes(std::vector &out, aiMesh **i // yes, we can. mesh->mBones = reinterpret_cast(&node->mTransformation); mesh->mNumBones = UINT_MAX; - } else { + continue; + } - // try to find us in the list of newly created meshes - for (unsigned int n = 0; n < out.size(); ++n) { - aiMesh *ctz = out[n]; - if (ctz->mNumBones == node->mMeshes[i] && *reinterpret_cast(ctz->mBones) == node->mTransformation) { + // try to find us in the list of newly created meshes + for (unsigned int n = 0; n < out.size(); ++n) { + aiMesh *ctz = out[n]; + if (ctz->mNumBones == node->mMeshes[i] && *reinterpret_cast(ctz->mBones) == node->mTransformation) { - // ok, use this one. Update node mesh index - node->mMeshes[i] = numIn + n; - } + // ok, use this one. Update node mesh index + node->mMeshes[i] = numIn + n; } - if (node->mMeshes[i] < numIn) { - // Worst case. Need to operate on a full copy of the mesh - ASSIMP_LOG_INFO("PretransformVertices: Copying mesh due to mismatching transforms"); - aiMesh *ntz; + } + if (node->mMeshes[i] < numIn) { + // Worst case. Need to operate on a full copy of the mesh + ASSIMP_LOG_INFO("PretransformVertices: Copying mesh due to mismatching transforms"); + aiMesh *ntz; - const unsigned int tmp = mesh->mNumBones; // - mesh->mNumBones = 0; - SceneCombiner::Copy(&ntz, mesh); - mesh->mNumBones = tmp; + const unsigned int cacheNumBones = mesh->mNumBones; // + mesh->mNumBones = 0; + SceneCombiner::Copy(&ntz, mesh); + mesh->mNumBones = cacheNumBones; - ntz->mNumBones = node->mMeshes[i]; - ntz->mBones = reinterpret_cast(&node->mTransformation); + ntz->mNumBones = node->mMeshes[i]; + ntz->mBones = reinterpret_cast(&node->mTransformation); - out.push_back(ntz); + out.push_back(ntz); - node->mMeshes[i] = static_cast(numIn + out.size() - 1); - } + node->mMeshes[i] = static_cast(numIn + out.size() - 1); } } // call children - for (unsigned int i = 0; i < node->mNumChildren; ++i) + for (unsigned int i = 0; i < node->mNumChildren; ++i) { BuildWCSMeshes(out, in, numIn, node->mChildren[i]); + } } // ------------------------------------------------------------------------------------------------ @@ -394,8 +393,9 @@ void PretransformVertices::MakeIdentityTransform(aiNode *nd) const { nd->mTransformation = aiMatrix4x4(); // call children - for (unsigned int i = 0; i < nd->mNumChildren; ++i) + for (unsigned int i = 0; i < nd->mNumChildren; ++i) { MakeIdentityTransform(nd->mChildren[i]); + } } // ------------------------------------------------------------------------------------------------ @@ -405,8 +405,27 @@ void PretransformVertices::BuildMeshRefCountArray(const aiNode *nd, unsigned int refs[nd->mMeshes[i]]++; // call children - for (unsigned int i = 0; i < nd->mNumChildren; ++i) + for (unsigned int i = 0; i < nd->mNumChildren; ++i) { BuildMeshRefCountArray(nd->mChildren[i], refs); + } +} + +// ------------------------------------------------------------------------------------------------ +static void appendNewMeshesToScene(aiScene *pScene, std::vector &apcOutMeshes) { + ai_assert(pScene != nullptr); + + if (apcOutMeshes.empty()) { + return; + } + + aiMesh **npp = new aiMesh *[pScene->mNumMeshes + apcOutMeshes.size()]; + + ::memcpy(npp, pScene->mMeshes, sizeof(aiMesh *) * pScene->mNumMeshes); + ::memcpy(npp + pScene->mNumMeshes, &apcOutMeshes[0], sizeof(aiMesh *) * apcOutMeshes.size()); + + pScene->mNumMeshes += static_cast(apcOutMeshes.size()); + delete[] pScene->mMeshes; + pScene->mMeshes = npp; } // ------------------------------------------------------------------------------------------------ @@ -418,12 +437,12 @@ void PretransformVertices::Execute(aiScene *pScene) { if (!pScene->mNumMeshes) return; - const unsigned int iOldMeshes = pScene->mNumMeshes; - const unsigned int iOldAnimationChannels = pScene->mNumAnimations; - const unsigned int iOldNodes = CountNodes(pScene->mRootNode); + const unsigned int oldMeshes = pScene->mNumMeshes; + const unsigned int oldAnimationChannels = pScene->mNumAnimations; + const unsigned int oldNodes = CountNodes(pScene->mRootNode); - if (configTransform) { - pScene->mRootNode->mTransformation = configTransformation * pScene->mRootNode->mTransformation; + if (mConfigTransform) { + pScene->mRootNode->mTransformation = mConfigTransformation * pScene->mRootNode->mTransformation; } // first compute absolute transformation matrices for all nodes @@ -449,22 +468,13 @@ void PretransformVertices::Execute(aiScene *pScene) { // we go on and transform all meshes, if one is referenced by nodes // with different absolute transformations a depth copy of the mesh // is required. - if (configKeepHierarchy) { + if (mConfigKeepHierarchy) { // Hack: store the matrix we're transforming a mesh with in aiMesh::mBones BuildWCSMeshes(apcOutMeshes, pScene->mMeshes, pScene->mNumMeshes, pScene->mRootNode); // ... if new meshes have been generated, append them to the end of the scene - if (apcOutMeshes.size() > 0) { - aiMesh **npp = new aiMesh *[pScene->mNumMeshes + apcOutMeshes.size()]; - - memcpy(npp, pScene->mMeshes, sizeof(aiMesh *) * pScene->mNumMeshes); - memcpy(npp + pScene->mNumMeshes, &apcOutMeshes[0], sizeof(aiMesh *) * apcOutMeshes.size()); - - pScene->mNumMeshes += static_cast(apcOutMeshes.size()); - delete[] pScene->mMeshes; - pScene->mMeshes = npp; - } + appendNewMeshesToScene(pScene, apcOutMeshes); // now iterate through all meshes and transform them to world-space for (unsigned int i = 0; i < pScene->mNumMeshes; ++i) { @@ -488,34 +498,35 @@ void PretransformVertices::Execute(aiScene *pScene) { aiVFormats.sort(); aiVFormats.unique(); for (std::list::const_iterator j = aiVFormats.begin(); j != aiVFormats.end(); ++j) { - unsigned int iVertices = 0; - unsigned int iFaces = 0; - CountVerticesAndFaces(pScene, pScene->mRootNode, i, *j, &iFaces, &iVertices); - if (0 != iFaces && 0 != iVertices) { + unsigned int numVertices = 0u; + unsigned int numFaces = 0u; + CountVerticesAndFaces(pScene, pScene->mRootNode, i, *j, &numFaces, &numVertices); + if (0 != numFaces && 0 != numVertices) { apcOutMeshes.push_back(new aiMesh()); aiMesh *pcMesh = apcOutMeshes.back(); - pcMesh->mNumFaces = iFaces; - pcMesh->mNumVertices = iVertices; - pcMesh->mFaces = new aiFace[iFaces]; - pcMesh->mVertices = new aiVector3D[iVertices]; + pcMesh->mNumFaces = numFaces; + pcMesh->mNumVertices = numVertices; + pcMesh->mFaces = new aiFace[numFaces]; + pcMesh->mVertices = new aiVector3D[numVertices]; pcMesh->mMaterialIndex = i; - if ((*j) & 0x2) pcMesh->mNormals = new aiVector3D[iVertices]; + if ((*j) & 0x2) pcMesh->mNormals = new aiVector3D[numVertices]; if ((*j) & 0x4) { - pcMesh->mTangents = new aiVector3D[iVertices]; - pcMesh->mBitangents = new aiVector3D[iVertices]; + pcMesh->mTangents = new aiVector3D[numVertices]; + pcMesh->mBitangents = new aiVector3D[numVertices]; } - iFaces = 0; - while ((*j) & (0x100 << iFaces)) { - pcMesh->mTextureCoords[iFaces] = new aiVector3D[iVertices]; - if ((*j) & (0x10000 << iFaces)) - pcMesh->mNumUVComponents[iFaces] = 3; - else - pcMesh->mNumUVComponents[iFaces] = 2; - iFaces++; + numFaces = 0; + while ((*j) & (0x100 << numFaces)) { + pcMesh->mTextureCoords[numFaces] = new aiVector3D[numVertices]; + if ((*j) & (0x10000 << numFaces)) { + pcMesh->mNumUVComponents[numFaces] = 3; + } else { + pcMesh->mNumUVComponents[numFaces] = 2; + } + ++numFaces; } - iFaces = 0; - while ((*j) & (0x1000000 << iFaces)) - pcMesh->mColors[iFaces++] = new aiColor4D[iVertices]; + numFaces = 0; + while ((*j) & (0x1000000 << numFaces)) + pcMesh->mColors[numFaces++] = new aiColor4D[numVertices]; // fill the mesh ... unsigned int aiTemp[2] = { 0, 0 }; @@ -593,7 +604,7 @@ void PretransformVertices::Execute(aiScene *pScene) { l->mUp = aiMatrix3x3(nd->mTransformation) * l->mUp; } - if (!configKeepHierarchy) { + if (!mConfigKeepHierarchy) { // now delete all nodes in the scene and build a new // flat node graph with a root node and some level 1 children @@ -644,7 +655,7 @@ void PretransformVertices::Execute(aiScene *pScene) { MakeIdentityTransform(pScene->mRootNode); } - if (configNormalize) { + if (mConfigNormalize) { // compute the boundary of all meshes aiVector3D min, max; MinMaxChooser()(min, max); @@ -674,9 +685,9 @@ void PretransformVertices::Execute(aiScene *pScene) { if (!DefaultLogger::isNullLogger()) { ASSIMP_LOG_DEBUG("PretransformVerticesProcess finished"); - ASSIMP_LOG_INFO("Removed ", iOldNodes, " nodes and ", iOldAnimationChannels, " animation channels (", + ASSIMP_LOG_INFO("Removed ", oldNodes, " nodes and ", oldAnimationChannels, " animation channels (", CountNodes(pScene->mRootNode), " output nodes)"); ASSIMP_LOG_INFO("Kept ", pScene->mNumLights, " lights and ", pScene->mNumCameras, " cameras."); - ASSIMP_LOG_INFO("Moved ", iOldMeshes, " meshes to WCS (number of output meshes: ", pScene->mNumMeshes, ")"); + ASSIMP_LOG_INFO("Moved ", oldMeshes, " meshes to WCS (number of output meshes: ", pScene->mNumMeshes, ")"); } } diff --git a/code/PostProcessing/PretransformVertices.h b/code/PostProcessing/PretransformVertices.h index 7c2b5e99e..69d3d8400 100644 --- a/code/PostProcessing/PretransformVertices.h +++ b/code/PostProcessing/PretransformVertices.h @@ -90,7 +90,7 @@ public: * @param keep true for keep configuration. */ void KeepHierarchy(bool keep) { - configKeepHierarchy = keep; + mConfigKeepHierarchy = keep; } // ------------------------------------------------------------------- @@ -98,7 +98,7 @@ public: * @return ... */ bool IsHierarchyKept() const { - return configKeepHierarchy; + return mConfigKeepHierarchy; } private: @@ -108,7 +108,7 @@ private: // ------------------------------------------------------------------- // Get a bitwise combination identifying the vertex format of a mesh - unsigned int GetMeshVFormat(aiMesh *pcMesh) const; + //unsigned int GetMeshVFormat(aiMesh *pcMesh) const; // ------------------------------------------------------------------- // Count the number of vertices in the whole scene and a given @@ -131,8 +131,8 @@ private: // ------------------------------------------------------------------- // Get a list of all vertex formats that occur for a given material // The output list contains duplicate elements - void GetVFormatList(const aiScene *pcScene, unsigned int iMat, - std::list &aiOut) const; + /*void GetVFormatList(const aiScene *pcScene, unsigned int iMat, + std::list &aiOut) const;*/ // ------------------------------------------------------------------- // Compute the absolute transformation matrices of each node @@ -156,10 +156,10 @@ private: void BuildMeshRefCountArray(const aiNode *nd, unsigned int *refs) const; //! Configuration option: keep scene hierarchy as long as possible - bool configKeepHierarchy; - bool configNormalize; - bool configTransform; - aiMatrix4x4 configTransformation; + bool mConfigKeepHierarchy; + bool mConfigNormalize; + bool mConfigTransform; + aiMatrix4x4 mConfigTransformation; bool mConfigPointCloud; }; diff --git a/code/PostProcessing/ProcessHelper.cpp b/code/PostProcessing/ProcessHelper.cpp index 15f01676c..e55c17648 100644 --- a/code/PostProcessing/ProcessHelper.cpp +++ b/code/PostProcessing/ProcessHelper.cpp @@ -175,10 +175,9 @@ unsigned int GetMeshVFormatUnique(const aiMesh *pcMesh) { // tangents and bitangents if (pcMesh->HasTangentsAndBitangents()) iRet |= 0x4; -#ifdef BOOST_STATIC_ASSERT - BOOST_STATIC_ASSERT(8 >= AI_MAX_NUMBER_OF_COLOR_SETS); - BOOST_STATIC_ASSERT(8 >= AI_MAX_NUMBER_OF_TEXTURECOORDS); -#endif + + static_assert(8 >= AI_MAX_NUMBER_OF_COLOR_SETS); + static_assert(8 >= AI_MAX_NUMBER_OF_TEXTURECOORDS); // texture coordinates unsigned int p = 0; diff --git a/code/PostProcessing/RemoveRedundantMaterials.cpp b/code/PostProcessing/RemoveRedundantMaterials.cpp index dbc3c8822..ea8d154dc 100644 --- a/code/PostProcessing/RemoveRedundantMaterials.cpp +++ b/code/PostProcessing/RemoveRedundantMaterials.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, @@ -45,7 +43,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ // internal headers - #include "RemoveRedundantMaterials.h" #include #include "ProcessHelper.h" @@ -57,35 +54,28 @@ using namespace Assimp; // ------------------------------------------------------------------------------------------------ // Constructor to be privately used by Importer -RemoveRedundantMatsProcess::RemoveRedundantMatsProcess() -: mConfigFixedMaterials() { - // nothing to do here -} +RemoveRedundantMatsProcess::RemoveRedundantMatsProcess() : mConfigFixedMaterials() {} // ------------------------------------------------------------------------------------------------ // Returns whether the processing step is present in the given flag field. -bool RemoveRedundantMatsProcess::IsActive( unsigned int pFlags) const -{ +bool RemoveRedundantMatsProcess::IsActive( unsigned int pFlags) const { return (pFlags & aiProcess_RemoveRedundantMaterials) != 0; } // ------------------------------------------------------------------------------------------------ // Setup import properties -void RemoveRedundantMatsProcess::SetupProperties(const Importer* pImp) -{ +void RemoveRedundantMatsProcess::SetupProperties(const Importer* pImp) { // Get value of AI_CONFIG_PP_RRM_EXCLUDE_LIST mConfigFixedMaterials = pImp->GetPropertyString(AI_CONFIG_PP_RRM_EXCLUDE_LIST,""); } // ------------------------------------------------------------------------------------------------ // Executes the post processing step on the given imported data. -void RemoveRedundantMatsProcess::Execute( aiScene* pScene) -{ +void RemoveRedundantMatsProcess::Execute( aiScene* pScene) { ASSIMP_LOG_DEBUG("RemoveRedundantMatsProcess begin"); unsigned int redundantRemoved = 0, unreferencedRemoved = 0; - if (pScene->mNumMaterials) - { + if (pScene->mNumMaterials) { // Find out which materials are referenced by meshes std::vector abReferenced(pScene->mNumMaterials,false); for (unsigned int i = 0;i < pScene->mNumMeshes;++i) @@ -134,8 +124,7 @@ void RemoveRedundantMatsProcess::Execute( aiScene* pScene) // we do already have a specific hash. This allows us to // determine which materials are identical. uint32_t *aiHashes = new uint32_t[ pScene->mNumMaterials ];; - for (unsigned int i = 0; i < pScene->mNumMaterials;++i) - { + for (unsigned int i = 0; i < pScene->mNumMaterials;++i) { // No mesh is referencing this material, remove it. if (!abReferenced[i]) { ++unreferencedRemoved; @@ -147,8 +136,7 @@ void RemoveRedundantMatsProcess::Execute( aiScene* pScene) // Check all previously mapped materials for a matching hash. // On a match we can delete this material and just make it ref to the same index. uint32_t me = aiHashes[i] = ComputeMaterialHash(pScene->mMaterials[i]); - for (unsigned int a = 0; a < i;++a) - { + for (unsigned int a = 0; a < i;++a) { if (abReferenced[a] && me == aiHashes[a]) { ++redundantRemoved; me = 0; @@ -205,12 +193,9 @@ void RemoveRedundantMatsProcess::Execute( aiScene* pScene) delete[] aiHashes; delete[] aiMappingTable; } - if (redundantRemoved == 0 && unreferencedRemoved == 0) - { + if (redundantRemoved == 0 && unreferencedRemoved == 0) { ASSIMP_LOG_DEBUG("RemoveRedundantMatsProcess finished "); - } - else - { + } else { ASSIMP_LOG_INFO("RemoveRedundantMatsProcess finished. Removed ", redundantRemoved, " redundant and ", unreferencedRemoved, " unused materials."); } diff --git a/code/PostProcessing/RemoveVCProcess.cpp b/code/PostProcessing/RemoveVCProcess.cpp index 35047dc0a..bcad65423 100644 --- a/code/PostProcessing/RemoveVCProcess.cpp +++ b/code/PostProcessing/RemoveVCProcess.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, @@ -74,63 +72,6 @@ inline void ArrayDelete(T **&in, unsigned int &num) { num = 0; } -#if 0 -// ------------------------------------------------------------------------------------------------ -// Updates the node graph - removes all nodes which have the "remove" flag set and the -// "don't remove" flag not set. Nodes with meshes are never deleted. -bool UpdateNodeGraph(aiNode* node,std::list& childsOfParent,bool root) -{ - bool b = false; - - std::list mine; - for (unsigned int i = 0; i < node->mNumChildren;++i) - { - if(UpdateNodeGraph(node->mChildren[i],mine,false)) - b = true; - } - - // somewhat tricky ... mNumMeshes must be originally 0 and MSB2 may not be set, - // so we can do a simple comparison against MSB here - if (!root && AI_RC_UINT_MSB == node->mNumMeshes ) - { - // this node needs to be removed - if(node->mNumChildren) - { - childsOfParent.insert(childsOfParent.end(),mine.begin(),mine.end()); - - // set all children to nullptr to make sure they are not deleted when we delete ourself - for (unsigned int i = 0; i < node->mNumChildren;++i) - node->mChildren[i] = nullptr; - } - b = true; - delete node; - } - else - { - AI_RC_UNMASK(node->mNumMeshes); - childsOfParent.push_back(node); - - if (b) - { - // reallocate the array of our children here - node->mNumChildren = (unsigned int)mine.size(); - aiNode** const children = new aiNode*[mine.size()]; - aiNode** ptr = children; - - for (std::list::iterator it = mine.begin(), end = mine.end(); - it != end; ++it) - { - *ptr++ = *it; - } - delete[] node->mChildren; - node->mChildren = children; - return false; - } - } - return b; -} -#endif - // ------------------------------------------------------------------------------------------------ // Executes the post processing step on the given imported data. void RemoveVCProcess::Execute(aiScene *pScene) { diff --git a/code/PostProcessing/ScaleProcess.cpp b/code/PostProcessing/ScaleProcess.cpp index 665f28a7e..1bb9196f1 100644 --- a/code/PostProcessing/ScaleProcess.cpp +++ b/code/PostProcessing/ScaleProcess.cpp @@ -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, @@ -86,9 +85,9 @@ void ScaleProcess::Execute( aiScene* pScene ) { return; // nothing to scale } - ai_assert( mScale != 0 ); - ai_assert( nullptr != pScene ); - ai_assert( nullptr != pScene->mRootNode ); + ai_assert(mScale != 0 ); + ai_assert(nullptr != pScene ); + ai_assert(nullptr != pScene->mRootNode ); if ( nullptr == pScene ) { return; @@ -140,7 +139,7 @@ void ScaleProcess::Execute( aiScene* pScene ) { aiMatrix4x4 scaling; aiMatrix4x4::Scaling( aiVector3D(scale), scaling ); - aiMatrix4x4 RotMatrix = aiMatrix4x4 (rotation.GetMatrix()); + const aiMatrix4x4 RotMatrix = aiMatrix4x4(rotation.GetMatrix()); bone->mOffsetMatrix = translation * RotMatrix * scaling; } diff --git a/code/PostProcessing/SortByPTypeProcess.cpp b/code/PostProcessing/SortByPTypeProcess.cpp index 1be75fc48..47633dce5 100644 --- a/code/PostProcessing/SortByPTypeProcess.cpp +++ b/code/PostProcessing/SortByPTypeProcess.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, @@ -54,10 +52,7 @@ using namespace Assimp; // ------------------------------------------------------------------------------------------------ // Constructor to be privately used by Importer -SortByPTypeProcess::SortByPTypeProcess() : - mConfigRemoveMeshes(0) { - // empty -} +SortByPTypeProcess::SortByPTypeProcess() : mConfigRemoveMeshes(0) {} // ------------------------------------------------------------------------------------------------ // Returns whether the processing step is present in the given flag field. @@ -104,8 +99,9 @@ void UpdateNodes(const std::vector &replaceMeshIndex, aiNode *node } // call all subnodes recursively - for (unsigned int m = 0; m < node->mNumChildren; ++m) + for (unsigned int m = 0; m < node->mNumChildren; ++m) { UpdateNodes(replaceMeshIndex, node->mChildren[m]); + } } // ------------------------------------------------------------------------------------------------ @@ -155,7 +151,7 @@ void SortByPTypeProcess::Execute(aiScene *pScene) { if (1 == num) { if (!(mConfigRemoveMeshes & mesh->mPrimitiveTypes)) { *meshIdx = static_cast(outMeshes.size()); - outMeshes.push_back(mesh); + outMeshes.emplace_back(mesh); } else { delete mesh; pScene->mMeshes[i] = nullptr; @@ -311,21 +307,23 @@ void SortByPTypeProcess::Execute(aiScene *pScene) { if (vert) { *vert++ = mesh->mVertices[idx]; - //mesh->mVertices[idx].x = get_qnan(); } - if (nor) *nor++ = mesh->mNormals[idx]; + if (nor) + *nor++ = mesh->mNormals[idx]; if (tan) { *tan++ = mesh->mTangents[idx]; *bit++ = mesh->mBitangents[idx]; } for (unsigned int pp = 0; pp < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++pp) { - if (!uv[pp]) break; + if (!uv[pp]) + break; *uv[pp]++ = mesh->mTextureCoords[pp][idx]; } for (unsigned int pp = 0; pp < AI_MAX_NUMBER_OF_COLOR_SETS; ++pp) { - if (!cols[pp]) break; + if (!cols[pp]) + break; *cols[pp]++ = mesh->mColors[pp][idx]; } @@ -351,7 +349,7 @@ void SortByPTypeProcess::Execute(aiScene *pScene) { } } if (pp == mesh->mNumAnimMeshes) - amIdx++; + ++amIdx; in.mIndices[q] = outIdx++; } diff --git a/code/PostProcessing/SplitByBoneCountProcess.cpp b/code/PostProcessing/SplitByBoneCountProcess.cpp index 5324160d4..969146fee 100644 --- a/code/PostProcessing/SplitByBoneCountProcess.cpp +++ b/code/PostProcessing/SplitByBoneCountProcess.cpp @@ -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, @@ -58,9 +57,7 @@ using namespace Assimp::Formatter; // ------------------------------------------------------------------------------------------------ // Constructor -SplitByBoneCountProcess::SplitByBoneCountProcess() : mMaxBoneCount(AI_SBBC_DEFAULT_MAX_BONES) { - // empty -} +SplitByBoneCountProcess::SplitByBoneCountProcess() : mMaxBoneCount(AI_SBBC_DEFAULT_MAX_BONES) {} // ------------------------------------------------------------------------------------------------ // Returns whether the processing step is present in the given flag. @@ -166,7 +163,7 @@ void SplitByBoneCountProcess::SplitMesh( const aiMesh* pMesh, std::vector isBoneUsed( pMesh->mNumBones, false); // indices of the faces which are going to go into this submesh - std::vector subMeshFaces; + IndexArray subMeshFaces; subMeshFaces.reserve( pMesh->mNumFaces); // accumulated vertex count of all the faces in this submesh unsigned int numSubMeshVertices = 0; @@ -202,7 +199,7 @@ void SplitByBoneCountProcess::SplitMesh( const aiMesh* pMesh, std::vector::iterator it = newBonesAtCurrentFace.begin(); it != newBonesAtCurrentFace.end(); ++it) { if (!isBoneUsed[*it]) { isBoneUsed[*it] = true; - numBones++; + ++numBones; } } @@ -212,18 +209,17 @@ void SplitByBoneCountProcess::SplitMesh( const aiMesh* pMesh, std::vectormName.length > 0 ) - { + if( pMesh->mName.length > 0 ) { newMesh->mName.Set( format() << pMesh->mName.data << "_sub" << poNewMeshes.size()); } newMesh->mMaterialIndex = pMesh->mMaterialIndex; newMesh->mPrimitiveTypes = pMesh->mPrimitiveTypes; - poNewMeshes.push_back( newMesh); + poNewMeshes.emplace_back( newMesh); // create all the arrays for this mesh if the old mesh contained them newMesh->mNumVertices = numSubMeshVertices; @@ -251,7 +247,7 @@ void SplitByBoneCountProcess::SplitMesh( const aiMesh* pMesh, std::vectormFaces = new aiFace[subMeshFaces.size()]; unsigned int nvi = 0; // next vertex index - std::vector previousVertexIndices( numSubMeshVertices, std::numeric_limits::max()); // per new vertex: its index in the source mesh + IndexArray previousVertexIndices( numSubMeshVertices, std::numeric_limits::max()); // per new vertex: its index in the source mesh for( unsigned int a = 0; a < subMeshFaces.size(); ++a ) { const aiFace& srcFace = pMesh->mFaces[subMeshFaces[a]]; aiFace& dstFace = newMesh->mFaces[a]; @@ -399,10 +395,10 @@ void SplitByBoneCountProcess::SplitMesh( const aiMesh* pMesh, std::vectormNumMeshes == 0 ) { - std::vector newMeshList; + IndexArray newMeshList; for( unsigned int a = 0; a < pNode->mNumMeshes; ++a) { unsigned int srcIndex = pNode->mMeshes[a]; - const std::vector& replaceMeshes = mSubMeshIndices[srcIndex]; + const IndexArray& replaceMeshes = mSubMeshIndices[srcIndex]; newMeshList.insert( newMeshList.end(), replaceMeshes.begin(), replaceMeshes.end()); } diff --git a/code/PostProcessing/SplitByBoneCountProcess.h b/code/PostProcessing/SplitByBoneCountProcess.h index 625019e0c..efe85824f 100644 --- a/code/PostProcessing/SplitByBoneCountProcess.h +++ b/code/PostProcessing/SplitByBoneCountProcess.h @@ -76,6 +76,10 @@ public: /// basing on the Importer's configuration property list. virtual void SetupProperties(const Importer* pImp) override; + /// @brief Will return the maximal number of bones. + /// @return The maximal number of bones. + size_t getMaxNumberOfBones() const; + protected: /// Executes the post processing step on the given imported data. /// At the moment a process is not supposed to fail. @@ -90,14 +94,19 @@ protected: /// Recursively updates the node's mesh list to account for the changed mesh list void UpdateNode( aiNode* pNode) const; -public: +private: /// Max bone count. Splitting occurs if a mesh has more than that number of bones. size_t mMaxBoneCount; /// Per mesh index: Array of indices of the new submeshes. - std::vector< std::vector > mSubMeshIndices; + using IndexArray = std::vector; + std::vector mSubMeshIndices; }; +inline size_t SplitByBoneCountProcess::getMaxNumberOfBones() const { + return mMaxBoneCount; +} + } // end of namespace Assimp #endif // !!AI_SPLITBYBONECOUNTPROCESS_H_INC diff --git a/code/PostProcessing/SplitLargeMeshes.cpp b/code/PostProcessing/SplitLargeMeshes.cpp index 73e0cc5d8..b6e5b772a 100644 --- a/code/PostProcessing/SplitLargeMeshes.cpp +++ b/code/PostProcessing/SplitLargeMeshes.cpp @@ -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, @@ -40,9 +39,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ---------------------------------------------------------------------- */ -/** - * @file Implementation of the SplitLargeMeshes postprocessing step - */ + /// @file Implementation of the SplitLargeMeshes postprocessing step // internal headers of the post-processing framework #include "SplitLargeMeshes.h" @@ -75,22 +72,22 @@ void SplitLargeMeshesProcess_Triangle::Execute( aiScene* pScene) { this->SplitMesh(a, pScene->mMeshes[a],avList); } - if (avList.size() != pScene->mNumMeshes) { - // it seems something has been split. rebuild the mesh list - delete[] pScene->mMeshes; - pScene->mNumMeshes = (unsigned int)avList.size(); - pScene->mMeshes = new aiMesh*[avList.size()]; - - for (unsigned int i = 0; i < avList.size();++i) { - pScene->mMeshes[i] = avList[i].first; - } - - // now we need to update all nodes - this->UpdateNode(pScene->mRootNode,avList); - ASSIMP_LOG_INFO("SplitLargeMeshesProcess_Triangle finished. Meshes have been split"); - } else { + if (avList.size() == pScene->mNumMeshes) { ASSIMP_LOG_DEBUG("SplitLargeMeshesProcess_Triangle finished. There was nothing to do"); } + + // it seems something has been split. rebuild the mesh list + delete[] pScene->mMeshes; + pScene->mNumMeshes = (unsigned int)avList.size(); + pScene->mMeshes = new aiMesh*[avList.size()]; + + for (unsigned int i = 0; i < avList.size();++i) { + pScene->mMeshes[i] = avList[i].first; + } + + // now we need to update all nodes + this->UpdateNode(pScene->mRootNode,avList); + ASSIMP_LOG_INFO("SplitLargeMeshesProcess_Triangle finished. Meshes have been split"); } // ------------------------------------------------------------------------------------------------ @@ -102,8 +99,7 @@ void SplitLargeMeshesProcess_Triangle::SetupProperties( const Importer* pImp) { // ------------------------------------------------------------------------------------------------ // Update a node after some meshes have been split -void SplitLargeMeshesProcess_Triangle::UpdateNode(aiNode* pcNode, - const std::vector >& avList) { +void SplitLargeMeshesProcess_Triangle::UpdateNode(aiNode* pcNode, const std::vector >& avList) { // for every index in out list build a new entry std::vector aiEntries; aiEntries.reserve(pcNode->mNumMeshes + 1); diff --git a/code/PostProcessing/TextureTransform.cpp b/code/PostProcessing/TextureTransform.cpp index 2ed17f390..3de357c17 100644 --- a/code/PostProcessing/TextureTransform.cpp +++ b/code/PostProcessing/TextureTransform.cpp @@ -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, @@ -42,8 +41,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. /** @file A helper class that processes texture transformations */ - - #include #include #include @@ -494,8 +491,9 @@ void TextureTransformStep::Execute( aiScene* pScene) { ai_assert(nullptr != src); // Copy the data to the destination array - if (dest != src) + if (dest != src) { ::memcpy(dest,src,sizeof(aiVector3D)*mesh->mNumVertices); + } end = dest + mesh->mNumVertices; diff --git a/code/PostProcessing/TriangulateProcess.cpp b/code/PostProcessing/TriangulateProcess.cpp index 52cfa66bf..b4c66b41e 100644 --- a/code/PostProcessing/TriangulateProcess.cpp +++ b/code/PostProcessing/TriangulateProcess.cpp @@ -158,15 +158,13 @@ namespace { // ------------------------------------------------------------------------------------------------ // Returns whether the processing step is present in the given flag field. -bool TriangulateProcess::IsActive( unsigned int pFlags) const -{ +bool TriangulateProcess::IsActive( unsigned int pFlags) const { return (pFlags & aiProcess_Triangulate) != 0; } // ------------------------------------------------------------------------------------------------ // Executes the post processing step on the given imported data. -void TriangulateProcess::Execute( aiScene* pScene) -{ +void TriangulateProcess::Execute( aiScene* pScene) { ASSIMP_LOG_DEBUG("TriangulateProcess begin"); bool bHas = false; @@ -187,8 +185,7 @@ void TriangulateProcess::Execute( aiScene* pScene) // ------------------------------------------------------------------------------------------------ // Triangulates the given mesh. -bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh) -{ +bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh) { // Now we have aiMesh::mPrimitiveTypes, so this is only here for test cases if (!pMesh->mPrimitiveTypes) { bool bNeed = false; @@ -218,8 +215,7 @@ bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh) if( face.mNumIndices <= 3) { numOut++; - } - else { + } else { numOut += face.mNumIndices-2; max_out = std::max(max_out,face.mNumIndices); } @@ -511,22 +507,6 @@ bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh) #endif num = 0; break; - - /*curOut -= (max-num); // undo all previous work - for (tmp = 0; tmp < max-2; ++tmp) { - aiFace& nface = *curOut++; - - nface.mNumIndices = 3; - if (!nface.mIndices) - nface.mIndices = new unsigned int[3]; - - nface.mIndices[0] = 0; - nface.mIndices[1] = tmp+1; - nface.mIndices[2] = tmp+2; - - } - num = 0; - break;*/ } aiFace& nface = *curOut++; @@ -580,23 +560,6 @@ bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh) for(aiFace* f = last_face; f != curOut; ) { unsigned int* i = f->mIndices; - // drop dumb 0-area triangles - deactivated for now: - //FindDegenerates post processing step can do the same thing - //if (std::fabs(GetArea2D(temp_verts[i[0]],temp_verts[i[1]],temp_verts[i[2]])) < 1e-5f) { - // ASSIMP_LOG_VERBOSE_DEBUG("Dropping triangle with area 0"); - // --curOut; - - // delete[] f->mIndices; - // f->mIndices = nullptr; - - // for(aiFace* ff = f; ff != curOut; ++ff) { - // ff->mNumIndices = (ff+1)->mNumIndices; - // ff->mIndices = (ff+1)->mIndices; - // (ff+1)->mIndices = nullptr; - // } - // continue; - //} - i[0] = idx[i[0]]; i[1] = idx[i[1]]; i[2] = idx[i[2]]; diff --git a/code/PostProcessing/ValidateDataStructure.cpp b/code/PostProcessing/ValidateDataStructure.cpp index e31054972..14259e11a 100644 --- a/code/PostProcessing/ValidateDataStructure.cpp +++ b/code/PostProcessing/ValidateDataStructure.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, @@ -110,18 +108,21 @@ inline int HasNameMatch(const aiString &in, aiNode *node) { template inline void ValidateDSProcess::DoValidation(T **parray, unsigned int size, const char *firstName, const char *secondName) { // validate all entries - if (size) { - if (!parray) { - ReportError("aiScene::%s is nullptr (aiScene::%s is %i)", - firstName, secondName, size); - } - for (unsigned int i = 0; i < size; ++i) { - if (!parray[i]) { - ReportError("aiScene::%s[%i] is nullptr (aiScene::%s is %i)", - firstName, i, secondName, size); - } - Validate(parray[i]); + if (size == 0) { + return; + } + + if (!parray) { + ReportError("aiScene::%s is nullptr (aiScene::%s is %i)", + firstName, secondName, size); + } + + for (unsigned int i = 0; i < size; ++i) { + if (!parray[i]) { + ReportError("aiScene::%s[%i] is nullptr (aiScene::%s is %i)", + firstName, i, secondName, size); } + Validate(parray[i]); } } @@ -130,25 +131,27 @@ template inline void ValidateDSProcess::DoValidationEx(T **parray, unsigned int size, const char *firstName, const char *secondName) { // validate all entries - if (size) { - if (!parray) { - ReportError("aiScene::%s is nullptr (aiScene::%s is %i)", - firstName, secondName, size); + if (size == 0) { + return; + } + + if (!parray) { + ReportError("aiScene::%s is nullptr (aiScene::%s is %i)", + firstName, secondName, size); + } + for (unsigned int i = 0; i < size; ++i) { + if (!parray[i]) { + ReportError("aiScene::%s[%u] is nullptr (aiScene::%s is %u)", + firstName, i, secondName, size); } - for (unsigned int i = 0; i < size; ++i) { - if (!parray[i]) { - ReportError("aiScene::%s[%u] is nullptr (aiScene::%s is %u)", - firstName, i, secondName, size); - } - Validate(parray[i]); + Validate(parray[i]); - // check whether there are duplicate names - for (unsigned int a = i + 1; a < size; ++a) { - if (parray[i]->mName == parray[a]->mName) { - ReportError("aiScene::%s[%u] has the same name as " - "aiScene::%s[%u]", - firstName, i, secondName, a); - } + // check whether there are duplicate names + for (unsigned int a = i + 1; a < size; ++a) { + if (parray[i]->mName == parray[a]->mName) { + ReportError("aiScene::%s[%u] has the same name as " + "aiScene::%s[%u]", + firstName, i, secondName, a); } } } @@ -229,12 +232,6 @@ void ValidateDSProcess::Execute(aiScene *pScene) { if (pScene->mNumMaterials) { DoValidation(pScene->mMaterials, pScene->mNumMaterials, "mMaterials", "mNumMaterials"); } -#if 0 - // NOTE: ScenePreprocessor generates a default material if none is there - else if (!(mScene->mFlags & AI_SCENE_FLAGS_INCOMPLETE)) { - ReportError("aiScene::mNumMaterials is 0. At least one material must be there"); - } -#endif else if (pScene->mMaterials) { ReportError("aiScene::mMaterials is non-null although there are no materials"); } @@ -267,8 +264,7 @@ void ValidateDSProcess::Validate(const aiCamera *pCamera) { if (pCamera->mClipPlaneFar <= pCamera->mClipPlaneNear) ReportError("aiCamera::mClipPlaneFar must be >= aiCamera::mClipPlaneNear"); - // FIX: there are many 3ds files with invalid FOVs. No reason to - // reject them at all ... a warning is appropriate. + // There are many 3ds files with invalid FOVs. No reason to reject them at all ... a warning is appropriate. if (!pCamera->mHorizontalFOV || pCamera->mHorizontalFOV >= (float)AI_MATH_PI) ReportWarning("%f is not a valid value for aiCamera::mHorizontalFOV", pCamera->mHorizontalFOV); } @@ -290,7 +286,6 @@ void ValidateDSProcess::Validate(const aiMesh *pMesh) { switch (face.mNumIndices) { case 0: ReportError("aiMesh::mFaces[%i].mNumIndices is 0", i); - break; case 1: if (0 == (pMesh->mPrimitiveTypes & aiPrimitiveType_POINT)) { ReportError("aiMesh::mFaces[%i] is a POINT but aiMesh::mPrimitiveTypes " @@ -362,15 +357,6 @@ void ValidateDSProcess::Validate(const aiMesh *pMesh) { if (face.mIndices[a] >= pMesh->mNumVertices) { ReportError("aiMesh::mFaces[%i]::mIndices[%i] is out of range", i, a); } - // the MSB flag is temporarily used by the extra verbose - // mode to tell us that the JoinVerticesProcess might have - // been executed already. - /*if ( !(this->mScene->mFlags & AI_SCENE_FLAGS_NON_VERBOSE_FORMAT ) && !(this->mScene->mFlags & AI_SCENE_FLAGS_ALLOW_SHARED) && - abRefList[face.mIndices[a]]) - { - ReportError("aiMesh::mVertices[%i] is referenced twice - second " - "time by aiMesh::mFaces[%i]::mIndices[%i]",face.mIndices[a],i,a); - }*/ abRefList[face.mIndices[a]] = true; } } @@ -466,7 +452,7 @@ void ValidateDSProcess::Validate(const aiMesh *pMesh, const aiBone *pBone, float this->Validate(&pBone->mName); if (!pBone->mNumWeights) { - //ReportError("aiBone::mNumWeights is zero"); + ReportWarning("aiBone::mNumWeights is zero"); } // check whether all vertices affected by this bone are valid diff --git a/contrib/Open3DGC/o3dgcArithmeticCodec.cpp b/contrib/Open3DGC/o3dgcArithmeticCodec.cpp index 2ae70fa2e..c1935822d 100644 --- a/contrib/Open3DGC/o3dgcArithmeticCodec.cpp +++ b/contrib/Open3DGC/o3dgcArithmeticCodec.cpp @@ -92,6 +92,7 @@ namespace o3dgc // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - Static functions - - - - - - - - - - - - - - - - - - - - - - - - - - - + AI_WONT_RETURN static void AC_Error(const char * msg) AI_WONT_RETURN_SUFFIX; static void AC_Error(const char * msg) { fprintf(stderr, "\n\n -> Arithmetic coding error: "); diff --git a/contrib/unzip/unzip.c b/contrib/unzip/unzip.c index ba15257a9..4bc6773ef 100644 --- a/contrib/unzip/unzip.c +++ b/contrib/unzip/unzip.c @@ -78,7 +78,7 @@ # pragma warning(disable : 4131 4244 4189 4245) #endif // _MSC_VER -const char unz_copyright[] = +static const char unz_copyright[] = " unzip 1.01 Copyright 1998-2004 Gilles Vollant - http://www.winimage.com/zLibDll"; /* unz_file_info_internal contain internal info about a file in zipfile*/ diff --git a/fuzz/assimp_fuzzer.cc b/fuzz/assimp_fuzzer.cc index edb5fdbb5..e347f59cb 100644 --- a/fuzz/assimp_fuzzer.cc +++ b/fuzz/assimp_fuzzer.cc @@ -40,6 +40,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include +#include #include #include @@ -53,6 +54,13 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t dataSize) { const aiScene *sc = importer.ReadFileFromMemory(data, dataSize, aiProcessPreset_TargetRealtime_Quality, nullptr ); + if (sc == nullptr) { + return 0; + } + + Exporter exporter; + exporter.ExportToBlob(sc, "fbx"); + aiDetachLogStream(&stream); return 0; diff --git a/include/assimp/AssertHandler.h b/include/assimp/AssertHandler.h index 365a924b0..1247ff490 100644 --- a/include/assimp/AssertHandler.h +++ b/include/assimp/AssertHandler.h @@ -66,7 +66,7 @@ ASSIMP_API void setAiAssertHandler(AiAssertHandler handler); * * @brief This issues a message to stderr and calls abort. */ -ASSIMP_API void defaultAiAssertHandler(const char* failedExpression, const char* file, int line); +AI_WONT_RETURN ASSIMP_API void defaultAiAssertHandler(const char* failedExpression, const char* file, int line) AI_WONT_RETURN_SUFFIX; // --------------------------------------------------------------------------- /** diff --git a/include/assimp/DefaultIOStream.h b/include/assimp/DefaultIOStream.h index e8d9ed329..67cba3c5c 100644 --- a/include/assimp/DefaultIOStream.h +++ b/include/assimp/DefaultIOStream.h @@ -84,7 +84,7 @@ protected: public: /** Destructor public to allow simple deletion to close the file. */ - ~DefaultIOStream (); + ~DefaultIOStream () override; // ------------------------------------------------------------------- /// Read from stream diff --git a/include/assimp/MemoryIOWrapper.h b/include/assimp/MemoryIOWrapper.h index 1b986ff1b..4023f7529 100644 --- a/include/assimp/MemoryIOWrapper.h +++ b/include/assimp/MemoryIOWrapper.h @@ -65,8 +65,8 @@ namespace Assimp { // ---------------------------------------------------------------------------------- class MemoryIOStream : public IOStream { public: - MemoryIOStream (const uint8_t* buff, size_t len, bool own = false) : - buffer (buff), + MemoryIOStream (const uint8_t* buff, size_t len, bool own = false) : + buffer (buff), length(len), pos(static_cast(0)), own(own) { @@ -145,7 +145,7 @@ public: } /// @brief Destructor. - ~MemoryIOSystem() = default; + ~MemoryIOSystem() override = default; // ------------------------------------------------------------------- /// @brief Tests for the existence of a file at the given path. @@ -190,7 +190,7 @@ public: bool ComparePaths(const char* one, const char* second) const override { return existing_io ? existing_io->ComparePaths(one, second) : false; } - + /// @brief Will push the directory. bool PushDirectory( const std::string &path ) override { return existing_io ? existing_io->PushDirectory(path) : false; @@ -216,7 +216,7 @@ public: bool CreateDirectory( const std::string &path ) override { return existing_io ? existing_io->CreateDirectory(path) : false; } - + /// @brief Will change the directory. bool ChangeDirectory( const std::string &path ) override { return existing_io ? existing_io->ChangeDirectory(path) : false; diff --git a/include/assimp/StreamWriter.h b/include/assimp/StreamWriter.h index 1bdfcc650..50e28447c 100644 --- a/include/assimp/StreamWriter.h +++ b/include/assimp/StreamWriter.h @@ -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, @@ -68,8 +66,7 @@ namespace Assimp { */ // -------------------------------------------------------------------------------------------- template -class StreamWriter -{ +class StreamWriter { enum { INITIAL_CAPACITY = 1024 }; diff --git a/include/assimp/Vertex.h b/include/assimp/Vertex.h index fd7eb037e..3fc974504 100644 --- a/include/assimp/Vertex.h +++ b/include/assimp/Vertex.h @@ -97,15 +97,21 @@ namespace Assimp { * to *all* vertex components equally. This is useful for stuff like interpolation * or subdivision, but won't work if special handling is required for some vertex components. */ // ------------------------------------------------------------------------------------------------ -class Vertex { +struct Vertex { friend Vertex operator + (const Vertex&,const Vertex&); friend Vertex operator - (const Vertex&,const Vertex&); friend Vertex operator * (const Vertex&,ai_real); friend Vertex operator / (const Vertex&,ai_real); friend Vertex operator * (ai_real, const Vertex&); -public: - Vertex() {} + aiVector3D position; + aiVector3D normal; + aiVector3D tangent, bitangent; + + aiVector3D texcoords[AI_MAX_NUMBER_OF_TEXTURECOORDS]; + aiColor4D colors[AI_MAX_NUMBER_OF_COLOR_SETS]; + + Vertex() = default; // ---------------------------------------------------------------------------- /** Extract a particular vertex from a mesh and interleave all components */ @@ -178,7 +184,7 @@ public: } // ---------------------------------------------------------------------------- - /** Convert back to non-interleaved storage */ + /// Convert back to non-interleaved storage void SortBack(aiMesh* out, unsigned int idx) const { ai_assert(idxmNumVertices); out->mVertices[idx] = position; @@ -204,7 +210,7 @@ public: private: // ---------------------------------------------------------------------------- - /** Construct from two operands and a binary operation to combine them */ + /// Construct from two operands and a binary operation to combine them template