diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 000000000..dd84ea782 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,38 @@ +--- +name: Bug report +about: Create a report to help us improve +title: '' +labels: '' +assignees: '' + +--- + +**Describe the bug** +A clear and concise description of what the bug is. + +**To Reproduce** +Steps to reproduce the behavior: +1. Go to '...' +2. Click on '....' +3. Scroll down to '....' +4. See error + +**Expected behavior** +A clear and concise description of what you expected to happen. + +**Screenshots** +If applicable, add screenshots to help explain your problem. + +**Desktop (please complete the following information):** + - OS: [e.g. iOS] + - Browser [e.g. chrome, safari] + - Version [e.g. 22] + +**Smartphone (please complete the following information):** + - Device: [e.g. iPhone6] + - OS: [e.g. iOS8.1] + - Browser [e.g. stock browser, safari] + - Version [e.g. 22] + +**Additional context** +Add any other context about the problem here. diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 000000000..bbcbbe7d6 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,20 @@ +--- +name: Feature request +about: Suggest an idea for this project +title: '' +labels: '' +assignees: '' + +--- + +**Is your feature request related to a problem? Please describe.** +A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] + +**Describe the solution you'd like** +A clear and concise description of what you want to happen. + +**Describe alternatives you've considered** +A clear and concise description of any alternative solutions or features you've considered. + +**Additional context** +Add any other context or screenshots about the feature request here. diff --git a/code/AMF/AMFImporter.cpp b/code/AMF/AMFImporter.cpp new file mode 100644 index 000000000..d93ca54cf --- /dev/null +++ b/code/AMF/AMFImporter.cpp @@ -0,0 +1,707 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2020, 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 AMFImporter.cpp +/// \brief AMF-format files importer for Assimp: main algorithm implementation. +/// \date 2016 +/// \author smal.root@gmail.com + +#ifndef ASSIMP_BUILD_NO_AMF_IMPORTER + +// Header files, Assimp. +#include "AMFImporter.hpp" +#include "AMFImporter_Macro.hpp" + +#include +#include + +// Header files, stdlib. +#include + +namespace Assimp +{ + +/// \var aiImporterDesc AMFImporter::Description +/// Conastant which hold importer description +const aiImporterDesc AMFImporter::Description = { + "Additive manufacturing file format(AMF) Importer", + "smalcom", + "", + "See documentation in source code. Chapter: Limitations.", + aiImporterFlags_SupportTextFlavour | aiImporterFlags_LimitedSupport | aiImporterFlags_Experimental, + 0, + 0, + 0, + 0, + "amf" +}; + +void AMFImporter::Clear() +{ + mNodeElement_Cur = nullptr; + mUnit.clear(); + mMaterial_Converted.clear(); + mTexture_Converted.clear(); + // Delete all elements + if(!mNodeElement_List.empty()) + { + for(CAMFImporter_NodeElement* ne: mNodeElement_List) { delete ne; } + + mNodeElement_List.clear(); + } +} + +AMFImporter::~AMFImporter() +{ + if(mReader != nullptr) delete mReader; + // Clear() is accounting if data already is deleted. So, just check again if all data is deleted. + Clear(); +} + +/*********************************************************************************************************************************************/ +/************************************************************ Functions: find set ************************************************************/ +/*********************************************************************************************************************************************/ + +bool AMFImporter::Find_NodeElement(const std::string& pID, const CAMFImporter_NodeElement::EType pType, CAMFImporter_NodeElement** pNodeElement) const +{ + for(CAMFImporter_NodeElement* ne: mNodeElement_List) + { + if((ne->ID == pID) && (ne->Type == pType)) + { + if(pNodeElement != nullptr) *pNodeElement = ne; + + return true; + } + }// for(CAMFImporter_NodeElement* ne: mNodeElement_List) + + return false; +} + +bool AMFImporter::Find_ConvertedNode(const std::string& pID, std::list& pNodeList, aiNode** pNode) const +{ +aiString node_name(pID.c_str()); + + for(aiNode* node: pNodeList) + { + if(node->mName == node_name) + { + if(pNode != nullptr) *pNode = node; + + return true; + } + }// for(aiNode* node: pNodeList) + + return false; +} + +bool AMFImporter::Find_ConvertedMaterial(const std::string& pID, const SPP_Material** pConvertedMaterial) const +{ + for(const SPP_Material& mat: mMaterial_Converted) + { + if(mat.ID == pID) + { + if(pConvertedMaterial != nullptr) *pConvertedMaterial = &mat; + + return true; + } + }// for(const SPP_Material& mat: mMaterial_Converted) + + return false; +} + +/*********************************************************************************************************************************************/ +/************************************************************ Functions: throw set ***********************************************************/ +/*********************************************************************************************************************************************/ + +void AMFImporter::Throw_CloseNotFound(const std::string& pNode) +{ + throw DeadlyImportError("Close tag for node <" + pNode + "> not found. Seems file is corrupt."); +} + +void AMFImporter::Throw_IncorrectAttr(const std::string& pAttrName) +{ + throw DeadlyImportError("Node <" + std::string(mReader->getNodeName()) + "> has incorrect attribute \"" + pAttrName + "\"."); +} + +void AMFImporter::Throw_IncorrectAttrValue(const std::string& pAttrName) +{ + throw DeadlyImportError("Attribute \"" + pAttrName + "\" in node <" + std::string(mReader->getNodeName()) + "> has incorrect value."); +} + +void AMFImporter::Throw_MoreThanOnceDefined(const std::string& pNodeType, const std::string& pDescription) +{ + throw DeadlyImportError("\"" + pNodeType + "\" node can be used only once in " + mReader->getNodeName() + ". Description: " + pDescription); +} + +void AMFImporter::Throw_ID_NotFound(const std::string& pID) const +{ + throw DeadlyImportError("Not found node with name \"" + pID + "\"."); +} + +/*********************************************************************************************************************************************/ +/************************************************************* Functions: XML set ************************************************************/ +/*********************************************************************************************************************************************/ + +void AMFImporter::XML_CheckNode_MustHaveChildren() +{ + if(mReader->isEmptyElement()) throw DeadlyImportError(std::string("Node <") + mReader->getNodeName() + "> must have children."); +} + +void AMFImporter::XML_CheckNode_SkipUnsupported(const std::string& pParentNodeName) +{ + static const size_t Uns_Skip_Len = 3; + const char* Uns_Skip[Uns_Skip_Len] = { "composite", "edge", "normal" }; + + static bool skipped_before[Uns_Skip_Len] = { false, false, false }; + + std::string nn(mReader->getNodeName()); + bool found = false; + bool close_found = false; + size_t sk_idx; + + for(sk_idx = 0; sk_idx < Uns_Skip_Len; sk_idx++) + { + if(nn != Uns_Skip[sk_idx]) continue; + + found = true; + if(mReader->isEmptyElement()) + { + close_found = true; + + goto casu_cres; + } + + while(mReader->read()) + { + if((mReader->getNodeType() == irr::io::EXN_ELEMENT_END) && (nn == mReader->getNodeName())) + { + close_found = true; + + goto casu_cres; + } + } + }// for(sk_idx = 0; sk_idx < Uns_Skip_Len; sk_idx++) + +casu_cres: + + if(!found) throw DeadlyImportError("Unknown node \"" + nn + "\" in " + pParentNodeName + "."); + if(!close_found) Throw_CloseNotFound(nn); + + if(!skipped_before[sk_idx]) + { + skipped_before[sk_idx] = true; + ASSIMP_LOG_WARN_F("Skipping node \"", nn, "\" in ", pParentNodeName, "."); + } +} + +bool AMFImporter::XML_SearchNode(const std::string& pNodeName) +{ + while(mReader->read()) + { + if((mReader->getNodeType() == irr::io::EXN_ELEMENT) && XML_CheckNode_NameEqual(pNodeName)) return true; + } + + return false; +} + +bool AMFImporter::XML_ReadNode_GetAttrVal_AsBool(const int pAttrIdx) +{ + std::string val(mReader->getAttributeValue(pAttrIdx)); + + if((val == "false") || (val == "0")) + return false; + else if((val == "true") || (val == "1")) + return true; + else + throw DeadlyImportError("Bool attribute value can contain \"false\"/\"0\" or \"true\"/\"1\" not the \"" + val + "\""); +} + +float AMFImporter::XML_ReadNode_GetAttrVal_AsFloat(const int pAttrIdx) +{ + std::string val; + float tvalf; + + ParseHelper_FixTruncatedFloatString(mReader->getAttributeValue(pAttrIdx), val); + fast_atoreal_move(val.c_str(), tvalf, false); + + return tvalf; +} + +uint32_t AMFImporter::XML_ReadNode_GetAttrVal_AsU32(const int pAttrIdx) +{ + return strtoul10(mReader->getAttributeValue(pAttrIdx)); +} + +float AMFImporter::XML_ReadNode_GetVal_AsFloat() +{ + std::string val; + float tvalf; + + if(!mReader->read()) throw DeadlyImportError("XML_ReadNode_GetVal_AsFloat. No data, seems file is corrupt."); + if(mReader->getNodeType() != irr::io::EXN_TEXT) throw DeadlyImportError("XML_ReadNode_GetVal_AsFloat. Invalid type of XML element, seems file is corrupt."); + + ParseHelper_FixTruncatedFloatString(mReader->getNodeData(), val); + fast_atoreal_move(val.c_str(), tvalf, false); + + return tvalf; +} + +uint32_t AMFImporter::XML_ReadNode_GetVal_AsU32() +{ + if(!mReader->read()) throw DeadlyImportError("XML_ReadNode_GetVal_AsU32. No data, seems file is corrupt."); + if(mReader->getNodeType() != irr::io::EXN_TEXT) throw DeadlyImportError("XML_ReadNode_GetVal_AsU32. Invalid type of XML element, seems file is corrupt."); + + return strtoul10(mReader->getNodeData()); +} + +void AMFImporter::XML_ReadNode_GetVal_AsString(std::string& pValue) +{ + if(!mReader->read()) throw DeadlyImportError("XML_ReadNode_GetVal_AsString. No data, seems file is corrupt."); + if(mReader->getNodeType() != irr::io::EXN_TEXT) + throw DeadlyImportError("XML_ReadNode_GetVal_AsString. Invalid type of XML element, seems file is corrupt."); + + pValue = mReader->getNodeData(); +} + +/*********************************************************************************************************************************************/ +/************************************************************ Functions: parse set ***********************************************************/ +/*********************************************************************************************************************************************/ + +void AMFImporter::ParseHelper_Node_Enter(CAMFImporter_NodeElement* pNode) +{ + mNodeElement_Cur->Child.push_back(pNode);// add new element to current element child list. + mNodeElement_Cur = pNode;// switch current element to new one. +} + +void AMFImporter::ParseHelper_Node_Exit() +{ + // check if we can walk up. + if(mNodeElement_Cur != nullptr) mNodeElement_Cur = mNodeElement_Cur->Parent; +} + +void AMFImporter::ParseHelper_FixTruncatedFloatString(const char* pInStr, std::string& pOutString) +{ + size_t instr_len; + + pOutString.clear(); + instr_len = strlen(pInStr); + if(!instr_len) return; + + pOutString.reserve(instr_len * 3 / 2); + // check and correct floats in format ".x". Must be "x.y". + if(pInStr[0] == '.') pOutString.push_back('0'); + + pOutString.push_back(pInStr[0]); + for(size_t ci = 1; ci < instr_len; ci++) + { + if((pInStr[ci] == '.') && ((pInStr[ci - 1] == ' ') || (pInStr[ci - 1] == '-') || (pInStr[ci - 1] == '+') || (pInStr[ci - 1] == '\t'))) + { + pOutString.push_back('0'); + pOutString.push_back('.'); + } + else + { + pOutString.push_back(pInStr[ci]); + } + } +} + +static bool ParseHelper_Decode_Base64_IsBase64(const char pChar) +{ + return (isalnum(pChar) || (pChar == '+') || (pChar == '/')); +} + +void AMFImporter::ParseHelper_Decode_Base64(const std::string& pInputBase64, std::vector& pOutputData) const +{ + // With help from + // René Nyffenegger http://www.adp-gmbh.ch/cpp/common/base64.html + const std::string base64_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + + uint8_t tidx = 0; + uint8_t arr4[4], arr3[3]; + + // check input data + if(pInputBase64.size() % 4) throw DeadlyImportError("Base64-encoded data must have size multiply of four."); + // prepare output place + pOutputData.clear(); + pOutputData.reserve(pInputBase64.size() / 4 * 3); + + for(size_t in_len = pInputBase64.size(), in_idx = 0; (in_len > 0) && (pInputBase64[in_idx] != '='); in_len--) + { + if(ParseHelper_Decode_Base64_IsBase64(pInputBase64[in_idx])) + { + arr4[tidx++] = pInputBase64[in_idx++]; + if(tidx == 4) + { + for(tidx = 0; tidx < 4; tidx++) arr4[tidx] = (uint8_t)base64_chars.find(arr4[tidx]); + + arr3[0] = (arr4[0] << 2) + ((arr4[1] & 0x30) >> 4); + arr3[1] = ((arr4[1] & 0x0F) << 4) + ((arr4[2] & 0x3C) >> 2); + arr3[2] = ((arr4[2] & 0x03) << 6) + arr4[3]; + for(tidx = 0; tidx < 3; tidx++) pOutputData.push_back(arr3[tidx]); + + tidx = 0; + }// if(tidx == 4) + }// if(ParseHelper_Decode_Base64_IsBase64(pInputBase64[in_idx])) + else + { + in_idx++; + }// if(ParseHelper_Decode_Base64_IsBase64(pInputBase64[in_idx])) else + } + + if(tidx) + { + for(uint8_t i = tidx; i < 4; i++) arr4[i] = 0; + for(uint8_t i = 0; i < 4; i++) arr4[i] = (uint8_t)(base64_chars.find(arr4[i])); + + arr3[0] = (arr4[0] << 2) + ((arr4[1] & 0x30) >> 4); + arr3[1] = ((arr4[1] & 0x0F) << 4) + ((arr4[2] & 0x3C) >> 2); + arr3[2] = ((arr4[2] & 0x03) << 6) + arr4[3]; + for(uint8_t i = 0; i < (tidx - 1); i++) pOutputData.push_back(arr3[i]); + } +} + +void AMFImporter::ParseFile(const std::string& pFile, IOSystem* pIOHandler) +{ + irr::io::IrrXMLReader* OldReader = mReader;// store current XMLreader. + std::unique_ptr file(pIOHandler->Open(pFile, "rb")); + + // Check whether we can read from the file + if (file.get() == nullptr) { + throw DeadlyImportError("Failed to open AMF file " + pFile + "."); + } + + // generate a XML reader for it + std::unique_ptr mIOWrapper(new CIrrXML_IOStreamReader(file.get())); + mReader = irr::io::createIrrXMLReader(mIOWrapper.get()); + if(!mReader) throw DeadlyImportError("Failed to create XML reader for file" + pFile + "."); + // + // start reading + // search for root tag + if(XML_SearchNode("amf")) + ParseNode_Root(); + else + throw DeadlyImportError("Root node \"amf\" not found."); + + delete mReader; + // restore old XMLreader + mReader = OldReader; +} + +// +// +// Root XML element. +// Multi elements - No. +void AMFImporter::ParseNode_Root() +{ + std::string unit, version; + CAMFImporter_NodeElement *ne( nullptr ); + + // Read attributes for node . + MACRO_ATTRREAD_LOOPBEG; + MACRO_ATTRREAD_CHECK_RET("unit", unit, mReader->getAttributeValue); + MACRO_ATTRREAD_CHECK_RET("version", version, mReader->getAttributeValue); + MACRO_ATTRREAD_LOOPEND_WSKIP; + + // Check attributes + if(!mUnit.empty()) + { + if((mUnit != "inch") && (mUnit != "millimeter") && (mUnit != "meter") && (mUnit != "feet") && (mUnit != "micron")) Throw_IncorrectAttrValue("unit"); + } + + // create root node element. + ne = new CAMFImporter_NodeElement_Root(nullptr); + mNodeElement_Cur = ne;// set first "current" element + // and assign attribute's values + ((CAMFImporter_NodeElement_Root*)ne)->Unit = unit; + ((CAMFImporter_NodeElement_Root*)ne)->Version = version; + + // Check for child nodes + if(!mReader->isEmptyElement()) + { + MACRO_NODECHECK_LOOPBEGIN("amf"); + if(XML_CheckNode_NameEqual("object")) { ParseNode_Object(); continue; } + if(XML_CheckNode_NameEqual("material")) { ParseNode_Material(); continue; } + if(XML_CheckNode_NameEqual("texture")) { ParseNode_Texture(); continue; } + if(XML_CheckNode_NameEqual("constellation")) { ParseNode_Constellation(); continue; } + if(XML_CheckNode_NameEqual("metadata")) { ParseNode_Metadata(); continue; } + MACRO_NODECHECK_LOOPEND("amf"); + mNodeElement_Cur = ne;// force restore "current" element + }// if(!mReader->isEmptyElement()) + + mNodeElement_List.push_back(ne);// add to node element list because its a new object in graph. +} + +// +// +// A collection of objects or constellations with specific relative locations. +// Multi elements - Yes. +// Parent element - . +void AMFImporter::ParseNode_Constellation() +{ + std::string id; + CAMFImporter_NodeElement* ne( nullptr ); + + // Read attributes for node . + MACRO_ATTRREAD_LOOPBEG; + MACRO_ATTRREAD_CHECK_RET("id", id, mReader->getAttributeValue); + MACRO_ATTRREAD_LOOPEND; + + // create and if needed - define new grouping object. + ne = new CAMFImporter_NodeElement_Constellation(mNodeElement_Cur); + + CAMFImporter_NodeElement_Constellation& als = *((CAMFImporter_NodeElement_Constellation*)ne);// alias for convenience + + if(!id.empty()) als.ID = id; + // Check for child nodes + if(!mReader->isEmptyElement()) + { + ParseHelper_Node_Enter(ne); + MACRO_NODECHECK_LOOPBEGIN("constellation"); + if(XML_CheckNode_NameEqual("instance")) { ParseNode_Instance(); continue; } + if(XML_CheckNode_NameEqual("metadata")) { ParseNode_Metadata(); continue; } + MACRO_NODECHECK_LOOPEND("constellation"); + ParseHelper_Node_Exit(); + }// if(!mReader->isEmptyElement()) + else + { + mNodeElement_Cur->Child.push_back(ne);// Add element to child list of current element + }// if(!mReader->isEmptyElement()) else + + mNodeElement_List.push_back(ne);// and to node element list because its a new object in graph. +} + +// +// +// A collection of objects or constellations with specific relative locations. +// Multi elements - Yes. +// Parent element - . +void AMFImporter::ParseNode_Instance() +{ + std::string objectid; + CAMFImporter_NodeElement* ne( nullptr ); + + // Read attributes for node . + MACRO_ATTRREAD_LOOPBEG; + MACRO_ATTRREAD_CHECK_RET("objectid", objectid, mReader->getAttributeValue); + MACRO_ATTRREAD_LOOPEND; + + // used object id must be defined, check that. + if(objectid.empty()) throw DeadlyImportError("\"objectid\" in must be defined."); + // create and define new grouping object. + ne = new CAMFImporter_NodeElement_Instance(mNodeElement_Cur); + + CAMFImporter_NodeElement_Instance& als = *((CAMFImporter_NodeElement_Instance*)ne);// alias for convenience + + als.ObjectID = objectid; + // Check for child nodes + if(!mReader->isEmptyElement()) + { + bool read_flag[6] = { false, false, false, false, false, false }; + + als.Delta.Set(0, 0, 0); + als.Rotation.Set(0, 0, 0); + ParseHelper_Node_Enter(ne); + MACRO_NODECHECK_LOOPBEGIN("instance"); + MACRO_NODECHECK_READCOMP_F("deltax", read_flag[0], als.Delta.x); + MACRO_NODECHECK_READCOMP_F("deltay", read_flag[1], als.Delta.y); + MACRO_NODECHECK_READCOMP_F("deltaz", read_flag[2], als.Delta.z); + MACRO_NODECHECK_READCOMP_F("rx", read_flag[3], als.Rotation.x); + MACRO_NODECHECK_READCOMP_F("ry", read_flag[4], als.Rotation.y); + MACRO_NODECHECK_READCOMP_F("rz", read_flag[5], als.Rotation.z); + MACRO_NODECHECK_LOOPEND("instance"); + ParseHelper_Node_Exit(); + // also convert degrees to radians. + als.Rotation.x = AI_MATH_PI_F * als.Rotation.x / 180.0f; + als.Rotation.y = AI_MATH_PI_F * als.Rotation.y / 180.0f; + als.Rotation.z = AI_MATH_PI_F * als.Rotation.z / 180.0f; + }// if(!mReader->isEmptyElement()) + else + { + mNodeElement_Cur->Child.push_back(ne);// Add element to child list of current element + }// if(!mReader->isEmptyElement()) else + + mNodeElement_List.push_back(ne);// and to node element list because its a new object in graph. +} + +// +// +// An object definition. +// Multi elements - Yes. +// Parent element - . +void AMFImporter::ParseNode_Object() +{ + std::string id; + CAMFImporter_NodeElement* ne( nullptr ); + + // Read attributes for node . + MACRO_ATTRREAD_LOOPBEG; + MACRO_ATTRREAD_CHECK_RET("id", id, mReader->getAttributeValue); + MACRO_ATTRREAD_LOOPEND; + + // create and if needed - define new geometry object. + ne = new CAMFImporter_NodeElement_Object(mNodeElement_Cur); + + CAMFImporter_NodeElement_Object& als = *((CAMFImporter_NodeElement_Object*)ne);// alias for convenience + + if(!id.empty()) als.ID = id; + // Check for child nodes + if(!mReader->isEmptyElement()) + { + bool col_read = false; + + ParseHelper_Node_Enter(ne); + MACRO_NODECHECK_LOOPBEGIN("object"); + if(XML_CheckNode_NameEqual("color")) + { + // Check if color already defined for object. + if(col_read) Throw_MoreThanOnceDefined("color", "Only one color can be defined for ."); + // read data and set flag about it + ParseNode_Color(); + col_read = true; + + continue; + } + + if(XML_CheckNode_NameEqual("mesh")) { ParseNode_Mesh(); continue; } + if(XML_CheckNode_NameEqual("metadata")) { ParseNode_Metadata(); continue; } + MACRO_NODECHECK_LOOPEND("object"); + ParseHelper_Node_Exit(); + }// if(!mReader->isEmptyElement()) + else + { + mNodeElement_Cur->Child.push_back(ne);// Add element to child list of current element + }// if(!mReader->isEmptyElement()) else + + mNodeElement_List.push_back(ne);// and to node element list because its a new object in graph. +} + +// +// +// Specify additional information about an entity. +// Multi elements - Yes. +// Parent element - , , , , . +// +// Reserved types are: +// "Name" - The alphanumeric label of the entity, to be used by the interpreter if interacting with the user. +// "Description" - A description of the content of the entity +// "URL" - A link to an external resource relating to the entity +// "Author" - Specifies the name(s) of the author(s) of the entity +// "Company" - Specifying the company generating the entity +// "CAD" - specifies the name of the originating CAD software and version +// "Revision" - specifies the revision of the entity +// "Tolerance" - specifies the desired manufacturing tolerance of the entity in entity's unit system +// "Volume" - specifies the total volume of the entity, in the entity's unit system, to be used for verification (object and volume only) +void AMFImporter::ParseNode_Metadata() +{ + std::string type, value; + CAMFImporter_NodeElement* ne( nullptr ); + + // read attribute + MACRO_ATTRREAD_LOOPBEG; + MACRO_ATTRREAD_CHECK_RET("type", type, mReader->getAttributeValue); + MACRO_ATTRREAD_LOOPEND; + // and value of node. + value = mReader->getNodeData(); + // Create node element and assign read data. + ne = new CAMFImporter_NodeElement_Metadata(mNodeElement_Cur); + ((CAMFImporter_NodeElement_Metadata*)ne)->Type = type; + ((CAMFImporter_NodeElement_Metadata*)ne)->Value = value; + mNodeElement_Cur->Child.push_back(ne);// Add element to child list of current element + mNodeElement_List.push_back(ne);// and to node element list because its a new object in graph. +} + +/*********************************************************************************************************************************************/ +/******************************************************** Functions: BaseImporter set ********************************************************/ +/*********************************************************************************************************************************************/ + +bool AMFImporter::CanRead(const std::string& pFile, IOSystem* pIOHandler, bool pCheckSig) const +{ + const std::string extension = GetExtension(pFile); + + if ( extension == "amf" ) { + return true; + } + + if(!extension.length() || pCheckSig) + { + const char* tokens[] = { "& pExtensionList) +{ + pExtensionList.insert("amf"); +} + +const aiImporterDesc* AMFImporter::GetInfo () const +{ + return &Description; +} + +void AMFImporter::InternReadFile(const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler) +{ + Clear();// delete old graph. + ParseFile(pFile, pIOHandler); + Postprocess_BuildScene(pScene); + // scene graph is ready, exit. +} + +}// namespace Assimp + +#endif // !ASSIMP_BUILD_NO_AMF_IMPORTER diff --git a/code/AssetLib/3DS/3DSExporter.cpp b/code/AssetLib/3DS/3DSExporter.cpp index 5f3d955da..fed96a51f 100644 --- a/code/AssetLib/3DS/3DSExporter.cpp +++ b/code/AssetLib/3DS/3DSExporter.cpp @@ -367,7 +367,7 @@ void Discreet3DSExporter::WriteTexture(const aiMaterial &mat, aiTextureType type aiTextureMapMode_Wrap, aiTextureMapMode_Wrap }; ai_real blend = 1.0; - if (mat.GetTexture(type, 0, &path, NULL, NULL, &blend, NULL, map_mode) != AI_SUCCESS || !path.length) { + if (mat.GetTexture(type, 0, &path, nullptr, nullptr, &blend, nullptr, map_mode) != AI_SUCCESS || !path.length) { return; } diff --git a/code/AssetLib/3DS/3DSHelper.h b/code/AssetLib/3DS/3DSHelper.h index e348c090d..89c15f5f2 100644 --- a/code/AssetLib/3DS/3DSHelper.h +++ b/code/AssetLib/3DS/3DSHelper.h @@ -462,30 +462,28 @@ struct Material { sTexAmbient(other.sTexAmbient), mTwoSided(other.mTwoSided) { // empty - } //! Move constructor. This is explicitly written because MSVC doesn't support defaulting it - Material(Material &&other) AI_NO_EXCEPT : - mName(std::move(other.mName)), - mDiffuse(std::move(other.mDiffuse)), - mSpecularExponent(std::move(other.mSpecularExponent)), - mShininessStrength(std::move(other.mShininessStrength)), - mSpecular(std::move(other.mSpecular)), - mAmbient(std::move(other.mAmbient)), - mShading(std::move(other.mShading)), - mTransparency(std::move(other.mTransparency)), - sTexDiffuse(std::move(other.sTexDiffuse)), - sTexOpacity(std::move(other.sTexOpacity)), - sTexSpecular(std::move(other.sTexSpecular)), - sTexReflective(std::move(other.sTexReflective)), - sTexBump(std::move(other.sTexBump)), - sTexEmissive(std::move(other.sTexEmissive)), - sTexShininess(std::move(other.sTexShininess)), - mBumpHeight(std::move(other.mBumpHeight)), - mEmissive(std::move(other.mEmissive)), - sTexAmbient(std::move(other.sTexAmbient)), - mTwoSided(std::move(other.mTwoSided)) { + Material(Material &&other) AI_NO_EXCEPT : mName(std::move(other.mName)), + mDiffuse(std::move(other.mDiffuse)), + mSpecularExponent(std::move(other.mSpecularExponent)), + mShininessStrength(std::move(other.mShininessStrength)), + mSpecular(std::move(other.mSpecular)), + mAmbient(std::move(other.mAmbient)), + mShading(std::move(other.mShading)), + mTransparency(std::move(other.mTransparency)), + sTexDiffuse(std::move(other.sTexDiffuse)), + sTexOpacity(std::move(other.sTexOpacity)), + sTexSpecular(std::move(other.sTexSpecular)), + sTexReflective(std::move(other.sTexReflective)), + sTexBump(std::move(other.sTexBump)), + sTexEmissive(std::move(other.sTexEmissive)), + sTexShininess(std::move(other.sTexShininess)), + mBumpHeight(std::move(other.mBumpHeight)), + mEmissive(std::move(other.mEmissive)), + sTexAmbient(std::move(other.sTexAmbient)), + mTwoSided(std::move(other.mTwoSided)) { // empty } @@ -615,7 +613,12 @@ struct Node { Node() = delete; explicit Node(const std::string &name) : - mParent(NULL), mName(name), mInstanceNumber(0), mHierarchyPos(0), mHierarchyIndex(0), mInstanceCount(1) { + mParent(nullptr), + mName(name), + mInstanceNumber(0), + mHierarchyPos(0), + mHierarchyIndex(0), + mInstanceCount(1) { aRotationKeys.reserve(20); aPositionKeys.reserve(20); aScalingKeys.reserve(20); diff --git a/code/AssetLib/3MF/D3MFImporter.cpp b/code/AssetLib/3MF/D3MFImporter.cpp index 9fc9a653d..2093e5e9a 100644 --- a/code/AssetLib/3MF/D3MFImporter.cpp +++ b/code/AssetLib/3MF/D3MFImporter.cpp @@ -314,19 +314,19 @@ private: ++buf; comp[1] = *buf; ++buf; - diffuse.r = static_cast(strtol(comp, NULL, 16)) / ai_real(255.0); + diffuse.r = static_cast(strtol(comp, nullptr, 16)) / ai_real(255.0); comp[0] = *buf; ++buf; comp[1] = *buf; ++buf; - diffuse.g = static_cast(strtol(comp, NULL, 16)) / ai_real(255.0); + diffuse.g = static_cast(strtol(comp, nullptr, 16)) / ai_real(255.0); comp[0] = *buf; ++buf; comp[1] = *buf; ++buf; - diffuse.b = static_cast(strtol(comp, NULL, 16)) / ai_real(255.0); + diffuse.b = static_cast(strtol(comp, nullptr, 16)) / ai_real(255.0); if (7 == len) return true; @@ -334,7 +334,7 @@ private: ++buf; comp[1] = *buf; ++buf; - diffuse.a = static_cast(strtol(comp, NULL, 16)) / ai_real(255.0); + diffuse.a = static_cast(strtol(comp, nullptr, 16)) / ai_real(255.0); return true; } diff --git a/code/AssetLib/3MF/D3MFOpcPackage.cpp b/code/AssetLib/3MF/D3MFOpcPackage.cpp index 64300ed83..e8e1e2f5e 100644 --- a/code/AssetLib/3MF/D3MFOpcPackage.cpp +++ b/code/AssetLib/3MF/D3MFOpcPackage.cpp @@ -45,19 +45,19 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "D3MFOpcPackage.h" #include +#include +#include +#include #include #include -#include -#include -#include -#include -#include -#include -#include +#include "3MFXmlTags.h" #include #include -#include "3MFXmlTags.h" +#include +#include +#include +#include namespace Assimp { @@ -68,49 +68,45 @@ typedef std::shared_ptr OpcPackageRelationshipPtr; class OpcPackageRelationshipReader { public: - OpcPackageRelationshipReader(XmlReader* xmlReader) { - while(xmlReader->read()) { - if(xmlReader->getNodeType() == irr::io::EXN_ELEMENT && - xmlReader->getNodeName() == XmlTag::RELS_RELATIONSHIP_CONTAINER) - { + OpcPackageRelationshipReader(XmlReader *xmlReader) { + while (xmlReader->read()) { + if (xmlReader->getNodeType() == irr::io::EXN_ELEMENT && + xmlReader->getNodeName() == XmlTag::RELS_RELATIONSHIP_CONTAINER) { ParseRootNode(xmlReader); } } } - void ParseRootNode(XmlReader* xmlReader) - { + void ParseRootNode(XmlReader *xmlReader) { ParseAttributes(xmlReader); - while(xmlReader->read()) - { - if(xmlReader->getNodeType() == irr::io::EXN_ELEMENT && - xmlReader->getNodeName() == XmlTag::RELS_RELATIONSHIP_NODE) - { + while (xmlReader->read()) { + if (xmlReader->getNodeType() == irr::io::EXN_ELEMENT && + xmlReader->getNodeName() == XmlTag::RELS_RELATIONSHIP_NODE) { ParseChildNode(xmlReader); } } } - void ParseAttributes(XmlReader*) { + void ParseAttributes(XmlReader *) { // empty } - bool validateRels( OpcPackageRelationshipPtr &relPtr ) { - if ( relPtr->id.empty() || relPtr->type.empty() || relPtr->target.empty() ) { + bool validateRels(OpcPackageRelationshipPtr &relPtr) { + if (relPtr->id.empty() || relPtr->type.empty() || relPtr->target.empty()) { return false; } return true; } - void ParseChildNode(XmlReader* xmlReader) { + void ParseChildNode(XmlReader *xmlReader) { OpcPackageRelationshipPtr relPtr(new OpcPackageRelationship()); relPtr->id = xmlReader->getAttributeValueSafe(XmlTag::RELS_ATTRIB_ID.c_str()); relPtr->type = xmlReader->getAttributeValueSafe(XmlTag::RELS_ATTRIB_TYPE.c_str()); relPtr->target = xmlReader->getAttributeValueSafe(XmlTag::RELS_ATTRIB_TARGET.c_str()); - if ( validateRels( relPtr ) ) { - m_relationShips.push_back( relPtr ); + if (validateRels(relPtr)) { + m_relationShips.push_back(relPtr); } } @@ -118,32 +114,34 @@ public: }; // ------------------------------------------------------------------------------------------------ -D3MFOpcPackage::D3MFOpcPackage(IOSystem* pIOHandler, const std::string& rFile) -: mRootStream(nullptr) -, mZipArchive() { - mZipArchive.reset( new ZipArchiveIOSystem( pIOHandler, rFile ) ); - if(!mZipArchive->isOpen()) { - throw DeadlyImportError("Failed to open file " + rFile+ "."); +D3MFOpcPackage::D3MFOpcPackage(IOSystem *pIOHandler, const std::string &rFile) : + mRootStream(nullptr), mZipArchive() { + mZipArchive.reset(new ZipArchiveIOSystem(pIOHandler, rFile)); + if (!mZipArchive->isOpen()) { + throw DeadlyImportError("Failed to open file " + rFile + "."); } std::vector fileList; mZipArchive->getFileList(fileList); - for (auto& file: fileList) { - if(file == D3MF::XmlTag::ROOT_RELATIONSHIPS_ARCHIVE) { - //PkgRelationshipReader pkgRelReader(file, archive); - ai_assert(mZipArchive->Exists(file.c_str())); + for (auto &file : fileList) { + if (file == D3MF::XmlTag::ROOT_RELATIONSHIPS_ARCHIVE) { + if (!mZipArchive->Exists(file.c_str())) { + continue; + } IOStream *fileStream = mZipArchive->Open(file.c_str()); - - ai_assert(fileStream != nullptr); + if (nullptr == fileStream) { + ai_assert(fileStream != nullptr); + continue; + } std::string rootFile = ReadPackageRootRelationship(fileStream); - if ( rootFile.size() > 0 && rootFile[ 0 ] == '/' ) { - rootFile = rootFile.substr( 1 ); - if ( rootFile[ 0 ] == '/' ) { + if (rootFile.size() > 0 && rootFile[0] == '/') { + rootFile = rootFile.substr(1); + if (rootFile[0] == '/') { // deal with zip-bug - rootFile = rootFile.substr( 1 ); + rootFile = rootFile.substr(1); } } @@ -152,17 +150,16 @@ D3MFOpcPackage::D3MFOpcPackage(IOSystem* pIOHandler, const std::string& rFile) mZipArchive->Close(fileStream); mRootStream = mZipArchive->Open(rootFile.c_str()); - ai_assert( mRootStream != nullptr ); - if ( nullptr == mRootStream ) { - throw DeadlyExportError( "Cannot open root-file in archive : " + rootFile ); + ai_assert(mRootStream != nullptr); + if (nullptr == mRootStream) { + throw DeadlyExportError("Cannot open root-file in archive : " + rootFile); } - } else if( file == D3MF::XmlTag::CONTENT_TYPES_ARCHIVE) { - ASSIMP_LOG_WARN_F("Ignored file of unsupported type CONTENT_TYPES_ARCHIVES",file); + } else if (file == D3MF::XmlTag::CONTENT_TYPES_ARCHIVE) { + ASSIMP_LOG_WARN_F("Ignored file of unsupported type CONTENT_TYPES_ARCHIVES", file); } else { - ASSIMP_LOG_WARN_F("Ignored file of unknown type: ",file); + ASSIMP_LOG_WARN_F("Ignored file of unknown type: ", file); } - } } @@ -170,32 +167,32 @@ D3MFOpcPackage::~D3MFOpcPackage() { mZipArchive->Close(mRootStream); } -IOStream* D3MFOpcPackage::RootStream() const { +IOStream *D3MFOpcPackage::RootStream() const { return mRootStream; } static const std::string ModelRef = "3D/3dmodel.model"; bool D3MFOpcPackage::validate() { - if ( nullptr == mRootStream || nullptr == mZipArchive ) { + if (nullptr == mRootStream || nullptr == mZipArchive) { return false; } - return mZipArchive->Exists( ModelRef.c_str() ); + return mZipArchive->Exists(ModelRef.c_str()); } -std::string D3MFOpcPackage::ReadPackageRootRelationship(IOStream* stream) { +std::string D3MFOpcPackage::ReadPackageRootRelationship(IOStream *stream) { std::unique_ptr xmlStream(new CIrrXML_IOStreamReader(stream)); std::unique_ptr xml(irr::io::createIrrXMLReader(xmlStream.get())); OpcPackageRelationshipReader reader(xml.get()); - auto itr = std::find_if(reader.m_relationShips.begin(), reader.m_relationShips.end(), [](const OpcPackageRelationshipPtr& rel){ + auto itr = std::find_if(reader.m_relationShips.begin(), reader.m_relationShips.end(), [](const OpcPackageRelationshipPtr &rel) { return rel->type == XmlTag::PACKAGE_START_PART_RELATIONSHIP_TYPE; }); - if ( itr == reader.m_relationShips.end() ) { - throw DeadlyImportError( "Cannot find " + XmlTag::PACKAGE_START_PART_RELATIONSHIP_TYPE ); + if (itr == reader.m_relationShips.end()) { + throw DeadlyImportError("Cannot find " + XmlTag::PACKAGE_START_PART_RELATIONSHIP_TYPE); } return (*itr)->target; diff --git a/code/AssetLib/AC/ACLoader.cpp b/code/AssetLib/AC/ACLoader.cpp index 2b8b7f087..ac1631a9b 100644 --- a/code/AssetLib/AC/ACLoader.cpp +++ b/code/AssetLib/AC/ACLoader.cpp @@ -627,7 +627,7 @@ aiNode *AC3DImporter::ConvertObjectSection(Object &object, std::unique_ptr div(Subdivider::Create(Subdivider::CATMULL_CLARKE)); ASSIMP_LOG_INFO("AC3D: Evaluating subdivision surface: " + object.name); - std::vector cpy(meshes.size() - oldm, NULL); + std::vector cpy(meshes.size() - oldm, nullptr); div->Subdivide(&meshes[oldm], cpy.size(), &cpy.front(), object.subDiv, true); std::copy(cpy.begin(), cpy.end(), meshes.begin() + oldm); diff --git a/code/AssetLib/AMF/AMFImporter.cpp b/code/AssetLib/AMF/AMFImporter.cpp index 87dfe4904..eb6b19257 100644 --- a/code/AssetLib/AMF/AMFImporter.cpp +++ b/code/AssetLib/AMF/AMFImporter.cpp @@ -88,7 +88,7 @@ void AMFImporter::Clear() { } } -AMFImporter::AMFImporter() : +AMFImporter::AMFImporter() AI_NO_EXCEPT : mNodeElement_Cur(nullptr), mXmlParser(nullptr) { // empty @@ -182,7 +182,7 @@ void AMFImporter::XML_CheckNode_MustHaveChildren(pugi::xml_node &node) { } } -void AMFImporter::XML_CheckNode_SkipUnsupported(const std::string &pParentNodeName) { +/*void AMFImporter::XML_CheckNode_SkipUnsupported(const std::string &pParentNodeName) { static const size_t Uns_Skip_Len = 3; const char *Uns_Skip[Uns_Skip_Len] = { "composite", "edge", "normal" }; @@ -221,7 +221,7 @@ casu_cres: skipped_before[sk_idx] = true; ASSIMP_LOG_WARN_F("Skipping node \"", nn, "\" in ", pParentNodeName, "."); } -} +}*/ bool AMFImporter::XML_SearchNode(const std::string &nodeName) { mXmlParser->h(nodeName); @@ -383,6 +383,7 @@ void AMFImporter::ParseFile(const std::string &pFile, IOSystem *pIOHandler) { throw DeadlyImportError("Failed to open AMF file " + pFile + "."); } +<<<<<<< HEAD mXmlParser = new XmlParser(); if (!mXmlParser->parse( file.get() ) { delete mXmlParser; @@ -391,6 +392,18 @@ void AMFImporter::ParseFile(const std::string &pFile, IOSystem *pIOHandler) { // Start reading, search for root tag if (!mXmlParser->hasNode("amf")) { +======= + // generate a XML reader for it + std::unique_ptr mIOWrapper(new CIrrXML_IOStreamReader(file.get())); + mReader = irr::io::createIrrXMLReader(mIOWrapper.get()); + if (!mReader) throw DeadlyImportError("Failed to create XML reader for file" + pFile + "."); + // + // start reading + // search for root tag + if (XML_SearchNode("amf")) + ParseNode_Root(); + else +>>>>>>> master throw DeadlyImportError("Root node \"amf\" not found."); } diff --git a/code/AssetLib/ASE/ASEParser.cpp b/code/AssetLib/ASE/ASEParser.cpp index 09ad2ab1d..c801f53a1 100644 --- a/code/AssetLib/ASE/ASEParser.cpp +++ b/code/AssetLib/ASE/ASEParser.cpp @@ -925,7 +925,7 @@ void Parser::ParseLV2AnimationBlock(ASE::BaseNode &mesh) { ASSIMP_LOG_ERROR("ASE: Found target animation channel " "but the node is neither a camera nor a spot light"); - anim = NULL; + anim = nullptr; } else anim = &mesh.mTargetAnim; } @@ -1797,14 +1797,14 @@ void Parser::ParseLV4MeshFace(ASE::Face &out) { } // ------------------------------------------------------------------------------------------------ void Parser::ParseLV4MeshLongTriple(unsigned int *apOut) { - ai_assert(NULL != apOut); + ai_assert(nullptr != apOut); for (unsigned int i = 0; i < 3; ++i) ParseLV4MeshLong(apOut[i]); } // ------------------------------------------------------------------------------------------------ void Parser::ParseLV4MeshLongTriple(unsigned int *apOut, unsigned int &rIndexOut) { - ai_assert(NULL != apOut); + ai_assert(nullptr != apOut); // parse the index ParseLV4MeshLong(rIndexOut); @@ -1814,7 +1814,7 @@ void Parser::ParseLV4MeshLongTriple(unsigned int *apOut, unsigned int &rIndexOut } // ------------------------------------------------------------------------------------------------ void Parser::ParseLV4MeshFloatTriple(ai_real *apOut, unsigned int &rIndexOut) { - ai_assert(NULL != apOut); + ai_assert(nullptr != apOut); // parse the index ParseLV4MeshLong(rIndexOut); @@ -1824,7 +1824,7 @@ void Parser::ParseLV4MeshFloatTriple(ai_real *apOut, unsigned int &rIndexOut) { } // ------------------------------------------------------------------------------------------------ void Parser::ParseLV4MeshFloatTriple(ai_real *apOut) { - ai_assert(NULL != apOut); + ai_assert(nullptr != apOut); for (unsigned int i = 0; i < 3; ++i) ParseLV4MeshFloat(apOut[i]); diff --git a/code/AssetLib/ASE/ASEParser.h b/code/AssetLib/ASE/ASEParser.h index c94c8e3aa..8df75c2dc 100644 --- a/code/AssetLib/ASE/ASEParser.h +++ b/code/AssetLib/ASE/ASEParser.h @@ -40,15 +40,14 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ---------------------------------------------------------------------- */ - /** @file Defines the helper data structures for importing ASE files */ #ifndef AI_ASEFILEHELPER_H_INC #define AI_ASEFILEHELPER_H_INC // public ASSIMP headers -#include -#include #include +#include +#include #ifndef ASSIMP_BUILD_NO_3DS_IMPORTER @@ -59,27 +58,26 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // ASE is quite similar to 3ds. We can reuse some structures #include "AssetLib/3DS/3DSLoader.h" -namespace Assimp { -namespace ASE { +namespace Assimp { +namespace ASE { using namespace D3DS; // --------------------------------------------------------------------------- /** Helper structure representing an ASE material */ -struct Material : public D3DS::Material -{ +struct Material : public D3DS::Material { //! Default constructor has been deleted Material() = delete; //! Constructor with explicit name - explicit Material(const std::string &name) - : D3DS::Material(name) - , pcInstance(NULL) - , bNeed (false) { + explicit Material(const std::string &name) : + D3DS::Material(name), + pcInstance(nullptr), + bNeed(false) { // empty } - Material(const Material &other) = default; + Material(const Material &other) = default; Material &operator=(const Material &other) { if (this == &other) { @@ -93,19 +91,16 @@ struct Material : public D3DS::Material return *this; } - //! Move constructor. This is explicitly written because MSVC doesn't support defaulting it Material(Material &&other) AI_NO_EXCEPT - : D3DS::Material(std::move(other)) - , avSubMaterials(std::move(other.avSubMaterials)) - , pcInstance(std::move(other.pcInstance)) - , bNeed(std::move(other.bNeed)) - { + : D3DS::Material(std::move(other)), + avSubMaterials(std::move(other.avSubMaterials)), + pcInstance(std::move(other.pcInstance)), + bNeed(std::move(other.bNeed)) { other.pcInstance = nullptr; } - - Material &operator=( Material &&other) AI_NO_EXCEPT { + Material &operator=(Material &&other) AI_NO_EXCEPT { if (this == &other) { return *this; } @@ -121,15 +116,13 @@ struct Material : public D3DS::Material return *this; } - ~Material() {} - //! Contains all sub materials of this material std::vector avSubMaterials; //! aiMaterial object - aiMaterial* pcInstance; + aiMaterial *pcInstance; //! Can we remove this material? bool bNeed; @@ -140,8 +133,8 @@ struct Material : public D3DS::Material struct Face : public FaceWithSmoothingGroup { //! Default constructor. Initializes everything with 0 Face() AI_NO_EXCEPT - : iMaterial(DEFAULT_MATINDEX) - , iFace(0) { + : iMaterial(DEFAULT_MATINDEX), + iFace(0) { // empty } @@ -172,8 +165,8 @@ struct Bone { Bone() = delete; //! Construction from an existing name - explicit Bone( const std::string& name) - : mName(name) { + explicit Bone(const std::string &name) : + mName(name) { // empty } @@ -186,33 +179,34 @@ struct Bone { struct BoneVertex { //! Bone and corresponding vertex weight. //! -1 for unrequired bones .... - std::vector > mBoneWeights; + std::vector> mBoneWeights; }; // --------------------------------------------------------------------------- /** Helper structure to represent an ASE file animation */ struct Animation { enum Type { - TRACK = 0x0, - BEZIER = 0x1, - TCB = 0x2 - } mRotationType, mScalingType, mPositionType; + TRACK = 0x0, + BEZIER = 0x1, + TCB = 0x2 + } mRotationType, + mScalingType, mPositionType; Animation() AI_NO_EXCEPT - : mRotationType (TRACK) - , mScalingType (TRACK) - , mPositionType (TRACK) { + : mRotationType(TRACK), + mScalingType(TRACK), + mPositionType(TRACK) { // empty } //! List of track rotation keyframes - std::vector< aiQuatKey > akeyRotations; + std::vector akeyRotations; //! List of track position keyframes - std::vector< aiVectorKey > akeyPositions; + std::vector akeyPositions; //! List of track scaling keyframes - std::vector< aiVectorKey > akeyScaling; + std::vector akeyScaling; }; // --------------------------------------------------------------------------- @@ -220,7 +214,7 @@ struct Animation { struct InheritanceInfo { //! Default constructor InheritanceInfo() AI_NO_EXCEPT { - for ( size_t i=0; i<3; ++i ) { + for (size_t i = 0; i < 3; ++i) { abInheritPosition[i] = abInheritRotation[i] = abInheritScaling[i] = true; } } @@ -239,17 +233,15 @@ struct InheritanceInfo { /** Represents an ASE file node. Base class for mesh, light and cameras */ struct BaseNode { enum Type { - Light, - Camera, - Mesh, + Light, + Camera, + Mesh, Dummy } mType; //! Construction from an existing name - BaseNode(Type _mType, const std::string &name) - : mType (_mType) - , mName (name) - , mProcessed (false) { + BaseNode(Type _mType, const std::string &name) : + mType(_mType), mName(name), mProcessed(false) { // Set mTargetPosition to qnan const ai_real qnan = get_qnan(); mTargetPosition.x = qnan; @@ -289,14 +281,9 @@ struct Mesh : public MeshWithSmoothingGroups, public BaseNode { Mesh() = delete; //! Construction from an existing name - explicit Mesh(const std::string &name) - : BaseNode( BaseNode::Mesh, name ) - , mVertexColors() - , mBoneVertices() - , mBones() - , iMaterialIndex(Face::DEFAULT_MATINDEX) - , bSkip (false) { - for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_TEXTURECOORDS;++c) { + explicit Mesh(const std::string &name) : + BaseNode(BaseNode::Mesh, name), mVertexColors(), mBoneVertices(), mBones(), iMaterialIndex(Face::DEFAULT_MATINDEX), bSkip(false) { + for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++c) { this->mNumUVComponents[c] = 2; } } @@ -325,10 +312,8 @@ struct Mesh : public MeshWithSmoothingGroups, public BaseNode { // --------------------------------------------------------------------------- /** Helper structure to represent an ASE light source */ -struct Light : public BaseNode -{ - enum LightType - { +struct Light : public BaseNode { + enum LightType { OMNI, TARGET, FREE, @@ -339,17 +324,13 @@ struct Light : public BaseNode Light() = delete; //! Construction from an existing name - explicit Light(const std::string &name) - : BaseNode (BaseNode::Light, name) - , mLightType (OMNI) - , mColor (1.f,1.f,1.f) - , mIntensity (1.f) // light is white by default - , mAngle (45.f) - , mFalloff (0.f) - { + explicit Light(const std::string &name) : + BaseNode(BaseNode::Light, name), mLightType(OMNI), mColor(1.f, 1.f, 1.f), mIntensity(1.f) // light is white by default + , + mAngle(45.f), + mFalloff(0.f) { } - LightType mLightType; aiColor3D mColor; ai_real mIntensity; @@ -359,10 +340,8 @@ struct Light : public BaseNode // --------------------------------------------------------------------------- /** Helper structure to represent an ASE camera */ -struct Camera : public BaseNode -{ - enum CameraType - { +struct Camera : public BaseNode { + enum CameraType { FREE, TARGET }; @@ -370,18 +349,16 @@ struct Camera : public BaseNode //! Default constructor has been deleted Camera() = delete; - //! Construction from an existing name - explicit Camera(const std::string &name) - : BaseNode (BaseNode::Camera, name) - , mFOV (0.75f) // in radians - , mNear (0.1f) - , mFar (1000.f) // could be zero - , mCameraType (FREE) - { + explicit Camera(const std::string &name) : + BaseNode(BaseNode::Camera, name), mFOV(0.75f) // in radians + , + mNear(0.1f), + mFar(1000.f) // could be zero + , + mCameraType(FREE) { } - ai_real mFOV, mNear, mFar; CameraType mCameraType; }; @@ -391,7 +368,7 @@ struct Camera : public BaseNode struct Dummy : public BaseNode { //! Constructor Dummy() AI_NO_EXCEPT - : BaseNode (BaseNode::Dummy, "DUMMY") { + : BaseNode(BaseNode::Dummy, "DUMMY") { // empty } }; @@ -414,7 +391,6 @@ private: } public: - // ------------------------------------------------------------------- //! Construct a parser from a given input file which is //! guaranteed to be terminated with zero. @@ -422,15 +398,13 @@ public: //! @param fileFormatDefault Assumed file format version. If the //! file format is specified in the file the new value replaces //! the default value. - Parser (const char* szFile, unsigned int fileFormatDefault); + Parser(const char *szFile, unsigned int fileFormatDefault); // ------------------------------------------------------------------- //! Parses the file into the parsers internal representation void Parse(); - private: - // ------------------------------------------------------------------- //! Parse the *SCENE block in a file void ParseLV1SceneBlock(); @@ -446,45 +420,45 @@ private: // ------------------------------------------------------------------- //! Parse a *OBJECT block in a file //! \param mesh Node to be filled - void ParseLV1ObjectBlock(BaseNode& mesh); + void ParseLV1ObjectBlock(BaseNode &mesh); // ------------------------------------------------------------------- //! Parse a *MATERIAL blocks in a material list //! \param mat Material structure to be filled - void ParseLV2MaterialBlock(Material& mat); + void ParseLV2MaterialBlock(Material &mat); // ------------------------------------------------------------------- //! Parse a *NODE_TM block in a file //! \param mesh Node (!) object to be filled - void ParseLV2NodeTransformBlock(BaseNode& mesh); + void ParseLV2NodeTransformBlock(BaseNode &mesh); // ------------------------------------------------------------------- //! Parse a *TM_ANIMATION block in a file //! \param mesh Mesh object to be filled - void ParseLV2AnimationBlock(BaseNode& mesh); - void ParseLV3PosAnimationBlock(ASE::Animation& anim); - void ParseLV3ScaleAnimationBlock(ASE::Animation& anim); - void ParseLV3RotAnimationBlock(ASE::Animation& anim); + void ParseLV2AnimationBlock(BaseNode &mesh); + void ParseLV3PosAnimationBlock(ASE::Animation &anim); + void ParseLV3ScaleAnimationBlock(ASE::Animation &anim); + void ParseLV3RotAnimationBlock(ASE::Animation &anim); // ------------------------------------------------------------------- //! Parse a *MESH block in a file //! \param mesh Mesh object to be filled - void ParseLV2MeshBlock(Mesh& mesh); + void ParseLV2MeshBlock(Mesh &mesh); // ------------------------------------------------------------------- //! Parse a *LIGHT_SETTINGS block in a file //! \param light Light object to be filled - void ParseLV2LightSettingsBlock(Light& light); + void ParseLV2LightSettingsBlock(Light &light); // ------------------------------------------------------------------- //! Parse a *CAMERA_SETTINGS block in a file //! \param cam Camera object to be filled - void ParseLV2CameraSettingsBlock(Camera& cam); + void ParseLV2CameraSettingsBlock(Camera &cam); // ------------------------------------------------------------------- //! Parse the *MAP_XXXXXX blocks in a material //! \param map Texture structure to be filled - void ParseLV3MapBlock(Texture& map); + void ParseLV3MapBlock(Texture &map); // ------------------------------------------------------------------- //! Parse a *MESH_VERTEX_LIST block in a file @@ -493,7 +467,7 @@ private: //! A warning is sent to the logger if the validations fails. //! \param mesh Mesh object to be filled void ParseLV3MeshVertexListBlock( - unsigned int iNumVertices,Mesh& mesh); + unsigned int iNumVertices, Mesh &mesh); // ------------------------------------------------------------------- //! Parse a *MESH_FACE_LIST block in a file @@ -502,7 +476,7 @@ private: //! A warning is sent to the logger if the validations fails. //! \param mesh Mesh object to be filled void ParseLV3MeshFaceListBlock( - unsigned int iNumFaces,Mesh& mesh); + unsigned int iNumFaces, Mesh &mesh); // ------------------------------------------------------------------- //! Parse a *MESH_TVERT_LIST block in a file @@ -512,7 +486,7 @@ private: //! \param mesh Mesh object to be filled //! \param iChannel Output UVW channel void ParseLV3MeshTListBlock( - unsigned int iNumVertices,Mesh& mesh, unsigned int iChannel = 0); + unsigned int iNumVertices, Mesh &mesh, unsigned int iChannel = 0); // ------------------------------------------------------------------- //! Parse a *MESH_TFACELIST block in a file @@ -522,7 +496,7 @@ private: //! \param mesh Mesh object to be filled //! \param iChannel Output UVW channel void ParseLV3MeshTFaceListBlock( - unsigned int iNumFaces,Mesh& mesh, unsigned int iChannel = 0); + unsigned int iNumFaces, Mesh &mesh, unsigned int iChannel = 0); // ------------------------------------------------------------------- //! Parse an additional mapping channel @@ -530,7 +504,7 @@ private: //! \param iChannel Channel index to be filled //! \param mesh Mesh object to be filled void ParseLV3MappingChannel( - unsigned int iChannel, Mesh& mesh); + unsigned int iChannel, Mesh &mesh); // ------------------------------------------------------------------- //! Parse a *MESH_CVERTLIST block in a file @@ -539,7 +513,7 @@ private: //! A warning is sent to the logger if the validations fails. //! \param mesh Mesh object to be filled void ParseLV3MeshCListBlock( - unsigned int iNumVertices, Mesh& mesh); + unsigned int iNumVertices, Mesh &mesh); // ------------------------------------------------------------------- //! Parse a *MESH_CFACELIST block in a file @@ -548,70 +522,70 @@ private: //! A warning is sent to the logger if the validations fails. //! \param mesh Mesh object to be filled void ParseLV3MeshCFaceListBlock( - unsigned int iNumFaces, Mesh& mesh); + unsigned int iNumFaces, Mesh &mesh); // ------------------------------------------------------------------- //! Parse a *MESH_NORMALS block in a file //! \param mesh Mesh object to be filled - void ParseLV3MeshNormalListBlock(Mesh& mesh); + void ParseLV3MeshNormalListBlock(Mesh &mesh); // ------------------------------------------------------------------- //! Parse a *MESH_WEIGHTSblock in a file //! \param mesh Mesh object to be filled - void ParseLV3MeshWeightsBlock(Mesh& mesh); + void ParseLV3MeshWeightsBlock(Mesh &mesh); // ------------------------------------------------------------------- //! Parse the bone list of a file //! \param mesh Mesh object to be filled //! \param iNumBones Number of bones in the mesh - void ParseLV4MeshBones(unsigned int iNumBones,Mesh& mesh); + void ParseLV4MeshBones(unsigned int iNumBones, Mesh &mesh); // ------------------------------------------------------------------- //! Parse the bone vertices list of a file //! \param mesh Mesh object to be filled //! \param iNumVertices Number of vertices to be parsed - void ParseLV4MeshBonesVertices(unsigned int iNumVertices,Mesh& mesh); + void ParseLV4MeshBonesVertices(unsigned int iNumVertices, Mesh &mesh); // ------------------------------------------------------------------- //! Parse a *MESH_FACE block in a file //! \param out receive the face data - void ParseLV4MeshFace(ASE::Face& out); + void ParseLV4MeshFace(ASE::Face &out); // ------------------------------------------------------------------- //! Parse a *MESH_VERT block in a file //! (also works for MESH_TVERT, MESH_CFACE, MESH_VERTCOL ...) //! \param apOut Output buffer (3 floats) //! \param rIndexOut Output index - void ParseLV4MeshFloatTriple(ai_real* apOut, unsigned int& rIndexOut); + void ParseLV4MeshFloatTriple(ai_real *apOut, unsigned int &rIndexOut); // ------------------------------------------------------------------- //! Parse a *MESH_VERT block in a file //! (also works for MESH_TVERT, MESH_CFACE, MESH_VERTCOL ...) //! \param apOut Output buffer (3 floats) - void ParseLV4MeshFloatTriple(ai_real* apOut); + void ParseLV4MeshFloatTriple(ai_real *apOut); // ------------------------------------------------------------------- //! Parse a *MESH_TFACE block in a file //! (also works for MESH_CFACE) //! \param apOut Output buffer (3 ints) //! \param rIndexOut Output index - void ParseLV4MeshLongTriple(unsigned int* apOut, unsigned int& rIndexOut); + void ParseLV4MeshLongTriple(unsigned int *apOut, unsigned int &rIndexOut); // ------------------------------------------------------------------- //! Parse a *MESH_TFACE block in a file //! (also works for MESH_CFACE) //! \param apOut Output buffer (3 ints) - void ParseLV4MeshLongTriple(unsigned int* apOut); + void ParseLV4MeshLongTriple(unsigned int *apOut); // ------------------------------------------------------------------- //! Parse a single float element //! \param fOut Output float - void ParseLV4MeshFloat(ai_real& fOut); + void ParseLV4MeshFloat(ai_real &fOut); // ------------------------------------------------------------------- //! Parse a single int element //! \param iOut Output integer - void ParseLV4MeshLong(unsigned int& iOut); + void ParseLV4MeshLong(unsigned int &iOut); // ------------------------------------------------------------------- //! Skip everything to the next: '*' or '\0' @@ -625,17 +599,17 @@ private: // ------------------------------------------------------------------- //! Output a warning to the logger //! \param szWarn Warn message - void LogWarning(const char* szWarn); + void LogWarning(const char *szWarn); // ------------------------------------------------------------------- //! Output a message to the logger //! \param szWarn Message - void LogInfo(const char* szWarn); + void LogInfo(const char *szWarn); // ------------------------------------------------------------------- //! Output an error to the logger //! \param szWarn Error message - AI_WONT_RETURN void LogError(const char* szWarn) AI_WONT_RETURN_SUFFIX; + AI_WONT_RETURN void LogError(const char *szWarn) AI_WONT_RETURN_SUFFIX; // ------------------------------------------------------------------- //! Parse a string, enclosed in double quotation marks @@ -643,12 +617,11 @@ private: //! \param szName Name of the enclosing element -> used in error //! messages. //! \return false if an error occurred - bool ParseString(std::string& out,const char* szName); + bool ParseString(std::string &out, const char *szName); public: - //! Pointer to current data - const char* filePtr; + const char *filePtr; //! background color to be passed to the viewer //! QNAN if none was found @@ -695,9 +668,8 @@ public: unsigned int iFileFormat; }; - } // Namespace ASE -} // Namespace ASSIMP +} // namespace Assimp #endif // ASSIMP_BUILD_NO_3DS_IMPORTER diff --git a/code/AssetLib/Assbin/AssbinFileWriter.cpp b/code/AssetLib/Assbin/AssbinFileWriter.cpp index 431be4d3a..a879e637c 100644 --- a/code/AssetLib/Assbin/AssbinFileWriter.cpp +++ b/code/AssetLib/Assbin/AssbinFileWriter.cpp @@ -336,7 +336,7 @@ protected: void WriteBinaryNode(IOStream *container, const aiNode *node) { AssbinChunkWriter chunk(container, ASSBIN_CHUNK_AINODE); - unsigned int nb_metadata = (node->mMetaData != NULL ? node->mMetaData->mNumProperties : 0); + unsigned int nb_metadata = (node->mMetaData != nullptr ? node->mMetaData->mNumProperties : 0); Write(&chunk, node->mName); Write(&chunk, node->mTransformation); @@ -744,7 +744,7 @@ public: }; try { - time_t tt = time(NULL); + time_t tt = time(nullptr); #if _WIN32 tm *p = gmtime(&tt); #else @@ -790,7 +790,7 @@ public: // Up to here the data is uncompressed. For compressed files, the rest // is compressed using standard DEFLATE from zlib. if (compressed) { - AssbinChunkWriter uncompressedStream(NULL, 0); + AssbinChunkWriter uncompressedStream(nullptr, 0); WriteBinaryScene(&uncompressedStream, pScene); uLongf uncompressedSize = static_cast(uncompressedStream.Tell()); diff --git a/code/AssetLib/Assbin/AssbinLoader.cpp b/code/AssetLib/Assbin/AssbinLoader.cpp index 5ee87e952..34021575c 100644 --- a/code/AssetLib/Assbin/AssbinLoader.cpp +++ b/code/AssetLib/Assbin/AssbinLoader.cpp @@ -604,7 +604,7 @@ void AssbinImporter::ReadBinaryScene(IOStream *stream, aiScene *scene) { // Read node graph //scene->mRootNode = new aiNode[1]; - ReadBinaryNode(stream, &scene->mRootNode, (aiNode *)NULL); + ReadBinaryNode(stream, &scene->mRootNode, (aiNode *)nullptr); // Read all meshes if (scene->mNumMeshes) { diff --git a/code/AssetLib/Assxml/AssxmlFileWriter.cpp b/code/AssetLib/Assxml/AssxmlFileWriter.cpp index b175265b5..05661d3fc 100644 --- a/code/AssetLib/Assxml/AssxmlFileWriter.cpp +++ b/code/AssetLib/Assxml/AssxmlFileWriter.cpp @@ -189,7 +189,7 @@ static std::string encodeXML(const std::string &data) { // ----------------------------------------------------------------------------------- // Write a text model dump static void WriteDump(const char *pFile, const char *cmd, const aiScene *scene, IOStream *io, bool shortened) { - time_t tt = ::time(NULL); + time_t tt = ::time(nullptr); #if _WIN32 tm *p = gmtime(&tt); #else diff --git a/code/AssetLib/BVH/BVHLoader.cpp b/code/AssetLib/BVH/BVHLoader.cpp index 348c30337..46afc5e64 100644 --- a/code/AssetLib/BVH/BVHLoader.cpp +++ b/code/AssetLib/BVH/BVHLoader.cpp @@ -422,9 +422,9 @@ void BVHLoader::CreateAnimation(aiScene *pScene) { anim->mNumChannels = static_cast(mNodes.size()); anim->mChannels = new aiNodeAnim *[anim->mNumChannels]; - // FIX: set the array elements to NULL to ensure proper deletion if an exception is thrown + // FIX: set the array elements to nullptr to ensure proper deletion if an exception is thrown for (unsigned int i = 0; i < anim->mNumChannels; ++i) - anim->mChannels[i] = NULL; + anim->mChannels[i] = nullptr; for (unsigned int a = 0; a < anim->mNumChannels; a++) { const Node &node = mNodes[a]; diff --git a/code/AssetLib/Blender/BlenderDNA.h b/code/AssetLib/Blender/BlenderDNA.h index 7e04bad19..c89b21434 100644 --- a/code/AssetLib/Blender/BlenderDNA.h +++ b/code/AssetLib/Blender/BlenderDNA.h @@ -230,7 +230,7 @@ public: // -------------------------------------------------------- /** Access a field of the structure by its canonical name. The pointer version - * returns NULL on failure while the reference version raises an import error. */ + * returns nullptr on failure while the reference version raises an import error. */ inline const Field &operator[](const std::string &ss) const; inline const Field *Get(const std::string &ss) const; @@ -359,7 +359,7 @@ private: template T *_allocate(vector &out, size_t &s) const { out.resize(s); - return s ? &out.front() : NULL; + return s ? &out.front() : nullptr; } // -------------------------------------------------------- @@ -367,14 +367,14 @@ private: struct _defaultInitializer { template - void operator()(T (&out)[N], const char * = NULL) { + void operator()(T (&out)[N], const char * = nullptr) { for (unsigned int i = 0; i < N; ++i) { out[i] = T(); } } template - void operator()(T (&out)[N][M], const char * = NULL) { + void operator()(T (&out)[N][M], const char * = nullptr) { for (unsigned int i = 0; i < N; ++i) { for (unsigned int j = 0; j < M; ++j) { out[i][j] = T(); @@ -383,7 +383,7 @@ private: } template - void operator()(T &out, const char * = NULL) { + void operator()(T &out, const char * = nullptr) { out = T(); } }; @@ -448,7 +448,7 @@ public: public: // -------------------------------------------------------- - /** Access a structure by its canonical name, the pointer version returns NULL on failure + /** Access a structure by its canonical name, the pointer version returns nullptr on failure * while the reference version raises an error. */ inline const Structure &operator[](const std::string &ss) const; inline const Structure *Get(const std::string &ss) const; diff --git a/code/AssetLib/Blender/BlenderDNA.inl b/code/AssetLib/Blender/BlenderDNA.inl index a41ceab7f..7bb9d586a 100644 --- a/code/AssetLib/Blender/BlenderDNA.inl +++ b/code/AssetLib/Blender/BlenderDNA.inl @@ -4,7 +4,6 @@ Open Asset Import Library (assimp) Copyright (c) 2006-2020, assimp team - All rights reserved. Redistribution and use of this software in source and binary forms, @@ -70,7 +69,7 @@ const Field& Structure :: operator [] (const std::string& ss) const const Field* Structure :: Get (const std::string& ss) const { std::map::const_iterator it = indices.find(ss); - return it == indices.end() ? NULL : &fields[(*it).second]; + return it == indices.end() ? nullptr : &fields[(*it).second]; } //-------------------------------------------------------------------------------- @@ -239,11 +238,13 @@ bool Structure :: ReadFieldPtr(TOUT (&out)[N], const char* name, try { f = &(*this)[name]; +#ifdef _DEBUG // sanity check, should never happen if the genblenddna script is right if ((FieldFlag_Pointer|FieldFlag_Pointer) != (f->flags & (FieldFlag_Pointer|FieldFlag_Pointer))) { throw Error((Formatter::format(),"Field `",name,"` of structure `", this->name,"` ought to be a pointer AND an array")); } +#endif // _DEBUG db.reader->IncPtr(f->offset); diff --git a/code/AssetLib/Blender/BlenderLoader.cpp b/code/AssetLib/Blender/BlenderLoader.cpp index 06ae79cd2..508db8422 100644 --- a/code/AssetLib/Blender/BlenderLoader.cpp +++ b/code/AssetLib/Blender/BlenderLoader.cpp @@ -45,43 +45,41 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * @brief Implementation of the Blender3D importer class. */ - //#define ASSIMP_BUILD_NO_COMPRESSED_BLEND // Uncomment this to disable support for (gzip)compressed .BLEND files #ifndef ASSIMP_BUILD_NO_BLEND_IMPORTER -#include "BlenderIntermediate.h" -#include "BlenderModifier.h" #include "BlenderBMesh.h" #include "BlenderCustomData.h" +#include "BlenderIntermediate.h" +#include "BlenderModifier.h" #include -#include #include +#include -#include -#include #include +#include +#include #include - // zlib is needed for compressed blend files #ifndef ASSIMP_BUILD_NO_COMPRESSED_BLEND -# ifdef ASSIMP_BUILD_NO_OWN_ZLIB -# include -# else -# include "../contrib/zlib/zlib.h" -# endif +#ifdef ASSIMP_BUILD_NO_OWN_ZLIB +#include +#else +#include "../contrib/zlib/zlib.h" +#endif #endif namespace Assimp { - template<> const char* LogFunctions::Prefix() - { - static auto prefix = "BLEND: "; - return prefix; - } +template <> +const char *LogFunctions::Prefix() { + static auto prefix = "BLEND: "; + return prefix; } +} // namespace Assimp using namespace Assimp; using namespace Assimp::Blender; @@ -100,81 +98,72 @@ static const aiImporterDesc blenderDesc = { "blend" }; - // ------------------------------------------------------------------------------------------------ // Constructor to be privately used by Importer -BlenderImporter::BlenderImporter() -: modifier_cache(new BlenderModifierShowcase()) { +BlenderImporter::BlenderImporter() : + modifier_cache(new BlenderModifierShowcase()) { // empty } // ------------------------------------------------------------------------------------------------ // Destructor, private as well -BlenderImporter::~BlenderImporter() -{ +BlenderImporter::~BlenderImporter() { delete modifier_cache; } -static const char* Tokens[] = { "BLENDER" }; -static const char* TokensForSearch[] = { "blender" }; +static const char *Tokens[] = { "BLENDER" }; +static const char *TokensForSearch[] = { "blender" }; // ------------------------------------------------------------------------------------------------ // Returns whether the class can handle the format of the given file. -bool BlenderImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const -{ - const std::string& extension = GetExtension(pFile); +bool BlenderImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const { + const std::string &extension = GetExtension(pFile); if (extension == "blend") { return true; } - else if ((!extension.length() || checkSig) && pIOHandler) { + else if ((!extension.length() || checkSig) && pIOHandler) { // note: this won't catch compressed files - return SearchFileHeaderForToken(pIOHandler,pFile, TokensForSearch,1); + return SearchFileHeaderForToken(pIOHandler, pFile, TokensForSearch, 1); } return false; } // ------------------------------------------------------------------------------------------------ // List all extensions handled by this loader -void BlenderImporter::GetExtensionList(std::set& app) -{ +void BlenderImporter::GetExtensionList(std::set &app) { app.insert("blend"); } // ------------------------------------------------------------------------------------------------ // Loader registry entry -const aiImporterDesc* BlenderImporter::GetInfo () const -{ +const aiImporterDesc *BlenderImporter::GetInfo() const { return &blenderDesc; } // ------------------------------------------------------------------------------------------------ // Setup configuration properties for the loader -void BlenderImporter::SetupProperties(const Importer* /*pImp*/) -{ +void BlenderImporter::SetupProperties(const Importer * /*pImp*/) { // nothing to be done for the moment } - // ------------------------------------------------------------------------------------------------ // Imports the given file into the given scene structure. -void BlenderImporter::InternReadFile( const std::string& pFile, - aiScene* pScene, IOSystem* pIOHandler) -{ +void BlenderImporter::InternReadFile(const std::string &pFile, + aiScene *pScene, IOSystem *pIOHandler) { #ifndef ASSIMP_BUILD_NO_COMPRESSED_BLEND std::vector uncompressed; #endif - FileDatabase file; - std::shared_ptr stream(pIOHandler->Open(pFile,"rb")); + std::shared_ptr stream(pIOHandler->Open(pFile, "rb")); if (!stream) { ThrowException("Could not open file for reading"); } - char magic[8] = {0}; - stream->Read(magic,7,1); - if (strcmp(magic, Tokens[0] )) { + char magic[8] = { 0 }; + stream->Read(magic, 7, 1); + if (strcmp(magic, Tokens[0])) { // Check for presence of the gzip header. If yes, assume it is a // compressed blend file and try uncompressing it, else fail. This is to // avoid uncompressing random files which our loader might end up with. @@ -192,21 +181,21 @@ void BlenderImporter::InternReadFile( const std::string& pFile, } // http://www.gzip.org/zlib/rfc-gzip.html#header-trailer - stream->Seek(0L,aiOrigin_SET); + stream->Seek(0L, aiOrigin_SET); std::shared_ptr reader = std::shared_ptr(new StreamReaderLE(stream)); // build a zlib stream z_stream zstream; zstream.opaque = Z_NULL; zstream.zalloc = Z_NULL; - zstream.zfree = Z_NULL; + zstream.zfree = Z_NULL; zstream.data_type = Z_BINARY; // http://hewgill.com/journal/entries/349-how-to-decompress-gzip-stream-with-zlib - inflateInit2(&zstream, 16+MAX_WBITS); + inflateInit2(&zstream, 16 + MAX_WBITS); - zstream.next_in = reinterpret_cast( reader->GetPtr() ); - zstream.avail_in = (uInt) reader->GetRemainingSize(); + zstream.next_in = reinterpret_cast(reader->GetPtr()); + zstream.avail_in = (uInt)reader->GetRemainingSize(); size_t total = 0l; @@ -226,62 +215,59 @@ void BlenderImporter::InternReadFile( const std::string& pFile, const size_t have = MYBLOCK - zstream.avail_out; total += have; uncompressed.resize(total); - memcpy(uncompressed.data() + total - have,block,have); - } - while (ret != Z_STREAM_END); + memcpy(uncompressed.data() + total - have, block, have); + } while (ret != Z_STREAM_END); // terminate zlib inflateEnd(&zstream); // replace the input stream with a memory stream - stream.reset(new MemoryIOStream(reinterpret_cast(uncompressed.data()),total)); + stream.reset(new MemoryIOStream(reinterpret_cast(uncompressed.data()), total)); // .. and retry - stream->Read(magic,7,1); - if (strcmp(magic,"BLENDER")) { + stream->Read(magic, 7, 1); + if (strcmp(magic, "BLENDER")) { ThrowException("Found no BLENDER magic word in decompressed GZIP file"); } #endif } - file.i64bit = (stream->Read(magic,1,1),magic[0]=='-'); - file.little = (stream->Read(magic,1,1),magic[0]=='v'); + file.i64bit = (stream->Read(magic, 1, 1), magic[0] == '-'); + file.little = (stream->Read(magic, 1, 1), magic[0] == 'v'); - stream->Read(magic,3,1); + stream->Read(magic, 3, 1); magic[3] = '\0'; - LogInfo((format(),"Blender version is ",magic[0],".",magic+1, - " (64bit: ",file.i64bit?"true":"false", - ", little endian: ",file.little?"true":"false",")" - )); + LogInfo((format(), "Blender version is ", magic[0], ".", magic + 1, + " (64bit: ", file.i64bit ? "true" : "false", + ", little endian: ", file.little ? "true" : "false", ")")); - ParseBlendFile(file,stream); + ParseBlendFile(file, stream); Scene scene; - ExtractScene(scene,file); + ExtractScene(scene, file); - ConvertBlendFile(pScene,scene,file); + ConvertBlendFile(pScene, scene, file); } // ------------------------------------------------------------------------------------------------ -void BlenderImporter::ParseBlendFile(FileDatabase& out, std::shared_ptr stream) -{ - out.reader = std::shared_ptr(new StreamReaderAny(stream,out.little)); +void BlenderImporter::ParseBlendFile(FileDatabase &out, std::shared_ptr stream) { + out.reader = std::shared_ptr(new StreamReaderAny(stream, out.little)); DNAParser dna_reader(out); - const DNA* dna = NULL; + const DNA *dna = nullptr; - out.entries.reserve(128); { // even small BLEND files tend to consist of many file blocks - SectionParser parser(*out.reader.get(),out.i64bit); + out.entries.reserve(128); + { // even small BLEND files tend to consist of many file blocks + SectionParser parser(*out.reader.get(), out.i64bit); // first parse the file in search for the DNA and insert all other sections into the database - while ((parser.Next(),1)) { - const FileBlockHead& head = parser.GetCurrent(); + while ((parser.Next(), 1)) { + const FileBlockHead &head = parser.GetCurrent(); if (head.id == "ENDB") { break; // only valid end of the file - } - else if (head.id == "DNA1") { + } else if (head.id == "DNA1") { dna_reader.Parse(); dna = &dna_reader.GetDNA(); continue; @@ -294,22 +280,21 @@ void BlenderImporter::ParseBlendFile(FileDatabase& out, std::shared_ptr::const_iterator it = file.dna.indices.find("Scene"); +void BlenderImporter::ExtractScene(Scene &out, const FileDatabase &file) { + const FileBlockHead *block = nullptr; + std::map::const_iterator it = file.dna.indices.find("Scene"); if (it == file.dna.indices.end()) { ThrowException("There is no `Scene` structure record"); } - const Structure& ss = file.dna.structures[(*it).second]; + const Structure &ss = file.dna.structures[(*it).second]; // we need a scene somewhere to start with. - for(const FileBlockHead& bl :file.entries) { + for (const FileBlockHead &bl : file.entries) { // Fix: using the DNA index is more reliable to locate scenes //if (bl.id == "SC") { @@ -325,39 +310,37 @@ void BlenderImporter::ExtractScene(Scene& out, const FileDatabase& file) } file.reader->SetCurrentPos(block->start); - ss.Convert(out,file); + ss.Convert(out, file); #ifndef ASSIMP_BUILD_BLENDER_NO_STATS ASSIMP_LOG_INFO_F( - "(Stats) Fields read: " ,file.stats().fields_read, - ", pointers resolved: " ,file.stats().pointers_resolved, - ", cache hits: " ,file.stats().cache_hits, - ", cached objects: " ,file.stats().cached_objects - ); + "(Stats) Fields read: ", file.stats().fields_read, + ", pointers resolved: ", file.stats().pointers_resolved, + ", cache hits: ", file.stats().cache_hits, + ", cached objects: ", file.stats().cached_objects); #endif } // ------------------------------------------------------------------------------------------------ -void BlenderImporter::ConvertBlendFile(aiScene* out, const Scene& in,const FileDatabase& file) -{ +void BlenderImporter::ConvertBlendFile(aiScene *out, const Scene &in, const FileDatabase &file) { ConversionData conv(file); // FIXME it must be possible to take the hierarchy directly from // the file. This is terrible. Here, we're first looking for // all objects which don't have parent objects at all - - std::deque no_parents; - for (std::shared_ptr cur = std::static_pointer_cast ( in.base.first ); cur; cur = cur->next) { + std::deque no_parents; + for (std::shared_ptr cur = std::static_pointer_cast(in.base.first); cur; cur = cur->next) { if (cur->object) { - if(!cur->object->parent) { + if (!cur->object->parent) { no_parents.push_back(cur->object.get()); } else { - conv.objects.insert( cur->object.get() ); + conv.objects.insert(cur->object.get()); } } } for (std::shared_ptr cur = in.basact; cur; cur = cur->next) { if (cur->object) { - if(cur->object->parent) { + if (cur->object->parent) { conv.objects.insert(cur->object.get()); } } @@ -367,10 +350,10 @@ void BlenderImporter::ConvertBlendFile(aiScene* out, const Scene& in,const FileD ThrowException("Expected at least one object with no parent"); } - aiNode* root = out->mRootNode = new aiNode(""); + aiNode *root = out->mRootNode = new aiNode(""); root->mNumChildren = static_cast(no_parents.size()); - root->mChildren = new aiNode*[root->mNumChildren](); + root->mChildren = new aiNode *[root->mNumChildren](); for (unsigned int i = 0; i < root->mNumChildren; ++i) { root->mChildren[i] = ConvertNode(in, no_parents[i], conv, aiMatrix4x4()); root->mChildren[i]->mParent = root; @@ -379,32 +362,32 @@ void BlenderImporter::ConvertBlendFile(aiScene* out, const Scene& in,const FileD BuildMaterials(conv); if (conv.meshes->size()) { - out->mMeshes = new aiMesh*[out->mNumMeshes = static_cast( conv.meshes->size() )]; - std::copy(conv.meshes->begin(),conv.meshes->end(),out->mMeshes); + out->mMeshes = new aiMesh *[out->mNumMeshes = static_cast(conv.meshes->size())]; + std::copy(conv.meshes->begin(), conv.meshes->end(), out->mMeshes); conv.meshes.dismiss(); } if (conv.lights->size()) { - out->mLights = new aiLight*[out->mNumLights = static_cast( conv.lights->size() )]; - std::copy(conv.lights->begin(),conv.lights->end(),out->mLights); + out->mLights = new aiLight *[out->mNumLights = static_cast(conv.lights->size())]; + std::copy(conv.lights->begin(), conv.lights->end(), out->mLights); conv.lights.dismiss(); } if (conv.cameras->size()) { - out->mCameras = new aiCamera*[out->mNumCameras = static_cast( conv.cameras->size() )]; - std::copy(conv.cameras->begin(),conv.cameras->end(),out->mCameras); + out->mCameras = new aiCamera *[out->mNumCameras = static_cast(conv.cameras->size())]; + std::copy(conv.cameras->begin(), conv.cameras->end(), out->mCameras); conv.cameras.dismiss(); } if (conv.materials->size()) { - out->mMaterials = new aiMaterial*[out->mNumMaterials = static_cast( conv.materials->size() )]; - std::copy(conv.materials->begin(),conv.materials->end(),out->mMaterials); + out->mMaterials = new aiMaterial *[out->mNumMaterials = static_cast(conv.materials->size())]; + std::copy(conv.materials->begin(), conv.materials->end(), out->mMaterials); conv.materials.dismiss(); } if (conv.textures->size()) { - out->mTextures = new aiTexture*[out->mNumTextures = static_cast( conv.textures->size() )]; - std::copy(conv.textures->begin(),conv.textures->end(),out->mTextures); + out->mTextures = new aiTexture *[out->mNumTextures = static_cast(conv.textures->size())]; + std::copy(conv.textures->begin(), conv.textures->end(), out->mTextures); conv.textures.dismiss(); } @@ -418,24 +401,25 @@ void BlenderImporter::ConvertBlendFile(aiScene* out, const Scene& in,const FileD } // ------------------------------------------------------------------------------------------------ -void BlenderImporter::ResolveImage(aiMaterial* out, const Material* mat, const MTex* tex, const Image* img, ConversionData& conv_data) -{ - (void)mat; (void)tex; (void)conv_data; +void BlenderImporter::ResolveImage(aiMaterial *out, const Material *mat, const MTex *tex, const Image *img, ConversionData &conv_data) { + (void)mat; + (void)tex; + (void)conv_data; aiString name; // check if the file contents are bundled with the BLEND file if (img->packedfile) { name.data[0] = '*'; - name.length = 1+ ASSIMP_itoa10(name.data+1,static_cast(MAXLEN-1), static_cast(conv_data.textures->size())); + name.length = 1 + ASSIMP_itoa10(name.data + 1, static_cast(MAXLEN - 1), static_cast(conv_data.textures->size())); conv_data.textures->push_back(new aiTexture()); - aiTexture* curTex = conv_data.textures->back(); + aiTexture *curTex = conv_data.textures->back(); // usually 'img->name' will be the original file name of the embedded textures, // so we can extract the file extension from it. - const size_t nlen = strlen( img->name ); - const char* s = img->name+nlen, *e = s; - while ( s >= img->name && *s != '.' ) { + const size_t nlen = strlen(img->name); + const char *s = img->name + nlen, *e = s; + while (s >= img->name && *s != '.') { --s; } @@ -448,14 +432,14 @@ void BlenderImporter::ResolveImage(aiMaterial* out, const Material* mat, const M curTex->mWidth = img->packedfile->size; uint8_t *ch = new uint8_t[curTex->mWidth]; - conv_data.db.reader->SetCurrentPos(static_cast( img->packedfile->data->val)); + conv_data.db.reader->SetCurrentPos(static_cast(img->packedfile->data->val)); conv_data.db.reader->CopyAndAdvance(ch, curTex->mWidth); curTex->pcData = reinterpret_cast(ch); - LogInfo("Reading embedded texture, original file was "+std::string(img->name)); + LogInfo("Reading embedded texture, original file was " + std::string(img->name)); } else { - name = aiString( img->name ); + name = aiString(img->name); } aiTextureType texture_type = aiTextureType_UNKNOWN; @@ -466,13 +450,11 @@ void BlenderImporter::ResolveImage(aiMaterial* out, const Material* mat, const M else if (map_type & MTex::MapType_NORM) { if (tex->tex->imaflag & Tex::ImageFlags_NORMALMAP) { texture_type = aiTextureType_NORMALS; - } - else { + } else { texture_type = aiTextureType_HEIGHT; } - out->AddProperty(&tex->norfac,1,AI_MATKEY_BUMPSCALING); - } - else if (map_type & MTex::MapType_COLSPEC) + out->AddProperty(&tex->norfac, 1, AI_MATKEY_BUMPSCALING); + } else if (map_type & MTex::MapType_COLSPEC) texture_type = aiTextureType_SPECULAR; else if (map_type & MTex::MapType_COLMIR) texture_type = aiTextureType_REFLECTION; @@ -491,86 +473,81 @@ void BlenderImporter::ResolveImage(aiMaterial* out, const Material* mat, const M texture_type = aiTextureType_DISPLACEMENT; //else if (map_type & MTex::MapType_WARP) - out->AddProperty(&name,AI_MATKEY_TEXTURE(texture_type, - conv_data.next_texture[texture_type]++)); - + out->AddProperty(&name, AI_MATKEY_TEXTURE(texture_type, + conv_data.next_texture[texture_type]++)); } // ------------------------------------------------------------------------------------------------ -void BlenderImporter::AddSentinelTexture(aiMaterial* out, const Material* mat, const MTex* tex, ConversionData& conv_data) -{ - (void)mat; (void)tex; (void)conv_data; +void BlenderImporter::AddSentinelTexture(aiMaterial *out, const Material *mat, const MTex *tex, ConversionData &conv_data) { + (void)mat; + (void)tex; + (void)conv_data; aiString name; - name.length = ai_snprintf(name.data, MAXLEN, "Procedural,num=%i,type=%s",conv_data.sentinel_cnt++, - GetTextureTypeDisplayString(tex->tex->type) - ); - out->AddProperty(&name,AI_MATKEY_TEXTURE_DIFFUSE( - conv_data.next_texture[aiTextureType_DIFFUSE]++) - ); + name.length = ai_snprintf(name.data, MAXLEN, "Procedural,num=%i,type=%s", conv_data.sentinel_cnt++, + GetTextureTypeDisplayString(tex->tex->type)); + out->AddProperty(&name, AI_MATKEY_TEXTURE_DIFFUSE( + conv_data.next_texture[aiTextureType_DIFFUSE]++)); } // ------------------------------------------------------------------------------------------------ -void BlenderImporter::ResolveTexture(aiMaterial* out, const Material* mat, const MTex* tex, ConversionData& conv_data) -{ - const Tex* rtex = tex->tex.get(); - if(!rtex || !rtex->type) { +void BlenderImporter::ResolveTexture(aiMaterial *out, const Material *mat, const MTex *tex, ConversionData &conv_data) { + const Tex *rtex = tex->tex.get(); + if (!rtex || !rtex->type) { return; } // We can't support most of the texture types because they're mostly procedural. // These are substituted by a dummy texture. - const char* dispnam = ""; - switch( rtex->type ) - { - // these are listed in blender's UI - case Tex::Type_CLOUDS : - case Tex::Type_WOOD : - case Tex::Type_MARBLE : - case Tex::Type_MAGIC : - case Tex::Type_BLEND : - case Tex::Type_STUCCI : - case Tex::Type_NOISE : - case Tex::Type_PLUGIN : - case Tex::Type_MUSGRAVE : - case Tex::Type_VORONOI : - case Tex::Type_DISTNOISE : - case Tex::Type_ENVMAP : + const char *dispnam = ""; + switch (rtex->type) { + // these are listed in blender's UI + case Tex::Type_CLOUDS: + case Tex::Type_WOOD: + case Tex::Type_MARBLE: + case Tex::Type_MAGIC: + case Tex::Type_BLEND: + case Tex::Type_STUCCI: + case Tex::Type_NOISE: + case Tex::Type_PLUGIN: + case Tex::Type_MUSGRAVE: + case Tex::Type_VORONOI: + case Tex::Type_DISTNOISE: + case Tex::Type_ENVMAP: - // these do no appear in the UI, why? - case Tex::Type_POINTDENSITY : - case Tex::Type_VOXELDATA : + // these do no appear in the UI, why? + case Tex::Type_POINTDENSITY: + case Tex::Type_VOXELDATA: - LogWarn(std::string("Encountered a texture with an unsupported type: ")+dispnam); - AddSentinelTexture(out, mat, tex, conv_data); + LogWarn(std::string("Encountered a texture with an unsupported type: ") + dispnam); + AddSentinelTexture(out, mat, tex, conv_data); + break; + + case Tex::Type_IMAGE: + if (!rtex->ima) { + LogError("A texture claims to be an Image, but no image reference is given"); break; + } + ResolveImage(out, mat, tex, rtex->ima.get(), conv_data); + break; - case Tex::Type_IMAGE : - if (!rtex->ima) { - LogError("A texture claims to be an Image, but no image reference is given"); - break; - } - ResolveImage(out, mat, tex, rtex->ima.get(),conv_data); - break; - - default: - ai_assert(false); + default: + ai_assert(false); }; } // ------------------------------------------------------------------------------------------------ -void BlenderImporter::BuildDefaultMaterial(Blender::ConversionData& conv_data) -{ +void BlenderImporter::BuildDefaultMaterial(Blender::ConversionData &conv_data) { // add a default material if necessary - unsigned int index = static_cast( -1 ); - for( aiMesh* mesh : conv_data.meshes.get() ) { - if (mesh->mMaterialIndex == static_cast( -1 )) { + unsigned int index = static_cast(-1); + for (aiMesh *mesh : conv_data.meshes.get()) { + if (mesh->mMaterialIndex == static_cast(-1)) { - if (index == static_cast( -1 )) { + if (index == static_cast(-1)) { // Setup a default material. std::shared_ptr p(new Material()); - ai_assert(::strlen(AI_DEFAULT_MATERIAL_NAME) < sizeof(p->id.name)-2); - strcpy( p->id.name+2, AI_DEFAULT_MATERIAL_NAME ); + ai_assert(::strlen(AI_DEFAULT_MATERIAL_NAME) < sizeof(p->id.name) - 2); + strcpy(p->id.name + 2, AI_DEFAULT_MATERIAL_NAME); // Note: MSVC11 does not zero-initialize Material here, although it should. // Thus all relevant fields should be explicitly initialized. We cannot add @@ -584,7 +561,7 @@ void BlenderImporter::BuildDefaultMaterial(Blender::ConversionData& conv_data) p->alpha = 0.f; p->har = 0; - index = static_cast( conv_data.materials_raw.size() ); + index = static_cast(conv_data.materials_raw.size()); conv_data.materials_raw.push_back(p); LogInfo("Adding default material"); } @@ -593,8 +570,7 @@ void BlenderImporter::BuildDefaultMaterial(Blender::ConversionData& conv_data) } } -void BlenderImporter::AddBlendParams(aiMaterial* result, const Material* source) -{ +void BlenderImporter::AddBlendParams(aiMaterial *result, const Material *source) { aiColor3D diffuseColor(source->r, source->g, source->b); result->AddProperty(&diffuseColor, 1, "$mat.blend.diffuse.color", 0, 0); @@ -607,7 +583,6 @@ void BlenderImporter::AddBlendParams(aiMaterial* result, const Material* source) int diffuseRamp = 0; result->AddProperty(&diffuseRamp, 1, "$mat.blend.diffuse.ramp", 0, 0); - aiColor3D specularColor(source->specr, source->specg, source->specb); result->AddProperty(&specularColor, 1, "$mat.blend.specular.color", 0, 0); @@ -623,7 +598,6 @@ void BlenderImporter::AddBlendParams(aiMaterial* result, const Material* source) int specularHardness = source->har; result->AddProperty(&specularHardness, 1, "$mat.blend.specular.hardness", 0, 0); - int transparencyUse = source->mode & MA_TRANSPARENCY ? 1 : 0; result->AddProperty(&transparencyUse, 1, "$mat.blend.transparency.use", 0, 0); @@ -666,7 +640,6 @@ void BlenderImporter::AddBlendParams(aiMaterial* result, const Material* source) int transparencyGlossSamples = source->samp_gloss_tra; result->AddProperty(&transparencyGlossSamples, 1, "$mat.blend.transparency.glossSamples", 0, 0); - int mirrorUse = source->mode & MA_RAYMIRROR ? 1 : 0; result->AddProperty(&mirrorUse, 1, "$mat.blend.mirror.use", 0, 0); @@ -704,68 +677,67 @@ void BlenderImporter::AddBlendParams(aiMaterial* result, const Material* source) result->AddProperty(&mirrorGlossAnisotropic, 1, "$mat.blend.mirror.glossAnisotropic", 0, 0); } -void BlenderImporter::BuildMaterials(ConversionData& conv_data) -{ +void BlenderImporter::BuildMaterials(ConversionData &conv_data) { conv_data.materials->reserve(conv_data.materials_raw.size()); BuildDefaultMaterial(conv_data); - for(std::shared_ptr mat : conv_data.materials_raw) { + for (std::shared_ptr mat : conv_data.materials_raw) { // reset per material global counters - for (size_t i = 0; i < sizeof(conv_data.next_texture)/sizeof(conv_data.next_texture[0]);++i) { - conv_data.next_texture[i] = 0 ; + for (size_t i = 0; i < sizeof(conv_data.next_texture) / sizeof(conv_data.next_texture[0]); ++i) { + conv_data.next_texture[i] = 0; } - aiMaterial* mout = new aiMaterial(); + aiMaterial *mout = new aiMaterial(); conv_data.materials->push_back(mout); // For any new material field handled here, the default material above must be updated with an appropriate default value. // set material name - aiString name = aiString(mat->id.name+2); // skip over the name prefix 'MA' - mout->AddProperty(&name,AI_MATKEY_NAME); + aiString name = aiString(mat->id.name + 2); // skip over the name prefix 'MA' + mout->AddProperty(&name, AI_MATKEY_NAME); // basic material colors - aiColor3D col(mat->r,mat->g,mat->b); - if (mat->r || mat->g || mat->b ) { + aiColor3D col(mat->r, mat->g, mat->b); + if (mat->r || mat->g || mat->b) { // Usually, zero diffuse color means no diffuse color at all in the equation. // So we omit this member to express this intent. - mout->AddProperty(&col,1,AI_MATKEY_COLOR_DIFFUSE); + mout->AddProperty(&col, 1, AI_MATKEY_COLOR_DIFFUSE); if (mat->emit) { - aiColor3D emit_col(mat->emit * mat->r, mat->emit * mat->g, mat->emit * mat->b) ; - mout->AddProperty(&emit_col, 1, AI_MATKEY_COLOR_EMISSIVE) ; + aiColor3D emit_col(mat->emit * mat->r, mat->emit * mat->g, mat->emit * mat->b); + mout->AddProperty(&emit_col, 1, AI_MATKEY_COLOR_EMISSIVE); } } - col = aiColor3D(mat->specr,mat->specg,mat->specb); - mout->AddProperty(&col,1,AI_MATKEY_COLOR_SPECULAR); + col = aiColor3D(mat->specr, mat->specg, mat->specb); + mout->AddProperty(&col, 1, AI_MATKEY_COLOR_SPECULAR); // is hardness/shininess set? - if( mat->har ) { + if (mat->har) { const float har = mat->har; - mout->AddProperty(&har,1,AI_MATKEY_SHININESS); + mout->AddProperty(&har, 1, AI_MATKEY_SHININESS); } - col = aiColor3D(mat->ambr,mat->ambg,mat->ambb); - mout->AddProperty(&col,1,AI_MATKEY_COLOR_AMBIENT); + col = aiColor3D(mat->ambr, mat->ambg, mat->ambb); + mout->AddProperty(&col, 1, AI_MATKEY_COLOR_AMBIENT); // is mirror enabled? - if( mat->mode & MA_RAYMIRROR ) { + if (mat->mode & MA_RAYMIRROR) { const float ray_mirror = mat->ray_mirror; - mout->AddProperty(&ray_mirror,1,AI_MATKEY_REFLECTIVITY); + mout->AddProperty(&ray_mirror, 1, AI_MATKEY_REFLECTIVITY); } - col = aiColor3D(mat->mirr,mat->mirg,mat->mirb); - mout->AddProperty(&col,1,AI_MATKEY_COLOR_REFLECTIVE); + col = aiColor3D(mat->mirr, mat->mirg, mat->mirb); + mout->AddProperty(&col, 1, AI_MATKEY_COLOR_REFLECTIVE); - for(size_t i = 0; i < sizeof(mat->mtex) / sizeof(mat->mtex[0]); ++i) { + for (size_t i = 0; i < sizeof(mat->mtex) / sizeof(mat->mtex[0]); ++i) { if (!mat->mtex[i]) { continue; } - ResolveTexture(mout,mat.get(),mat->mtex[i].get(),conv_data); + ResolveTexture(mout, mat.get(), mat->mtex[i].get(), conv_data); } AddBlendParams(mout, mat.get()); @@ -773,85 +745,79 @@ void BlenderImporter::BuildMaterials(ConversionData& conv_data) } // ------------------------------------------------------------------------------------------------ -void BlenderImporter::CheckActualType(const ElemBase* dt, const char* check) -{ +void BlenderImporter::CheckActualType(const ElemBase *dt, const char *check) { ai_assert(dt); - if (strcmp(dt->dna_type,check)) { + if (strcmp(dt->dna_type, check)) { ThrowException((format(), - "Expected object at ",std::hex,dt," to be of type `",check, - "`, but it claims to be a `",dt->dna_type,"`instead" - )); + "Expected object at ", std::hex, dt, " to be of type `", check, + "`, but it claims to be a `", dt->dna_type, "`instead")); } } // ------------------------------------------------------------------------------------------------ -void BlenderImporter::NotSupportedObjectType(const Object* obj, const char* type) -{ - LogWarn((format(), "Object `",obj->id.name,"` - type is unsupported: `",type, "`, skipping" )); +void BlenderImporter::NotSupportedObjectType(const Object *obj, const char *type) { + LogWarn((format(), "Object `", obj->id.name, "` - type is unsupported: `", type, "`, skipping")); } // ------------------------------------------------------------------------------------------------ -void BlenderImporter::ConvertMesh(const Scene& /*in*/, const Object* /*obj*/, const Mesh* mesh, - ConversionData& conv_data, TempArray& temp - ) -{ +void BlenderImporter::ConvertMesh(const Scene & /*in*/, const Object * /*obj*/, const Mesh *mesh, + ConversionData &conv_data, TempArray &temp) { // TODO: Resolve various problems with BMesh triangulation before re-enabling. // See issues #400, #373, #318 #315 and #132. #if defined(TODO_FIX_BMESH_CONVERSION) - BlenderBMeshConverter BMeshConverter( mesh ); - if ( BMeshConverter.ContainsBMesh( ) ) - { - mesh = BMeshConverter.TriangulateBMesh( ); + BlenderBMeshConverter BMeshConverter(mesh); + if (BMeshConverter.ContainsBMesh()) { + mesh = BMeshConverter.TriangulateBMesh(); } #endif - typedef std::pair MyPair; + typedef std::pair MyPair; if ((!mesh->totface && !mesh->totloop) || !mesh->totvert) { return; } // some sanity checks - if (static_cast ( mesh->totface ) > mesh->mface.size() ){ + if (static_cast(mesh->totface) > mesh->mface.size()) { ThrowException("Number of faces is larger than the corresponding array"); } - if (static_cast ( mesh->totvert ) > mesh->mvert.size()) { + if (static_cast(mesh->totvert) > mesh->mvert.size()) { ThrowException("Number of vertices is larger than the corresponding array"); } - if (static_cast ( mesh->totloop ) > mesh->mloop.size()) { + if (static_cast(mesh->totloop) > mesh->mloop.size()) { ThrowException("Number of vertices is larger than the corresponding array"); } // collect per-submesh numbers - std::map per_mat; - std::map per_mat_verts; + std::map per_mat; + std::map per_mat_verts; for (int i = 0; i < mesh->totface; ++i) { - const MFace& mf = mesh->mface[i]; - per_mat[ mf.mat_nr ]++; - per_mat_verts[ mf.mat_nr ] += mf.v4?4:3; + const MFace &mf = mesh->mface[i]; + per_mat[mf.mat_nr]++; + per_mat_verts[mf.mat_nr] += mf.v4 ? 4 : 3; } for (int i = 0; i < mesh->totpoly; ++i) { - const MPoly& mp = mesh->mpoly[i]; - per_mat[ mp.mat_nr ]++; - per_mat_verts[ mp.mat_nr ] += mp.totloop; + const MPoly &mp = mesh->mpoly[i]; + per_mat[mp.mat_nr]++; + per_mat_verts[mp.mat_nr] += mp.totloop; } // ... and allocate the corresponding meshes const size_t old = temp->size(); temp->reserve(temp->size() + per_mat.size()); - std::map mat_num_to_mesh_idx; - for(MyPair& it : per_mat) { + std::map mat_num_to_mesh_idx; + for (MyPair &it : per_mat) { mat_num_to_mesh_idx[it.first] = temp->size(); temp->push_back(new aiMesh()); - aiMesh* out = temp->back(); + aiMesh *out = temp->back(); out->mVertices = new aiVector3D[per_mat_verts[it.first]]; - out->mNormals = new aiVector3D[per_mat_verts[it.first]]; + out->mNormals = new aiVector3D[per_mat_verts[it.first]]; //out->mNumFaces = 0 //out->mNumVertices = 0 @@ -859,45 +825,43 @@ void BlenderImporter::ConvertMesh(const Scene& /*in*/, const Object* /*obj*/, co // all sub-meshes created from this mesh are named equally. this allows // curious users to recover the original adjacency. - out->mName = aiString(mesh->id.name+2); - // skip over the name prefix 'ME' + out->mName = aiString(mesh->id.name + 2); + // skip over the name prefix 'ME' // resolve the material reference and add this material to the set of // output materials. The (temporary) material index is the index // of the material entry within the list of resolved materials. if (mesh->mat) { - if (static_cast ( it.first ) >= mesh->mat.size() ) { + if (static_cast(it.first) >= mesh->mat.size()) { ThrowException("Material index is out of range"); } std::shared_ptr mat = mesh->mat[it.first]; - const std::deque< std::shared_ptr >::iterator has = std::find( + const std::deque>::iterator has = std::find( conv_data.materials_raw.begin(), - conv_data.materials_raw.end(),mat - ); + conv_data.materials_raw.end(), mat); if (has != conv_data.materials_raw.end()) { - out->mMaterialIndex = static_cast( std::distance(conv_data.materials_raw.begin(),has)); - } - else { - out->mMaterialIndex = static_cast( conv_data.materials_raw.size() ); + out->mMaterialIndex = static_cast(std::distance(conv_data.materials_raw.begin(), has)); + } else { + out->mMaterialIndex = static_cast(conv_data.materials_raw.size()); conv_data.materials_raw.push_back(mat); } - } - else out->mMaterialIndex = static_cast( -1 ); + } else + out->mMaterialIndex = static_cast(-1); } for (int i = 0; i < mesh->totface; ++i) { - const MFace& mf = mesh->mface[i]; + const MFace &mf = mesh->mface[i]; - aiMesh* const out = temp[ mat_num_to_mesh_idx[ mf.mat_nr ] ]; - aiFace& f = out->mFaces[out->mNumFaces++]; + aiMesh *const out = temp[mat_num_to_mesh_idx[mf.mat_nr]]; + aiFace &f = out->mFaces[out->mNumFaces++]; - f.mIndices = new unsigned int[ f.mNumIndices = mf.v4?4:3 ]; - aiVector3D* vo = out->mVertices + out->mNumVertices; - aiVector3D* vn = out->mNormals + out->mNumVertices; + f.mIndices = new unsigned int[f.mNumIndices = mf.v4 ? 4 : 3]; + aiVector3D *vo = out->mVertices + out->mNumVertices; + aiVector3D *vn = out->mNormals + out->mNumVertices; // XXX we can't fold this easily, because we are restricted // to the member names from the BLEND file (v1,v2,v3,v4) @@ -908,7 +872,7 @@ void BlenderImporter::ConvertMesh(const Scene& /*in*/, const Object* /*obj*/, co if (mf.v1 >= mesh->totvert) { ThrowException("Vertex index v1 out of range"); } - const MVert* v = &mesh->mvert[mf.v1]; + const MVert *v = &mesh->mvert[mf.v1]; vo->x = v->co[0]; vo->y = v->co[1]; vo->z = v->co[2]; @@ -966,8 +930,8 @@ void BlenderImporter::ConvertMesh(const Scene& /*in*/, const Object* /*obj*/, co ++vn; out->mPrimitiveTypes |= aiPrimitiveType_POLYGON; - } - else out->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE; + } else + out->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE; // } // } @@ -976,29 +940,28 @@ void BlenderImporter::ConvertMesh(const Scene& /*in*/, const Object* /*obj*/, co for (int i = 0; i < mesh->totpoly; ++i) { - const MPoly& mf = mesh->mpoly[i]; + const MPoly &mf = mesh->mpoly[i]; - aiMesh* const out = temp[ mat_num_to_mesh_idx[ mf.mat_nr ] ]; - aiFace& f = out->mFaces[out->mNumFaces++]; + aiMesh *const out = temp[mat_num_to_mesh_idx[mf.mat_nr]]; + aiFace &f = out->mFaces[out->mNumFaces++]; - f.mIndices = new unsigned int[ f.mNumIndices = mf.totloop ]; - aiVector3D* vo = out->mVertices + out->mNumVertices; - aiVector3D* vn = out->mNormals + out->mNumVertices; + f.mIndices = new unsigned int[f.mNumIndices = mf.totloop]; + aiVector3D *vo = out->mVertices + out->mNumVertices; + aiVector3D *vn = out->mNormals + out->mNumVertices; // XXX we can't fold this easily, because we are restricted // to the member names from the BLEND file (v1,v2,v3,v4) // which are assigned by the genblenddna.py script and // cannot be changed without breaking the entire // import process. - for (int j = 0;j < mf.totloop; ++j) - { - const MLoop& loop = mesh->mloop[mf.loopstart + j]; + for (int j = 0; j < mf.totloop; ++j) { + const MLoop &loop = mesh->mloop[mf.loopstart + j]; if (loop.v >= mesh->totvert) { ThrowException("Vertex index out of range"); } - const MVert& v = mesh->mvert[loop.v]; + const MVert &v = mesh->mvert[loop.v]; vo->x = v.co[0]; vo->y = v.co[1]; @@ -1010,14 +973,10 @@ void BlenderImporter::ConvertMesh(const Scene& /*in*/, const Object* /*obj*/, co ++vo; ++vn; - } - if (mf.totloop == 3) - { + if (mf.totloop == 3) { out->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE; - } - else - { + } else { out->mPrimitiveTypes |= aiPrimitiveType_POLYGON; } } @@ -1052,17 +1011,17 @@ void BlenderImporter::ConvertMesh(const Scene& /*in*/, const Object* /*obj*/, co // collect texture coordinates, they're stored in a separate per-face buffer if (mesh->mtface || mesh->mloopuv) { - if (mesh->totface > static_cast ( mesh->mtface.size())) { + if (mesh->totface > static_cast(mesh->mtface.size())) { ThrowException("Number of UV faces is larger than the corresponding UV face array (#1)"); } - for (std::vector::iterator it = temp->begin()+old; it != temp->end(); ++it) { - ai_assert((*it)->mNumVertices && (*it)->mNumFaces); + for (std::vector::iterator it = temp->begin() + old; it != temp->end(); ++it) { + ai_assert(0 != (*it)->mNumVertices); + ai_assert(0 != (*it)->mNumFaces); const auto itMatTexUvMapping = matTexUvMappings.find((*it)->mMaterialIndex); if (itMatTexUvMapping == matTexUvMappings.end()) { // default behaviour like before (*it)->mTextureCoords[0] = new aiVector3D[(*it)->mNumVertices]; - } - else { + } else { // create texture coords for every mapped tex for (uint32_t i = 0; i < itMatTexUvMapping->second.size(); ++i) { (*it)->mTextureCoords[i] = new aiVector3D[(*it)->mNumVertices]; @@ -1072,29 +1031,29 @@ void BlenderImporter::ConvertMesh(const Scene& /*in*/, const Object* /*obj*/, co } for (int i = 0; i < mesh->totface; ++i) { - const MTFace* v = &mesh->mtface[i]; + const MTFace *v = &mesh->mtface[i]; - aiMesh* const out = temp[ mat_num_to_mesh_idx[ mesh->mface[i].mat_nr ] ]; - const aiFace& f = out->mFaces[out->mNumFaces++]; + aiMesh *const out = temp[mat_num_to_mesh_idx[mesh->mface[i].mat_nr]]; + const aiFace &f = out->mFaces[out->mNumFaces++]; - aiVector3D* vo = &out->mTextureCoords[0][out->mNumVertices]; - for (unsigned int j = 0; j < f.mNumIndices; ++j,++vo,++out->mNumVertices) { + aiVector3D *vo = &out->mTextureCoords[0][out->mNumVertices]; + for (unsigned int j = 0; j < f.mNumIndices; ++j, ++vo, ++out->mNumVertices) { vo->x = v->uv[j][0]; vo->y = v->uv[j][1]; } } for (int i = 0; i < mesh->totpoly; ++i) { - const MPoly& v = mesh->mpoly[i]; - aiMesh* const out = temp[ mat_num_to_mesh_idx[ v.mat_nr ] ]; - const aiFace& f = out->mFaces[out->mNumFaces++]; + const MPoly &v = mesh->mpoly[i]; + aiMesh *const out = temp[mat_num_to_mesh_idx[v.mat_nr]]; + const aiFace &f = out->mFaces[out->mNumFaces++]; const auto itMatTexUvMapping = matTexUvMappings.find(v.mat_nr); if (itMatTexUvMapping == matTexUvMappings.end()) { // old behavior - aiVector3D* vo = &out->mTextureCoords[0][out->mNumVertices]; + aiVector3D *vo = &out->mTextureCoords[0][out->mNumVertices]; for (unsigned int j = 0; j < f.mNumIndices; ++j, ++vo, ++out->mNumVertices) { - const MLoopUV& uv = mesh->mloopuv[v.loopstart + j]; + const MLoopUV &uv = mesh->mloopuv[v.loopstart + j]; vo->x = uv.uv[0]; vo->y = uv.uv[1]; } @@ -1102,10 +1061,10 @@ void BlenderImporter::ConvertMesh(const Scene& /*in*/, const Object* /*obj*/, co // create textureCoords for every mapped tex for (uint32_t m = 0; m < itMatTexUvMapping->second.size(); ++m) { const MLoopUV *tm = itMatTexUvMapping->second[m]; - aiVector3D* vo = &out->mTextureCoords[m][out->mNumVertices]; + aiVector3D *vo = &out->mTextureCoords[m][out->mNumVertices]; uint32_t j = 0; for (; j < f.mNumIndices; ++j, ++vo) { - const MLoopUV& uv = tm[v.loopstart + j]; + const MLoopUV &uv = tm[v.loopstart + j]; vo->x = uv.uv[0]; vo->y = uv.uv[1]; } @@ -1121,24 +1080,25 @@ void BlenderImporter::ConvertMesh(const Scene& /*in*/, const Object* /*obj*/, co // collect texture coordinates, old-style (marked as deprecated in current blender sources) if (mesh->tface) { - if (mesh->totface > static_cast ( mesh->tface.size())) { + if (mesh->totface > static_cast(mesh->tface.size())) { ThrowException("Number of faces is larger than the corresponding UV face array (#2)"); } - for (std::vector::iterator it = temp->begin()+old; it != temp->end(); ++it) { - ai_assert((*it)->mNumVertices && (*it)->mNumFaces); + for (std::vector::iterator it = temp->begin() + old; it != temp->end(); ++it) { + ai_assert(0 != (*it)->mNumVertices); + ai_assert(0 != (*it)->mNumFaces); (*it)->mTextureCoords[0] = new aiVector3D[(*it)->mNumVertices]; (*it)->mNumFaces = (*it)->mNumVertices = 0; } for (int i = 0; i < mesh->totface; ++i) { - const TFace* v = &mesh->tface[i]; + const TFace *v = &mesh->tface[i]; - aiMesh* const out = temp[ mat_num_to_mesh_idx[ mesh->mface[i].mat_nr ] ]; - const aiFace& f = out->mFaces[out->mNumFaces++]; + aiMesh *const out = temp[mat_num_to_mesh_idx[mesh->mface[i].mat_nr]]; + const aiFace &f = out->mFaces[out->mNumFaces++]; - aiVector3D* vo = &out->mTextureCoords[0][out->mNumVertices]; - for (unsigned int j = 0; j < f.mNumIndices; ++j,++vo,++out->mNumVertices) { + aiVector3D *vo = &out->mTextureCoords[0][out->mNumVertices]; + for (unsigned int j = 0; j < f.mNumIndices; ++j, ++vo, ++out->mNumVertices) { vo->x = v->uv[j][0]; vo->y = v->uv[j][1]; } @@ -1147,11 +1107,12 @@ void BlenderImporter::ConvertMesh(const Scene& /*in*/, const Object* /*obj*/, co // collect vertex colors, stored separately as well if (mesh->mcol || mesh->mloopcol) { - if (mesh->totface > static_cast ( (mesh->mcol.size()/4)) ) { + if (mesh->totface > static_cast((mesh->mcol.size() / 4))) { ThrowException("Number of faces is larger than the corresponding color face array"); } - for (std::vector::iterator it = temp->begin()+old; it != temp->end(); ++it) { - ai_assert((*it)->mNumVertices && (*it)->mNumFaces); + for (std::vector::iterator it = temp->begin() + old; it != temp->end(); ++it) { + ai_assert(0 != (*it)->mNumVertices); + ai_assert(0 != (*it)->mNumFaces); (*it)->mColors[0] = new aiColor4D[(*it)->mNumVertices]; (*it)->mNumFaces = (*it)->mNumVertices = 0; @@ -1159,53 +1120,51 @@ void BlenderImporter::ConvertMesh(const Scene& /*in*/, const Object* /*obj*/, co for (int i = 0; i < mesh->totface; ++i) { - aiMesh* const out = temp[ mat_num_to_mesh_idx[ mesh->mface[i].mat_nr ] ]; - const aiFace& f = out->mFaces[out->mNumFaces++]; + aiMesh *const out = temp[mat_num_to_mesh_idx[mesh->mface[i].mat_nr]]; + const aiFace &f = out->mFaces[out->mNumFaces++]; - aiColor4D* vo = &out->mColors[0][out->mNumVertices]; - for (unsigned int n = 0; n < f.mNumIndices; ++n, ++vo,++out->mNumVertices) { - const MCol* col = &mesh->mcol[(i<<2)+n]; + aiColor4D *vo = &out->mColors[0][out->mNumVertices]; + for (unsigned int n = 0; n < f.mNumIndices; ++n, ++vo, ++out->mNumVertices) { + const MCol *col = &mesh->mcol[(i << 2) + n]; vo->r = col->r; vo->g = col->g; vo->b = col->b; vo->a = col->a; } - for (unsigned int n = f.mNumIndices; n < 4; ++n); + for (unsigned int n = f.mNumIndices; n < 4; ++n) + ; } for (int i = 0; i < mesh->totpoly; ++i) { - const MPoly& v = mesh->mpoly[i]; - aiMesh* const out = temp[ mat_num_to_mesh_idx[ v.mat_nr ] ]; - const aiFace& f = out->mFaces[out->mNumFaces++]; + const MPoly &v = mesh->mpoly[i]; + aiMesh *const out = temp[mat_num_to_mesh_idx[v.mat_nr]]; + const aiFace &f = out->mFaces[out->mNumFaces++]; - aiColor4D* vo = &out->mColors[0][out->mNumVertices]; - const ai_real scaleZeroToOne = 1.f/255.f; - for (unsigned int j = 0; j < f.mNumIndices; ++j,++vo,++out->mNumVertices) { - const MLoopCol& col = mesh->mloopcol[v.loopstart + j]; + aiColor4D *vo = &out->mColors[0][out->mNumVertices]; + const ai_real scaleZeroToOne = 1.f / 255.f; + for (unsigned int j = 0; j < f.mNumIndices; ++j, ++vo, ++out->mNumVertices) { + const MLoopCol &col = mesh->mloopcol[v.loopstart + j]; vo->r = ai_real(col.r) * scaleZeroToOne; vo->g = ai_real(col.g) * scaleZeroToOne; vo->b = ai_real(col.b) * scaleZeroToOne; vo->a = ai_real(col.a) * scaleZeroToOne; } - } - } return; } // ------------------------------------------------------------------------------------------------ -aiCamera* BlenderImporter::ConvertCamera(const Scene& /*in*/, const Object* obj, const Camera* cam, ConversionData& /*conv_data*/) -{ +aiCamera *BlenderImporter::ConvertCamera(const Scene & /*in*/, const Object *obj, const Camera *cam, ConversionData & /*conv_data*/) { std::unique_ptr out(new aiCamera()); - out->mName = obj->id.name+2; + out->mName = obj->id.name + 2; out->mPosition = aiVector3D(0.f, 0.f, 0.f); out->mUp = aiVector3D(0.f, 1.f, 0.f); out->mLookAt = aiVector3D(0.f, 0.f, -1.f); if (cam->sensor_x && cam->lens) { - out->mHorizontalFOV = 2.f * std::atan2(cam->sensor_x, 2.f * cam->lens); + out->mHorizontalFOV = 2.f * std::atan2(cam->sensor_x, 2.f * cam->lens); } out->mClipPlaneNear = cam->clipsta; out->mClipPlaneFar = cam->clipend; @@ -1214,51 +1173,48 @@ aiCamera* BlenderImporter::ConvertCamera(const Scene& /*in*/, const Object* obj, } // ------------------------------------------------------------------------------------------------ -aiLight* BlenderImporter::ConvertLight(const Scene& /*in*/, const Object* obj, const Lamp* lamp, ConversionData& /*conv_data*/) -{ +aiLight *BlenderImporter::ConvertLight(const Scene & /*in*/, const Object *obj, const Lamp *lamp, ConversionData & /*conv_data*/) { std::unique_ptr out(new aiLight()); - out->mName = obj->id.name+2; + out->mName = obj->id.name + 2; - switch (lamp->type) - { - case Lamp::Type_Local: - out->mType = aiLightSource_POINT; - break; - case Lamp::Type_Spot: - out->mType = aiLightSource_SPOT; + switch (lamp->type) { + case Lamp::Type_Local: + out->mType = aiLightSource_POINT; + break; + case Lamp::Type_Spot: + out->mType = aiLightSource_SPOT; - // blender orients directional lights as facing toward -z - out->mDirection = aiVector3D(0.f, 0.f, -1.f); - out->mUp = aiVector3D(0.f, 1.f, 0.f); + // blender orients directional lights as facing toward -z + out->mDirection = aiVector3D(0.f, 0.f, -1.f); + out->mUp = aiVector3D(0.f, 1.f, 0.f); - out->mAngleInnerCone = lamp->spotsize * (1.0f - lamp->spotblend); - out->mAngleOuterCone = lamp->spotsize; - break; - case Lamp::Type_Sun: - out->mType = aiLightSource_DIRECTIONAL; + out->mAngleInnerCone = lamp->spotsize * (1.0f - lamp->spotblend); + out->mAngleOuterCone = lamp->spotsize; + break; + case Lamp::Type_Sun: + out->mType = aiLightSource_DIRECTIONAL; - // blender orients directional lights as facing toward -z - out->mDirection = aiVector3D(0.f, 0.f, -1.f); - out->mUp = aiVector3D(0.f, 1.f, 0.f); - break; + // blender orients directional lights as facing toward -z + out->mDirection = aiVector3D(0.f, 0.f, -1.f); + out->mUp = aiVector3D(0.f, 1.f, 0.f); + break; - case Lamp::Type_Area: - out->mType = aiLightSource_AREA; + case Lamp::Type_Area: + out->mType = aiLightSource_AREA; - if (lamp->area_shape == 0) { - out->mSize = aiVector2D(lamp->area_size, lamp->area_size); - } - else { - out->mSize = aiVector2D(lamp->area_size, lamp->area_sizey); - } + if (lamp->area_shape == 0) { + out->mSize = aiVector2D(lamp->area_size, lamp->area_size); + } else { + out->mSize = aiVector2D(lamp->area_size, lamp->area_sizey); + } - // blender orients directional lights as facing toward -z - out->mDirection = aiVector3D(0.f, 0.f, -1.f); - out->mUp = aiVector3D(0.f, 1.f, 0.f); - break; + // blender orients directional lights as facing toward -z + out->mDirection = aiVector3D(0.f, 0.f, -1.f); + out->mUp = aiVector3D(0.f, 1.f, 0.f); + break; - default: - break; + default: + break; } out->mColorAmbient = aiColor3D(lamp->r, lamp->g, lamp->b) * lamp->energy; @@ -1268,14 +1224,11 @@ aiLight* BlenderImporter::ConvertLight(const Scene& /*in*/, const Object* obj, c // If default values are supplied, compute the coefficients from light's max distance // Read this: https://imdoingitwrong.wordpress.com/2011/01/31/light-attenuation/ // - if (lamp->constant_coefficient == 1.0f && lamp->linear_coefficient == 0.0f && lamp->quadratic_coefficient == 0.0f && lamp->dist > 0.0f) - { + if (lamp->constant_coefficient == 1.0f && lamp->linear_coefficient == 0.0f && lamp->quadratic_coefficient == 0.0f && lamp->dist > 0.0f) { out->mAttenuationConstant = 1.0f; out->mAttenuationLinear = 2.0f / lamp->dist; out->mAttenuationQuadratic = 1.0f / (lamp->dist * lamp->dist); - } - else - { + } else { out->mAttenuationConstant = lamp->constant_coefficient; out->mAttenuationLinear = lamp->linear_coefficient; out->mAttenuationQuadratic = lamp->quadratic_coefficient; @@ -1285,11 +1238,10 @@ aiLight* BlenderImporter::ConvertLight(const Scene& /*in*/, const Object* obj, c } // ------------------------------------------------------------------------------------------------ -aiNode* BlenderImporter::ConvertNode(const Scene& in, const Object* obj, ConversionData& conv_data, const aiMatrix4x4& parentTransform) -{ - std::deque children; - for(ObjectSet::iterator it = conv_data.objects.begin(); it != conv_data.objects.end() ;) { - const Object* object = *it; +aiNode *BlenderImporter::ConvertNode(const Scene &in, const Object *obj, ConversionData &conv_data, const aiMatrix4x4 &parentTransform) { + std::deque children; + for (ObjectSet::iterator it = conv_data.objects.begin(); it != conv_data.objects.end();) { + const Object *object = *it; if (object->parent == obj) { children.push_back(object); @@ -1299,66 +1251,61 @@ aiNode* BlenderImporter::ConvertNode(const Scene& in, const Object* obj, Convers ++it; } - std::unique_ptr node(new aiNode(obj->id.name+2)); // skip over the name prefix 'OB' + std::unique_ptr node(new aiNode(obj->id.name + 2)); // skip over the name prefix 'OB' if (obj->data) { - switch (obj->type) - { - case Object :: Type_EMPTY: + switch (obj->type) { + case Object ::Type_EMPTY: break; // do nothing - // supported object types - case Object :: Type_MESH: { + case Object ::Type_MESH: { const size_t old = conv_data.meshes->size(); - CheckActualType(obj->data.get(),"Mesh"); - ConvertMesh(in,obj,static_cast(obj->data.get()),conv_data,conv_data.meshes); + CheckActualType(obj->data.get(), "Mesh"); + ConvertMesh(in, obj, static_cast(obj->data.get()), conv_data, conv_data.meshes); if (conv_data.meshes->size() > old) { - node->mMeshes = new unsigned int[node->mNumMeshes = static_cast(conv_data.meshes->size()-old)]; + node->mMeshes = new unsigned int[node->mNumMeshes = static_cast(conv_data.meshes->size() - old)]; for (unsigned int i = 0; i < node->mNumMeshes; ++i) { node->mMeshes[i] = static_cast(i + old); } - }} - break; - case Object :: Type_LAMP: { - CheckActualType(obj->data.get(),"Lamp"); - aiLight* mesh = ConvertLight(in,obj,static_cast( - obj->data.get()),conv_data); + } + } break; + case Object ::Type_LAMP: { + CheckActualType(obj->data.get(), "Lamp"); + aiLight *mesh = ConvertLight(in, obj, static_cast(obj->data.get()), conv_data); if (mesh) { conv_data.lights->push_back(mesh); - }} - break; - case Object :: Type_CAMERA: { - CheckActualType(obj->data.get(),"Camera"); - aiCamera* mesh = ConvertCamera(in,obj,static_cast( - obj->data.get()),conv_data); + } + } break; + case Object ::Type_CAMERA: { + CheckActualType(obj->data.get(), "Camera"); + aiCamera *mesh = ConvertCamera(in, obj, static_cast(obj->data.get()), conv_data); if (mesh) { conv_data.cameras->push_back(mesh); - }} - break; - + } + } break; // unsupported object types / log, but do not break - case Object :: Type_CURVE: - NotSupportedObjectType(obj,"Curve"); + case Object ::Type_CURVE: + NotSupportedObjectType(obj, "Curve"); break; - case Object :: Type_SURF: - NotSupportedObjectType(obj,"Surface"); + case Object ::Type_SURF: + NotSupportedObjectType(obj, "Surface"); break; - case Object :: Type_FONT: - NotSupportedObjectType(obj,"Font"); + case Object ::Type_FONT: + NotSupportedObjectType(obj, "Font"); break; - case Object :: Type_MBALL: - NotSupportedObjectType(obj,"MetaBall"); + case Object ::Type_MBALL: + NotSupportedObjectType(obj, "MetaBall"); break; - case Object :: Type_WAVE: - NotSupportedObjectType(obj,"Wave"); + case Object ::Type_WAVE: + NotSupportedObjectType(obj, "Wave"); break; - case Object :: Type_LATTICE: - NotSupportedObjectType(obj,"Lattice"); + case Object ::Type_LATTICE: + NotSupportedObjectType(obj, "Lattice"); break; // invalid or unknown type @@ -1367,8 +1314,8 @@ aiNode* BlenderImporter::ConvertNode(const Scene& in, const Object* obj, Convers } } - for(unsigned int x = 0; x < 4; ++x) { - for(unsigned int y = 0; y < 4; ++y) { + for (unsigned int x = 0; x < 4; ++x) { + for (unsigned int y = 0; y < 4; ++y) { node->mTransformation[y][x] = obj->obmat[x][y]; } } @@ -1376,19 +1323,19 @@ aiNode* BlenderImporter::ConvertNode(const Scene& in, const Object* obj, Convers aiMatrix4x4 m = parentTransform; m = m.Inverse(); - node->mTransformation = m*node->mTransformation; + node->mTransformation = m * node->mTransformation; if (children.size()) { node->mNumChildren = static_cast(children.size()); - aiNode** nd = node->mChildren = new aiNode*[node->mNumChildren](); - for (const Object* nobj :children) { - *nd = ConvertNode(in,nobj,conv_data,node->mTransformation * parentTransform); + aiNode **nd = node->mChildren = new aiNode *[node->mNumChildren](); + for (const Object *nobj : children) { + *nd = ConvertNode(in, nobj, conv_data, node->mTransformation * parentTransform); (*nd++)->mParent = node.get(); } } // apply modifiers - modifier_cache->ApplyModifiers(*node,conv_data,in,*obj); + modifier_cache->ApplyModifiers(*node, conv_data, in, *obj); return node.release(); } diff --git a/code/AssetLib/COB/COBLoader.cpp b/code/AssetLib/COB/COBLoader.cpp index 52273d9e1..86550e776 100644 --- a/code/AssetLib/COB/COBLoader.cpp +++ b/code/AssetLib/COB/COBLoader.cpp @@ -322,7 +322,9 @@ aiNode *COBImporter::BuildNodes(const Node &root, const Scene &scin, aiScene *fi break; default: + ASSIMP_LOG_ERROR("Unknown option."); ai_assert(false); // shouldn't be here + break; } mat->AddProperty(&shader, 1, AI_MATKEY_SHADING_MODEL); if (shader != aiShadingMode_Gouraud) { diff --git a/code/AssetLib/CSM/CSMLoader.cpp b/code/AssetLib/CSM/CSMLoader.cpp index 914ca4e33..c455bb3a4 100644 --- a/code/AssetLib/CSM/CSMLoader.cpp +++ b/code/AssetLib/CSM/CSMLoader.cpp @@ -127,7 +127,7 @@ void CSMImporter::InternReadFile( const std::string& pFile, std::unique_ptr file( pIOHandler->Open( pFile, "rb")); // Check whether we can read from the file - if( file.get() == NULL) { + if( file.get() == nullptr) { throw DeadlyImportError( "Failed to open CSM file " + pFile + "."); } diff --git a/code/AssetLib/Collada/ColladaHelper.h b/code/AssetLib/Collada/ColladaHelper.h index f41691606..bc93203aa 100644 --- a/code/AssetLib/Collada/ColladaHelper.h +++ b/code/AssetLib/Collada/ColladaHelper.h @@ -298,14 +298,14 @@ struct Accessor { size_t mSubOffset[4]; // Suboffset inside the object for the common 4 elements. For a vector, that's XYZ, for a color RGBA and so on. // For example, SubOffset[0] denotes which of the values inside the object is the vector X component. std::string mSource; // URL of the source array - mutable const Data *mData; // Pointer to the source array, if resolved. NULL else + mutable const Data *mData; // Pointer to the source array, if resolved. nullptr else Accessor() { mCount = 0; mSize = 0; mOffset = 0; mStride = 0; - mData = NULL; + mData = nullptr; mSubOffset[0] = mSubOffset[1] = mSubOffset[2] = mSubOffset[3] = 0; } }; @@ -321,13 +321,13 @@ struct InputChannel { size_t mIndex; // Optional index, if multiple sets of the same data type are given size_t mOffset; // Index offset in the indices array of per-face indices. Don't ask, can't explain that any better. std::string mAccessor; // ID of the accessor where to read the actual values from. - mutable const Accessor *mResolved; // Pointer to the accessor, if resolved. NULL else + mutable const Accessor *mResolved; // Pointer to the accessor, if resolved. nullptr else InputChannel() { mType = IT_Invalid; mIndex = 0; mOffset = 0; - mResolved = NULL; + mResolved = nullptr; } }; diff --git a/code/AssetLib/Collada/ColladaLoader.cpp b/code/AssetLib/Collada/ColladaLoader.cpp index 4e7434fe3..7b0fdd8e0 100644 --- a/code/AssetLib/Collada/ColladaLoader.cpp +++ b/code/AssetLib/Collada/ColladaLoader.cpp @@ -145,7 +145,7 @@ bool ColladaLoader::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool if (extension == "xml" || !extension.length() || checkSig) { /* If CanRead() is called in order to check whether we * support a specific file extension in general pIOHandler - * might be NULL and it's our duty to return true here. + * might be nullptr and it's our duty to return true here. */ if (!pIOHandler) { return true; @@ -316,7 +316,7 @@ void ColladaLoader::ResolveNodeInstances(const ColladaParser &pParser, const Col for (const auto &nodeInst : pNode->mNodeInstances) { // find the corresponding node in the library const ColladaParser::NodeLibrary::const_iterator itt = pParser.mNodeLibrary.find(nodeInst.mNode); - const Collada::Node *nd = itt == pParser.mNodeLibrary.end() ? NULL : (*itt).second; + const Collada::Node *nd = itt == pParser.mNodeLibrary.end() ? nullptr : (*itt).second; // FIX for http://sourceforge.net/tracker/?func=detail&aid=3054873&group_id=226462&atid=1067632 // need to check for both name and ID to catch all. To avoid breaking valid files, @@ -716,7 +716,7 @@ aiMesh *ColladaLoader::CreateMesh(const ColladaParser &pParser, const Collada::M if (targetMesh->mSubMeshes.size() > 1) { throw DeadlyImportError("Morphing target mesh must be a single"); } - aimesh = CreateMesh(pParser, targetMesh, targetMesh->mSubMeshes.at(0), NULL, 0, 0); + aimesh = CreateMesh(pParser, targetMesh, targetMesh->mSubMeshes.at(0), nullptr, 0, 0); mTargetMeshes.push_back(aimesh); } targetMeshes.push_back(aimesh); @@ -1000,7 +1000,7 @@ void ColladaLoader::StoreAnimations(aiScene *pScene, const ColladaParser &pParse combinedAnim->mChannels = new aiNodeAnim *[combinedAnim->mNumChannels]; // add the template anim as first channel by moving its aiNodeAnim to the combined animation combinedAnim->mChannels[0] = templateAnim->mChannels[0]; - templateAnim->mChannels[0] = NULL; + templateAnim->mChannels[0] = nullptr; delete templateAnim; // combined animation replaces template animation in the anim array mAnims[a] = combinedAnim; @@ -1009,7 +1009,7 @@ void ColladaLoader::StoreAnimations(aiScene *pScene, const ColladaParser &pParse for (size_t b = 0; b < collectedAnimIndices.size(); ++b) { aiAnimation *srcAnimation = mAnims[collectedAnimIndices[b]]; combinedAnim->mChannels[1 + b] = srcAnimation->mChannels[0]; - srcAnimation->mChannels[0] = NULL; + srcAnimation->mChannels[0] = nullptr; delete srcAnimation; } @@ -1116,9 +1116,9 @@ void ColladaLoader::CreateAnimation(aiScene *pScene, const ColladaParser &pParse // find the collada node corresponding to the aiNode const Collada::Node *srcNode = FindNode(pParser.mRootNode, nodeName); - // ai_assert( srcNode != NULL); - if (!srcNode) + if (!srcNode) { continue; + } // now check all channels if they affect the current node std::string targetID, subElement; @@ -1132,8 +1132,9 @@ void ColladaLoader::CreateAnimation(aiScene *pScene, const ColladaParser &pParse std::string::size_type slashPos = srcChannel.mTarget.find('/'); if (slashPos == std::string::npos) { std::string::size_type targetPos = srcChannel.mTarget.find(srcNode->mID); - if (targetPos == std::string::npos) + if (targetPos == std::string::npos) { continue; + } // not node transform, but something else. store as unknown animation channel for now entry.mChannel = &(*cit); @@ -1777,11 +1778,12 @@ const Collada::Node *ColladaLoader::FindNode(const Collada::Node *pNode, const s for (size_t a = 0; a < pNode->mChildren.size(); ++a) { const Collada::Node *node = FindNode(pNode->mChildren[a], pName); - if (node) + if (node) { return node; + } } - return NULL; + return nullptr; } // ------------------------------------------------------------------------------------------------ diff --git a/code/AssetLib/Collada/ColladaParser.cpp b/code/AssetLib/Collada/ColladaParser.cpp index c773f137f..87a84710a 100644 --- a/code/AssetLib/Collada/ColladaParser.cpp +++ b/code/AssetLib/Collada/ColladaParser.cpp @@ -86,7 +86,7 @@ ColladaParser::ColladaParser(IOSystem *pIOHandler, const std::string &pFile) : mFormat(FV_1_5_n) { // validate io-handler instance if (nullptr == pIOHandler) { - throw DeadlyImportError("IOSystem is NULL."); + throw DeadlyImportError("IOSystem is nullptr."); } std::unique_ptr daefile; @@ -314,6 +314,7 @@ void ColladaParser::ReadContents(XmlNode &node) { // ------------------------------------------------------------------------------------------------ // Reads the structure of the file +<<<<<<< HEAD void ColladaParser::ReadStructure(XmlNode &node) { for (pugi::xml_node curNode : node.children()) { const std::string name = std::string(curNode.name()); @@ -380,6 +381,44 @@ void ColladaParser::ReadStructure(XmlNode &node) { } else if (mReader->getNodeType() == irr::io::EXN_ELEMENT_END) { break; }*/ +======= +void ColladaParser::ReadStructure() { + while (mReader->read()) { + // beginning of elements + if (mReader->getNodeType() == irr::io::EXN_ELEMENT) { + if (IsElement("asset")) + ReadAssetInfo(); + else if (IsElement("library_animations")) + ReadAnimationLibrary(); + else if (IsElement("library_animation_clips")) + ReadAnimationClipLibrary(); + else if (IsElement("library_controllers")) + ReadControllerLibrary(); + else if (IsElement("library_images")) + ReadImageLibrary(); + else if (IsElement("library_materials")) + ReadMaterialLibrary(); + else if (IsElement("library_effects")) + ReadEffectLibrary(); + else if (IsElement("library_geometries")) + ReadGeometryLibrary(); + else if (IsElement("library_visual_scenes")) + ReadSceneLibrary(); + else if (IsElement("library_lights")) + ReadLightLibrary(); + else if (IsElement("library_cameras")) + ReadCameraLibrary(); + else if (IsElement("library_nodes")) + ReadSceneNode(nullptr); /* some hacking to reuse this piece of code */ + else if (IsElement("scene")) + ReadScene(); + else + SkipElement(); + } else if (mReader->getNodeType() == irr::io::EXN_ELEMENT_END) { + break; + } + } +>>>>>>> master PostProcessRootAnimations(); PostProcessControllers(); @@ -726,7 +765,7 @@ void ColladaParser::ReadAnimation(XmlNode &node, Collada::Animation *pParent) { typedef std::map ChannelMap; ChannelMap channels; // this is the anim container in case we're a container - Animation *anim = NULL; + Animation *anim = nullptr; // optional name given as an attribute std::string animName; @@ -1933,9 +1972,6 @@ void ColladaParser::ReadGeometryLibrary(XmlNode &node) { int indexID = GetAttribute("id"); std::string id = mReader->getAttributeValue(indexID); - // TODO: (thom) support SIDs - // ai_assert( TestAttribute( "sid") == -1); - // create a mesh and store it in the library under its (resolved) ID // Skip and warn if ID is not unique if (mMeshLibrary.find(id) == mMeshLibrary.cend()) { @@ -2555,7 +2591,7 @@ size_t ColladaParser::ReadPrimitives(XmlNode &node, Mesh &pMesh, std::vector and tags this function will create wrong uv coordinates. ///It's not clear from COLLADA documentation is this allowed or not. For now only exporter fixed to avoid such behavior void ColladaParser::CopyVertex(size_t currentVertex, size_t numOffsets, size_t numPoints, size_t perVertexOffset, Mesh &pMesh, @@ -2760,8 +2796,6 @@ void ColladaParser::ReadSceneNode(XmlNode &node, Node *pNode) { if (attrName > -1) child->mName = mReader->getAttributeValue(attrName); - // TODO: (thom) support SIDs - // ai_assert( TestAttribute( "sid") == -1); if (pNode) { pNode->mChildren.push_back(child); @@ -2792,7 +2826,7 @@ void ColladaParser::ReadSceneNode(XmlNode &node, Node *pNode) { ReadNodeTransformation(pNode, TF_SKEW); else if (IsElement("translate")) ReadNodeTransformation(pNode, TF_TRANSLATE); - else if (IsElement("render") && pNode->mParent == NULL && 0 == pNode->mPrimaryCamera.length()) { + else if (IsElement("render") && pNode->mParent == nullptr && 0 == pNode->mPrimaryCamera.length()) { // ... scene evaluation or, in other words, postprocessing pipeline, // or, again in other words, a turing-complete description how to // render a Collada scene. The only thing that is interesting for @@ -3156,17 +3190,19 @@ const char *ColladaParser::GetTextContent() { } // ------------------------------------------------------------------------------------------------ -// Reads the text contents of an element, returns NULL if not given. Skips leading whitespace. +// Reads the text contents of an element, returns nullptr if not given. Skips leading whitespace. const char *ColladaParser::TestTextContent() { // present node should be the beginning of an element if (mReader->getNodeType() != irr::io::EXN_ELEMENT || mReader->isEmptyElement()) - return NULL; + return nullptr; // read contents of the element - if (!mReader->read()) - return NULL; - if (mReader->getNodeType() != irr::io::EXN_TEXT && mReader->getNodeType() != irr::io::EXN_CDATA) - return NULL; + if (!mReader->read()) { + return nullptr; + } + if (mReader->getNodeType() != irr::io::EXN_TEXT && mReader->getNodeType() != irr::io::EXN_CDATA) { + return nullptr; + } // skip leading whitespace const char *text = mReader->getNodeData(); diff --git a/code/AssetLib/Collada/ColladaParser.h b/code/AssetLib/Collada/ColladaParser.h index 69e0c9759..841995de5 100644 --- a/code/AssetLib/Collada/ColladaParser.h +++ b/code/AssetLib/Collada/ColladaParser.h @@ -273,7 +273,7 @@ protected: Skips leading whitespace. */ const char *GetTextContent(); - /** Reads the text contents of an element, returns NULL if not given. + /** Reads the text contents of an element, returns nullptr if not given. Skips leading whitespace. */ const char *TestTextContent(); diff --git a/code/AssetLib/FBX/FBXAnimation.cpp b/code/AssetLib/FBX/FBXAnimation.cpp index 9a54f61a0..d7596131d 100644 --- a/code/AssetLib/FBX/FBXAnimation.cpp +++ b/code/AssetLib/FBX/FBXAnimation.cpp @@ -47,10 +47,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef ASSIMP_BUILD_NO_FBX_IMPORTER -#include "FBXParser.h" #include "FBXDocument.h" -#include "FBXImporter.h" #include "FBXDocumentUtil.h" +#include "FBXImporter.h" +#include "FBXParser.h" namespace Assimp { namespace FBX { @@ -58,65 +58,60 @@ namespace FBX { using namespace Util; // ------------------------------------------------------------------------------------------------ -AnimationCurve::AnimationCurve(uint64_t id, const Element& element, const std::string& name, const Document& /*doc*/) -: Object(id, element, name) -{ - const Scope& sc = GetRequiredScope(element); - const Element& KeyTime = GetRequiredElement(sc,"KeyTime"); - const Element& KeyValueFloat = GetRequiredElement(sc,"KeyValueFloat"); +AnimationCurve::AnimationCurve(uint64_t id, const Element &element, const std::string &name, const Document & /*doc*/) : + Object(id, element, name) { + const Scope &sc = GetRequiredScope(element); + const Element &KeyTime = GetRequiredElement(sc, "KeyTime"); + const Element &KeyValueFloat = GetRequiredElement(sc, "KeyValueFloat"); ParseVectorDataArray(keys, KeyTime); ParseVectorDataArray(values, KeyValueFloat); - if(keys.size() != values.size()) { - DOMError("the number of key times does not match the number of keyframe values",&KeyTime); + if (keys.size() != values.size()) { + DOMError("the number of key times does not match the number of keyframe values", &KeyTime); } // check if the key times are well-ordered - if(!std::equal(keys.begin(), keys.end() - 1, keys.begin() + 1, std::less())) { - DOMError("the keyframes are not in ascending order",&KeyTime); + if (!std::equal(keys.begin(), keys.end() - 1, keys.begin() + 1, std::less())) { + DOMError("the keyframes are not in ascending order", &KeyTime); } - const Element* KeyAttrDataFloat = sc["KeyAttrDataFloat"]; - if(KeyAttrDataFloat) { + const Element *KeyAttrDataFloat = sc["KeyAttrDataFloat"]; + if (KeyAttrDataFloat) { ParseVectorDataArray(attributes, *KeyAttrDataFloat); } - const Element* KeyAttrFlags = sc["KeyAttrFlags"]; - if(KeyAttrFlags) { + const Element *KeyAttrFlags = sc["KeyAttrFlags"]; + if (KeyAttrFlags) { ParseVectorDataArray(flags, *KeyAttrFlags); } } // ------------------------------------------------------------------------------------------------ -AnimationCurve::~AnimationCurve() -{ +AnimationCurve::~AnimationCurve() { // empty } // ------------------------------------------------------------------------------------------------ -AnimationCurveNode::AnimationCurveNode(uint64_t id, const Element& element, const std::string& name, - const Document& doc, const char* const * target_prop_whitelist /*= NULL*/, - size_t whitelist_size /*= 0*/) -: Object(id, element, name) -, target() -, doc(doc) -{ - const Scope& sc = GetRequiredScope(element); +AnimationCurveNode::AnimationCurveNode(uint64_t id, const Element &element, const std::string &name, + const Document &doc, const char *const *target_prop_whitelist /*= nullptr*/, + size_t whitelist_size /*= 0*/) : + Object(id, element, name), target(), doc(doc) { + const Scope &sc = GetRequiredScope(element); // find target node - const char* whitelist[] = {"Model","NodeAttribute","Deformer"}; - const std::vector& conns = doc.GetConnectionsBySourceSequenced(ID(),whitelist,3); + const char *whitelist[] = { "Model", "NodeAttribute", "Deformer" }; + const std::vector &conns = doc.GetConnectionsBySourceSequenced(ID(), whitelist, 3); - for(const Connection* con : conns) { + for (const Connection *con : conns) { // link should go for a property if (!con->PropertyName().length()) { continue; } - if(target_prop_whitelist) { - const char* const s = con->PropertyName().c_str(); + if (target_prop_whitelist) { + const char *const s = con->PropertyName().c_str(); bool ok = false; for (size_t i = 0; i < whitelist_size; ++i) { if (!strcmp(s, target_prop_whitelist[i])) { @@ -130,16 +125,14 @@ AnimationCurveNode::AnimationCurveNode(uint64_t id, const Element& element, cons } } - const Object* const ob = con->DestinationObject(); - if(!ob) { - DOMWarning("failed to read destination object for AnimationCurveNode->Model link, ignoring",&element); + const Object *const ob = con->DestinationObject(); + if (!ob) { + DOMWarning("failed to read destination object for AnimationCurveNode->Model link, ignoring", &element); continue; } - // XXX support constraints as DOM class - //ai_assert(dynamic_cast(ob) || dynamic_cast(ob)); target = ob; - if(!target) { + if (!target) { continue; } @@ -147,42 +140,40 @@ AnimationCurveNode::AnimationCurveNode(uint64_t id, const Element& element, cons break; } - if(!target) { - DOMWarning("failed to resolve target Model/NodeAttribute/Constraint for AnimationCurveNode",&element); + if (!target) { + DOMWarning("failed to resolve target Model/NodeAttribute/Constraint for AnimationCurveNode", &element); } - props = GetPropertyTable(doc,"AnimationCurveNode.FbxAnimCurveNode",element,sc,false); + props = GetPropertyTable(doc, "AnimationCurveNode.FbxAnimCurveNode", element, sc, false); } // ------------------------------------------------------------------------------------------------ -AnimationCurveNode::~AnimationCurveNode() -{ +AnimationCurveNode::~AnimationCurveNode() { // empty } // ------------------------------------------------------------------------------------------------ -const AnimationCurveMap& AnimationCurveNode::Curves() const -{ - if ( curves.empty() ) { +const AnimationCurveMap &AnimationCurveNode::Curves() const { + if (curves.empty()) { // resolve attached animation curves - const std::vector& conns = doc.GetConnectionsByDestinationSequenced(ID(),"AnimationCurve"); + const std::vector &conns = doc.GetConnectionsByDestinationSequenced(ID(), "AnimationCurve"); - for(const Connection* con : conns) { + for (const Connection *con : conns) { // link should go for a property if (!con->PropertyName().length()) { continue; } - const Object* const ob = con->SourceObject(); - if(!ob) { - DOMWarning("failed to read source object for AnimationCurve->AnimationCurveNode link, ignoring",&element); + const Object *const ob = con->SourceObject(); + if (nullptr == ob) { + DOMWarning("failed to read source object for AnimationCurve->AnimationCurveNode link, ignoring", &element); continue; } - const AnimationCurve* const anim = dynamic_cast(ob); - if(!anim) { - DOMWarning("source object for ->AnimationCurveNode link is not an AnimationCurve",&element); + const AnimationCurve *const anim = dynamic_cast(ob); + if (nullptr == anim) { + DOMWarning("source object for ->AnimationCurveNode link is not an AnimationCurve", &element); continue; } @@ -194,53 +185,49 @@ const AnimationCurveMap& AnimationCurveNode::Curves() const } // ------------------------------------------------------------------------------------------------ -AnimationLayer::AnimationLayer(uint64_t id, const Element& element, const std::string& name, const Document& doc) -: Object(id, element, name) -, doc(doc) -{ - const Scope& sc = GetRequiredScope(element); +AnimationLayer::AnimationLayer(uint64_t id, const Element &element, const std::string &name, const Document &doc) : + Object(id, element, name), doc(doc) { + const Scope &sc = GetRequiredScope(element); // note: the props table here bears little importance and is usually absent - props = GetPropertyTable(doc,"AnimationLayer.FbxAnimLayer",element,sc, true); + props = GetPropertyTable(doc, "AnimationLayer.FbxAnimLayer", element, sc, true); } // ------------------------------------------------------------------------------------------------ -AnimationLayer::~AnimationLayer() -{ +AnimationLayer::~AnimationLayer() { // empty } // ------------------------------------------------------------------------------------------------ -AnimationCurveNodeList AnimationLayer::Nodes(const char* const * target_prop_whitelist /*= NULL*/, - size_t whitelist_size /*= 0*/) const -{ +AnimationCurveNodeList AnimationLayer::Nodes(const char *const *target_prop_whitelist /*= nullptr*/, + size_t whitelist_size /*= 0*/) const { AnimationCurveNodeList nodes; // resolve attached animation nodes - const std::vector& conns = doc.GetConnectionsByDestinationSequenced(ID(),"AnimationCurveNode"); + const std::vector &conns = doc.GetConnectionsByDestinationSequenced(ID(), "AnimationCurveNode"); nodes.reserve(conns.size()); - for(const Connection* con : conns) { + for (const Connection *con : conns) { // link should not go to a property if (con->PropertyName().length()) { continue; } - const Object* const ob = con->SourceObject(); - if(!ob) { - DOMWarning("failed to read source object for AnimationCurveNode->AnimationLayer link, ignoring",&element); + const Object *const ob = con->SourceObject(); + if (!ob) { + DOMWarning("failed to read source object for AnimationCurveNode->AnimationLayer link, ignoring", &element); continue; } - const AnimationCurveNode* const anim = dynamic_cast(ob); - if(!anim) { - DOMWarning("source object for ->AnimationLayer link is not an AnimationCurveNode",&element); + const AnimationCurveNode *const anim = dynamic_cast(ob); + if (!anim) { + DOMWarning("source object for ->AnimationLayer link is not an AnimationCurveNode", &element); continue; } - if(target_prop_whitelist) { - const char* s = anim->TargetProperty().c_str(); + if (target_prop_whitelist) { + const char *s = anim->TargetProperty().c_str(); bool ok = false; for (size_t i = 0; i < whitelist_size; ++i) { if (!strcmp(s, target_prop_whitelist[i])) { @@ -248,7 +235,7 @@ AnimationCurveNodeList AnimationLayer::Nodes(const char* const * target_prop_whi break; } } - if(!ok) { + if (!ok) { continue; } } @@ -259,34 +246,33 @@ AnimationCurveNodeList AnimationLayer::Nodes(const char* const * target_prop_whi } // ------------------------------------------------------------------------------------------------ -AnimationStack::AnimationStack(uint64_t id, const Element& element, const std::string& name, const Document& doc) -: Object(id, element, name) -{ - const Scope& sc = GetRequiredScope(element); +AnimationStack::AnimationStack(uint64_t id, const Element &element, const std::string &name, const Document &doc) : + Object(id, element, name) { + const Scope &sc = GetRequiredScope(element); // note: we don't currently use any of these properties so we shouldn't bother if it is missing - props = GetPropertyTable(doc,"AnimationStack.FbxAnimStack",element,sc, true); + props = GetPropertyTable(doc, "AnimationStack.FbxAnimStack", element, sc, true); // resolve attached animation layers - const std::vector& conns = doc.GetConnectionsByDestinationSequenced(ID(),"AnimationLayer"); + const std::vector &conns = doc.GetConnectionsByDestinationSequenced(ID(), "AnimationLayer"); layers.reserve(conns.size()); - for(const Connection* con : conns) { + for (const Connection *con : conns) { // link should not go to a property if (con->PropertyName().length()) { continue; } - const Object* const ob = con->SourceObject(); - if(!ob) { - DOMWarning("failed to read source object for AnimationLayer->AnimationStack link, ignoring",&element); + const Object *const ob = con->SourceObject(); + if (!ob) { + DOMWarning("failed to read source object for AnimationLayer->AnimationStack link, ignoring", &element); continue; } - const AnimationLayer* const anim = dynamic_cast(ob); - if(!anim) { - DOMWarning("source object for ->AnimationStack link is not an AnimationLayer",&element); + const AnimationLayer *const anim = dynamic_cast(ob); + if (!anim) { + DOMWarning("source object for ->AnimationStack link is not an AnimationLayer", &element); continue; } layers.push_back(anim); @@ -294,12 +280,11 @@ AnimationStack::AnimationStack(uint64_t id, const Element& element, const std::s } // ------------------------------------------------------------------------------------------------ -AnimationStack::~AnimationStack() -{ +AnimationStack::~AnimationStack() { // empty } -} //!FBX -} //!Assimp +} // namespace FBX +} // namespace Assimp #endif // ASSIMP_BUILD_NO_FBX_IMPORTER diff --git a/code/AssetLib/FBX/FBXConverter.cpp b/code/AssetLib/FBX/FBXConverter.cpp index eb995f429..71a2cb669 100644 --- a/code/AssetLib/FBX/FBXConverter.cpp +++ b/code/AssetLib/FBX/FBXConverter.cpp @@ -804,11 +804,6 @@ bool FBXConverter::GenerateTransformationNodeChain(const Model &model, const std aiMatrix4x4::Translation(-GeometricTranslation, chain[TransformationComp_GeometricTranslationInverse]); } - // is_complex needs to be consistent with NeedsComplexTransformationChain() - // or the interplay between this code and the animation converter would - // not be guaranteed. - //ai_assert(NeedsComplexTransformationChain(model) == ((chainBits & chainMaskComplex) != 0)); - // now, if we have more than just Translation, Scaling and Rotation, // we need to generate a full node chain to accommodate for assimp's // lack to express pivots and offsets. @@ -1163,7 +1158,8 @@ unsigned int FBXConverter::ConvertMeshSingleMaterial(const MeshGeometry &mesh, c const std::vector &curVertices = shapeGeometry->GetVertices(); const std::vector &curNormals = shapeGeometry->GetNormals(); const std::vector &curIndices = shapeGeometry->GetIndices(); - animMesh->mName.Set(FixAnimMeshName(shapeGeometry->Name())); + //losing channel name if using shapeGeometry->Name() + animMesh->mName.Set(FixAnimMeshName(blendShapeChannel->Name())); for (size_t j = 0; j < curIndices.size(); j++) { const unsigned int curIndex = curIndices.at(j); aiVector3D vertex = curVertices.at(j); @@ -1289,7 +1285,8 @@ unsigned int FBXConverter::ConvertMeshMultiMaterial(const MeshGeometry &mesh, co } if (binormals) { - ai_assert(tangents.size() == vertices.size() && binormals->size() == vertices.size()); + ai_assert(tangents.size() == vertices.size()); + ai_assert(binormals->size() == vertices.size()); out_mesh->mTangents = new aiVector3D[vertices.size()]; out_mesh->mBitangents = new aiVector3D[vertices.size()]; @@ -3164,7 +3161,8 @@ FBXConverter::KeyFrameListList FBXConverter::GetKeyframeList(const std::vectorGetKeys().size() == curve->GetValues().size() && curve->GetKeys().size()); + ai_assert(curve->GetKeys().size() == curve->GetValues().size()); + ai_assert(curve->GetKeys().size()); //get values within the start/stop time window std::shared_ptr Keys(new KeyTimeList()); diff --git a/code/AssetLib/FBX/FBXConverter.h b/code/AssetLib/FBX/FBXConverter.h index c24434c34..7db4b795b 100644 --- a/code/AssetLib/FBX/FBXConverter.h +++ b/code/AssetLib/FBX/FBXConverter.h @@ -220,8 +220,8 @@ private: * each output vertex the DOM index it maps to. */ void ConvertWeights(aiMesh *out, const MeshGeometry &geo, const aiMatrix4x4 &absolute_transform, - aiNode *parent = NULL, unsigned int materialIndex = NO_MATERIAL_SEPARATION, - std::vector *outputVertStartIndices = NULL); + aiNode *parent = nullptr, unsigned int materialIndex = NO_MATERIAL_SEPARATION, + std::vector *outputVertStartIndices = nullptr); // ------------------------------------------------------------------------------------------------ void ConvertCluster(std::vector &local_mesh_bones, const Cluster *cl, diff --git a/code/AssetLib/FBX/FBXDocument.cpp b/code/AssetLib/FBX/FBXDocument.cpp index bab3707d2..88e5c4eb4 100644 --- a/code/AssetLib/FBX/FBXDocument.cpp +++ b/code/AssetLib/FBX/FBXDocument.cpp @@ -221,7 +221,7 @@ const Object* LazyObject::Get(bool dieOnError) if(!DefaultLogger::isNullLogger()) { ASSIMP_LOG_ERROR(ex.what()); } - return NULL; + return nullptr; } if (!object.get()) { @@ -467,7 +467,7 @@ void Document::ReadPropertyTemplates() const Element *Properties70 = (*innerSc)["Properties70"]; if(Properties70) { std::shared_ptr props = std::make_shared( - *Properties70,std::shared_ptr(static_cast(NULL)) + *Properties70, std::shared_ptr(static_cast(nullptr)) ); templates[oname+"."+pname] = props; diff --git a/code/AssetLib/FBX/FBXDocument.h b/code/AssetLib/FBX/FBXDocument.h index 8984b3df7..165bb900e 100644 --- a/code/AssetLib/FBX/FBXDocument.h +++ b/code/AssetLib/FBX/FBXDocument.h @@ -96,7 +96,7 @@ public: template const T* Get(bool dieOnError = false) { const Object* const ob = Get(dieOnError); - return ob ? dynamic_cast(ob) : NULL; + return ob ? dynamic_cast(ob) : nullptr; } uint64_t ID() const { @@ -213,7 +213,8 @@ private: type name() const { \ const int ival = PropertyGet(Props(), fbx_stringize(name), static_cast(default_value)); \ if (ival < 0 || ival >= AI_CONCAT(type, _MAX)) { \ - ai_assert(static_cast(default_value) >= 0 && static_cast(default_value) < AI_CONCAT(type, _MAX)); \ + ai_assert(static_cast(default_value) >= 0); \ + ai_assert(static_cast(default_value) < AI_CONCAT(type, _MAX)); \ return static_cast(default_value); \ } \ return static_cast(ival); \ @@ -744,7 +745,7 @@ public: wants animations for. If the curve node does not match one of these, std::range_error will be thrown. */ AnimationCurveNode(uint64_t id, const Element& element, const std::string& name, const Document& doc, - const char* const * target_prop_whitelist = NULL, size_t whitelist_size = 0); + const char *const *target_prop_whitelist = nullptr, size_t whitelist_size = 0); virtual ~AnimationCurveNode(); @@ -756,7 +757,7 @@ public: const AnimationCurveMap& Curves() const; - /** Object the curve is assigned to, this can be NULL if the + /** Object the curve is assigned to, this can be nullptr if the * target object has no DOM representation or could not * be read for other reasons.*/ const Object* Target() const { @@ -968,7 +969,7 @@ public: // note: a connection ensures that the source and dest objects exist, but // not that they have DOM representations, so the return value of one of - // these functions can still be NULL. + // these functions can still be nullptr. const Object* SourceObject() const; const Object* DestinationObject() const; diff --git a/code/AssetLib/FBX/FBXDocumentUtil.cpp b/code/AssetLib/FBX/FBXDocumentUtil.cpp index 7178e9f26..16235645c 100644 --- a/code/AssetLib/FBX/FBXDocumentUtil.cpp +++ b/code/AssetLib/FBX/FBXDocumentUtil.cpp @@ -65,7 +65,7 @@ void DOMError(const std::string& message, const Token& token) } // ------------------------------------------------------------------------------------------------ -void DOMError(const std::string& message, const Element* element /*= NULL*/) +void DOMError(const std::string& message, const Element* element /*= nullptr*/) { if(element) { DOMError(message,element->KeyToken()); @@ -84,7 +84,7 @@ void DOMWarning(const std::string& message, const Token& token) } // ------------------------------------------------------------------------------------------------ -void DOMWarning(const std::string& message, const Element* element /*= NULL*/) +void DOMWarning(const std::string& message, const Element* element /*= nullptr*/) { if(element) { DOMWarning(message,element->KeyToken()); @@ -106,7 +106,7 @@ std::shared_ptr GetPropertyTable(const Document& doc, { const Element* const Properties70 = sc["Properties70"]; std::shared_ptr templateProps = std::shared_ptr( - static_cast(NULL)); + static_cast(nullptr)); if(templateName.length()) { PropertyTemplateMap::const_iterator it = doc.Templates().find(templateName); diff --git a/code/AssetLib/FBX/FBXMeshGeometry.cpp b/code/AssetLib/FBX/FBXMeshGeometry.cpp index 4a3de9f99..da96934d6 100644 --- a/code/AssetLib/FBX/FBXMeshGeometry.cpp +++ b/code/AssetLib/FBX/FBXMeshGeometry.cpp @@ -241,7 +241,7 @@ const MatIndexArray& MeshGeometry::GetMaterialIndices() const { // ------------------------------------------------------------------------------------------------ const unsigned int* MeshGeometry::ToOutputVertexIndex( unsigned int in_index, unsigned int& count ) const { if ( in_index >= m_mapping_counts.size() ) { - return NULL; + return nullptr; } ai_assert( m_mapping_counts.size() == m_mapping_offsets.size() ); diff --git a/code/AssetLib/FBX/FBXMeshGeometry.h b/code/AssetLib/FBX/FBXMeshGeometry.h index 97265e4b2..f30f527d6 100644 --- a/code/AssetLib/FBX/FBXMeshGeometry.h +++ b/code/AssetLib/FBX/FBXMeshGeometry.h @@ -61,10 +61,10 @@ public: Geometry( uint64_t id, const Element& element, const std::string& name, const Document& doc ); virtual ~Geometry(); - /** Get the Skin attached to this geometry or NULL */ + /** Get the Skin attached to this geometry or nullptr */ const Skin* DeformerSkin() const; - /** Get the BlendShape attached to this geometry or NULL */ + /** Get the BlendShape attached to this geometry or nullptr */ const std::vector& GetBlendShapes() const; private: @@ -123,7 +123,7 @@ public: /** Get per-face-vertex material assignments */ const MatIndexArray& GetMaterialIndices() const; - /** Convert from a fbx file vertex index (for example from a #Cluster weight) or NULL + /** Convert from a fbx file vertex index (for example from a #Cluster weight) or nullptr * if the vertex index is not valid. */ const unsigned int* ToOutputVertexIndex( unsigned int in_index, unsigned int& count ) const; diff --git a/code/AssetLib/FBX/FBXParser.cpp b/code/AssetLib/FBX/FBXParser.cpp index c47f36150..3c9137ccc 100644 --- a/code/AssetLib/FBX/FBXParser.cpp +++ b/code/AssetLib/FBX/FBXParser.cpp @@ -77,7 +77,7 @@ namespace { } // ------------------------------------------------------------------------------------------------ - AI_WONT_RETURN void ParseError(const std::string& message, const Element* element = NULL) AI_WONT_RETURN_SUFFIX; + AI_WONT_RETURN void ParseError(const std::string &message, const Element *element = nullptr) AI_WONT_RETURN_SUFFIX; AI_WONT_RETURN void ParseError(const std::string& message, const Element* element) { if(element) { @@ -181,7 +181,7 @@ Scope::Scope(Parser& parser,bool topLevel) } TokenPtr n = parser.AdvanceToNextToken(); - if(n == NULL) { + if (n == nullptr) { ParseError("unexpected end of file"); } @@ -196,7 +196,7 @@ Scope::Scope(Parser& parser,bool topLevel) // Element() should stop at the next Key token (or right after a Close token) n = parser.CurrentToken(); - if(n == NULL) { + if (n == nullptr) { if (topLevel) { return; } @@ -236,7 +236,7 @@ TokenPtr Parser::AdvanceToNextToken() { last = current; if (cursor == tokens.end()) { - current = NULL; + current = nullptr; } else { current = *cursor++; } @@ -258,7 +258,7 @@ TokenPtr Parser::LastToken() const // ------------------------------------------------------------------------------------------------ uint64_t ParseTokenAsID(const Token& t, const char*& err_out) { - err_out = NULL; + err_out = nullptr; if (t.Type() != TokenType_DATA) { err_out = "expected TOK_DATA token"; @@ -296,7 +296,7 @@ uint64_t ParseTokenAsID(const Token& t, const char*& err_out) size_t ParseTokenAsDim(const Token& t, const char*& err_out) { // same as ID parsing, except there is a trailing asterisk - err_out = NULL; + err_out = nullptr; if (t.Type() != TokenType_DATA) { err_out = "expected TOK_DATA token"; @@ -342,7 +342,7 @@ size_t ParseTokenAsDim(const Token& t, const char*& err_out) // ------------------------------------------------------------------------------------------------ float ParseTokenAsFloat(const Token& t, const char*& err_out) { - err_out = NULL; + err_out = nullptr; if (t.Type() != TokenType_DATA) { err_out = "expected TOK_DATA token"; @@ -385,7 +385,7 @@ float ParseTokenAsFloat(const Token& t, const char*& err_out) // ------------------------------------------------------------------------------------------------ int ParseTokenAsInt(const Token& t, const char*& err_out) { - err_out = NULL; + err_out = nullptr; if (t.Type() != TokenType_DATA) { err_out = "expected TOK_DATA token"; @@ -421,7 +421,7 @@ int ParseTokenAsInt(const Token& t, const char*& err_out) // ------------------------------------------------------------------------------------------------ int64_t ParseTokenAsInt64(const Token& t, const char*& err_out) { - err_out = NULL; + err_out = nullptr; if (t.Type() != TokenType_DATA) { err_out = "expected TOK_DATA token"; @@ -458,7 +458,7 @@ int64_t ParseTokenAsInt64(const Token& t, const char*& err_out) // ------------------------------------------------------------------------------------------------ std::string ParseTokenAsString(const Token& t, const char*& err_out) { - err_out = NULL; + err_out = nullptr; if (t.Type() != TokenType_DATA) { err_out = "expected TOK_DATA token"; @@ -1211,7 +1211,7 @@ bool HasElement( const Scope& sc, const std::string& index ) { // ------------------------------------------------------------------------------------------------ // extract a required element from a scope, abort if the element cannot be found -const Element& GetRequiredElement(const Scope& sc, const std::string& index, const Element* element /*= NULL*/) +const Element& GetRequiredElement(const Scope& sc, const std::string& index, const Element* element /*= nullptr*/) { const Element* el = sc[index]; if(!el) { diff --git a/code/AssetLib/FBX/FBXParser.h b/code/AssetLib/FBX/FBXParser.h index 7617f96ad..3ee3d5033 100644 --- a/code/AssetLib/FBX/FBXParser.h +++ b/code/AssetLib/FBX/FBXParser.h @@ -137,7 +137,7 @@ public: return element->second; } } - return NULL; + return nullptr; } ElementCollection GetCollection(const std::string& index) const { @@ -219,7 +219,7 @@ void ParseVectorDataArray(std::vector& out, const Element& el); bool HasElement( const Scope& sc, const std::string& index ); // extract a required element from a scope, abort if the element cannot be found -const Element& GetRequiredElement(const Scope& sc, const std::string& index, const Element* element = NULL); +const Element &GetRequiredElement(const Scope &sc, const std::string &index, const Element *element = nullptr); // extract required compound scope const Scope& GetRequiredScope(const Element& el); diff --git a/code/AssetLib/FBX/FBXProperties.cpp b/code/AssetLib/FBX/FBXProperties.cpp index afc20e7fb..25282b637 100644 --- a/code/AssetLib/FBX/FBXProperties.cpp +++ b/code/AssetLib/FBX/FBXProperties.cpp @@ -70,7 +70,7 @@ Property::~Property() namespace { // ------------------------------------------------------------------------------------------------ -// read a typed property out of a FBX element. The return value is NULL if the property cannot be read. +// read a typed property out of a FBX element. The return value is nullptr if the property cannot be read. Property* ReadTypedProperty(const Element& element) { ai_assert(element.KeyToken().StringContents() == "P"); @@ -112,7 +112,7 @@ Property* ReadTypedProperty(const Element& element) else if (!strcmp(cs,"double") || !strcmp(cs,"Number") || !strcmp(cs,"Float") || !strcmp(cs,"FieldOfView") || !strcmp( cs, "UnitScaleFactor" ) ) { return new TypedProperty(ParseTokenAsFloat(*tok[4])); } - return NULL; + return nullptr; } @@ -197,7 +197,7 @@ const Property* PropertyTable::Get(const std::string& name) const return templateProps->Get(name); } - return NULL; + return nullptr; } } diff --git a/code/AssetLib/FBX/FBXProperties.h b/code/AssetLib/FBX/FBXProperties.h index 209d5e940..58793d7ae 100644 --- a/code/AssetLib/FBX/FBXProperties.h +++ b/code/AssetLib/FBX/FBXProperties.h @@ -110,7 +110,7 @@ public: const Property* Get(const std::string& name) const; - // PropertyTable's need not be coupled with FBX elements so this can be NULL + // PropertyTable's need not be coupled with FBX elements so this can be nullptr const Element* GetElement() const { return element; } diff --git a/code/AssetLib/FBX/FBXTokenizer.cpp b/code/AssetLib/FBX/FBXTokenizer.cpp index 23c238d1f..bd3ee7ad1 100644 --- a/code/AssetLib/FBX/FBXTokenizer.cpp +++ b/code/AssetLib/FBX/FBXTokenizer.cpp @@ -127,7 +127,7 @@ void ProcessDataToken( TokenList& output_tokens, const char*& start, const char* TokenizeError("unexpected character, expected data token", line, column); } - start = end = NULL; + start = end = nullptr; } } @@ -146,7 +146,7 @@ void Tokenize(TokenList& output_tokens, const char* input) bool in_double_quotes = false; bool pending_data_token = false; - const char* token_begin = NULL, *token_end = NULL; + const char *token_begin = nullptr, *token_end = nullptr; for (const char* cur = input;*cur;column += (*cur == '\t' ? ASSIMP_FBX_TAB_WIDTH : 1), ++cur) { const char c = *cur; diff --git a/code/AssetLib/HMP/HMPLoader.cpp b/code/AssetLib/HMP/HMPLoader.cpp index 54eb395bd..33460cc73 100644 --- a/code/AssetLib/HMP/HMPLoader.cpp +++ b/code/AssetLib/HMP/HMPLoader.cpp @@ -5,8 +5,6 @@ Open Asset Import Library (assimp) Copyright (c) 2006-2020, assimp team - - All rights reserved. Redistribution and use of this software in source and binary forms, @@ -43,17 +41,16 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. /** @file Implementation of the MDL importer class */ - #ifndef ASSIMP_BUILD_NO_HMP_IMPORTER // internal headers #include "AssetLib/HMP/HMPLoader.h" #include "AssetLib/MD2/MD2FileData.h" -#include -#include -#include #include +#include +#include +#include #include @@ -74,24 +71,21 @@ static const aiImporterDesc desc = { // ------------------------------------------------------------------------------------------------ // Constructor to be privately used by Importer -HMPImporter::HMPImporter() -{ +HMPImporter::HMPImporter() { // nothing to do here } // ------------------------------------------------------------------------------------------------ // Destructor, private as well -HMPImporter::~HMPImporter() -{ +HMPImporter::~HMPImporter() { // nothing to do here } // ------------------------------------------------------------------------------------------------ // Returns whether the class can handle the format of the given file. -bool HMPImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool cs) const -{ +bool HMPImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool cs) const { const std::string extension = GetExtension(pFile); - if (extension == "hmp" ) + if (extension == "hmp") return true; // if check for extension is not enough, check for the magic tokens @@ -100,167 +94,155 @@ bool HMPImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool tokens[0] = AI_HMP_MAGIC_NUMBER_LE_4; tokens[1] = AI_HMP_MAGIC_NUMBER_LE_5; tokens[2] = AI_HMP_MAGIC_NUMBER_LE_7; - return CheckMagicToken(pIOHandler,pFile,tokens,3,0); + return CheckMagicToken(pIOHandler, pFile, tokens, 3, 0); } return false; } // ------------------------------------------------------------------------------------------------ // Get list of all file extensions that are handled by this loader -const aiImporterDesc* HMPImporter::GetInfo () const -{ +const aiImporterDesc *HMPImporter::GetInfo() const { return &desc; } // ------------------------------------------------------------------------------------------------ // Imports the given file into the given scene structure. -void HMPImporter::InternReadFile( const std::string& pFile, - aiScene* _pScene, IOSystem* _pIOHandler) -{ - pScene = _pScene; +void HMPImporter::InternReadFile(const std::string &pFile, + aiScene *_pScene, IOSystem *_pIOHandler) { + pScene = _pScene; mIOHandler = _pIOHandler; std::unique_ptr file(mIOHandler->Open(pFile)); // Check whether we can read from the file - if( file.get() == nullptr) - throw DeadlyImportError( "Failed to open HMP file " + pFile + "."); + if (file.get() == nullptr) { + throw DeadlyImportError("Failed to open HMP file " + pFile + "."); + } // Check whether the HMP file is large enough to contain // at least the file header const size_t fileSize = file->FileSize(); - if( fileSize < 50) - throw DeadlyImportError( "HMP File is too small."); + if (fileSize < 50) + throw DeadlyImportError("HMP File is too small."); // Allocate storage and copy the contents of the file to a memory buffer mBuffer = new uint8_t[fileSize]; - file->Read( (void*)mBuffer, 1, fileSize); + file->Read((void *)mBuffer, 1, fileSize); iFileSize = (unsigned int)fileSize; // Determine the file subtype and call the appropriate member function - const uint32_t iMagic = *((uint32_t*)this->mBuffer); + const uint32_t iMagic = *((uint32_t *)this->mBuffer); // HMP4 format if (AI_HMP_MAGIC_NUMBER_LE_4 == iMagic || - AI_HMP_MAGIC_NUMBER_BE_4 == iMagic) - { + AI_HMP_MAGIC_NUMBER_BE_4 == iMagic) { ASSIMP_LOG_DEBUG("HMP subtype: 3D GameStudio A4, magic word is HMP4"); InternReadFile_HMP4(); } // HMP5 format else if (AI_HMP_MAGIC_NUMBER_LE_5 == iMagic || - AI_HMP_MAGIC_NUMBER_BE_5 == iMagic) - { + AI_HMP_MAGIC_NUMBER_BE_5 == iMagic) { ASSIMP_LOG_DEBUG("HMP subtype: 3D GameStudio A5, magic word is HMP5"); InternReadFile_HMP5(); } // HMP7 format else if (AI_HMP_MAGIC_NUMBER_LE_7 == iMagic || - AI_HMP_MAGIC_NUMBER_BE_7 == iMagic) - { + AI_HMP_MAGIC_NUMBER_BE_7 == iMagic) { ASSIMP_LOG_DEBUG("HMP subtype: 3D GameStudio A7, magic word is HMP7"); InternReadFile_HMP7(); - } - else - { + } else { // Print the magic word to the logger char szBuffer[5]; - szBuffer[0] = ((char*)&iMagic)[0]; - szBuffer[1] = ((char*)&iMagic)[1]; - szBuffer[2] = ((char*)&iMagic)[2]; - szBuffer[3] = ((char*)&iMagic)[3]; + szBuffer[0] = ((char *)&iMagic)[0]; + szBuffer[1] = ((char *)&iMagic)[1]; + szBuffer[2] = ((char *)&iMagic)[2]; + szBuffer[3] = ((char *)&iMagic)[3]; szBuffer[4] = '\0'; // We're definitely unable to load this file - throw DeadlyImportError( "Unknown HMP subformat " + pFile + - ". Magic word (" + szBuffer + ") is not known"); + throw DeadlyImportError("Unknown HMP subformat " + pFile + + ". Magic word (" + szBuffer + ") is not known"); } // Set the AI_SCENE_FLAGS_TERRAIN bit pScene->mFlags |= AI_SCENE_FLAGS_TERRAIN; delete[] mBuffer; - mBuffer= nullptr; - + mBuffer = nullptr; } // ------------------------------------------------------------------------------------------------ -void HMPImporter::ValidateHeader_HMP457( ) -{ - const HMP::Header_HMP5* const pcHeader = (const HMP::Header_HMP5*)mBuffer; +void HMPImporter::ValidateHeader_HMP457() { + const HMP::Header_HMP5 *const pcHeader = (const HMP::Header_HMP5 *)mBuffer; - if (120 > iFileSize) - { + if (120 > iFileSize) { throw DeadlyImportError("HMP file is too small (header size is " - "120 bytes, this file is smaller)"); + "120 bytes, this file is smaller)"); } if (!pcHeader->ftrisize_x || !pcHeader->ftrisize_y) throw DeadlyImportError("Size of triangles in either x or y direction is zero"); - if(pcHeader->fnumverts_x < 1.0f || (pcHeader->numverts/pcHeader->fnumverts_x) < 1.0f) + if (pcHeader->fnumverts_x < 1.0f || (pcHeader->numverts / pcHeader->fnumverts_x) < 1.0f) throw DeadlyImportError("Number of triangles in either x or y direction is zero"); - if(!pcHeader->numframes) + if (!pcHeader->numframes) throw DeadlyImportError("There are no frames. At least one should be there"); - } // ------------------------------------------------------------------------------------------------ -void HMPImporter::InternReadFile_HMP4( ) -{ +void HMPImporter::InternReadFile_HMP4() { throw DeadlyImportError("HMP4 is currently not supported"); } // ------------------------------------------------------------------------------------------------ -void HMPImporter::InternReadFile_HMP5( ) -{ +void HMPImporter::InternReadFile_HMP5() { // read the file header and skip everything to byte 84 - const HMP::Header_HMP5* pcHeader = (const HMP::Header_HMP5*)mBuffer; - const unsigned char* szCurrent = (const unsigned char*)(mBuffer+84); + const HMP::Header_HMP5 *pcHeader = (const HMP::Header_HMP5 *)mBuffer; + const unsigned char *szCurrent = (const unsigned char *)(mBuffer + 84); ValidateHeader_HMP457(); // generate an output mesh pScene->mNumMeshes = 1; - pScene->mMeshes = new aiMesh*[1]; - aiMesh* pcMesh = pScene->mMeshes[0] = new aiMesh(); + pScene->mMeshes = new aiMesh *[1]; + aiMesh *pcMesh = pScene->mMeshes[0] = new aiMesh(); pcMesh->mMaterialIndex = 0; pcMesh->mVertices = new aiVector3D[pcHeader->numverts]; pcMesh->mNormals = new aiVector3D[pcHeader->numverts]; const unsigned int height = (unsigned int)(pcHeader->numverts / pcHeader->fnumverts_x); - const unsigned int width = (unsigned int)pcHeader->fnumverts_x; + const unsigned int width = (unsigned int)pcHeader->fnumverts_x; // generate/load a material for the terrain - CreateMaterial(szCurrent,&szCurrent); + CreateMaterial(szCurrent, &szCurrent); // goto offset 120, I don't know why ... // (fixme) is this the frame header? I assume yes since it starts with 2. szCurrent += 36; - SizeCheck(szCurrent + sizeof(const HMP::Vertex_HMP7)*height*width); + SizeCheck(szCurrent + sizeof(const HMP::Vertex_HMP7) * height * width); // now load all vertices from the file - aiVector3D* pcVertOut = pcMesh->mVertices; - aiVector3D* pcNorOut = pcMesh->mNormals; - const HMP::Vertex_HMP5* src = (const HMP::Vertex_HMP5*) szCurrent; - for (unsigned int y = 0; y < height;++y) - { - for (unsigned int x = 0; x < width;++x) - { + aiVector3D *pcVertOut = pcMesh->mVertices; + aiVector3D *pcNorOut = pcMesh->mNormals; + const HMP::Vertex_HMP5 *src = (const HMP::Vertex_HMP5 *)szCurrent; + for (unsigned int y = 0; y < height; ++y) { + for (unsigned int x = 0; x < width; ++x) { pcVertOut->x = x * pcHeader->ftrisize_x; pcVertOut->y = y * pcHeader->ftrisize_y; - pcVertOut->z = (((float)src->z / 0xffff)-0.5f) * pcHeader->ftrisize_x * 8.0f; - MD2::LookupNormalIndex(src->normals162index, *pcNorOut ); - ++pcVertOut;++pcNorOut;++src; + pcVertOut->z = (((float)src->z / 0xffff) - 0.5f) * pcHeader->ftrisize_x * 8.0f; + MD2::LookupNormalIndex(src->normals162index, *pcNorOut); + ++pcVertOut; + ++pcNorOut; + ++src; } } // generate texture coordinates if necessary if (pcHeader->numskins) - GenerateTextureCoords(width,height); + GenerateTextureCoords(width, height); // now build a list of faces - CreateOutputFaceList(width,height); + CreateOutputFaceList(width, height); // there is no nodegraph in HMP files. Simply assign the one mesh // (no, not the one ring) to the root node @@ -272,17 +254,16 @@ void HMPImporter::InternReadFile_HMP5( ) } // ------------------------------------------------------------------------------------------------ -void HMPImporter::InternReadFile_HMP7( ) -{ +void HMPImporter::InternReadFile_HMP7() { // read the file header and skip everything to byte 84 - const HMP::Header_HMP5* const pcHeader = (const HMP::Header_HMP5*)mBuffer; - const unsigned char* szCurrent = (const unsigned char*)(mBuffer+84); + const HMP::Header_HMP5 *const pcHeader = (const HMP::Header_HMP5 *)mBuffer; + const unsigned char *szCurrent = (const unsigned char *)(mBuffer + 84); ValidateHeader_HMP457(); // generate an output mesh pScene->mNumMeshes = 1; - pScene->mMeshes = new aiMesh*[1]; - aiMesh* pcMesh = pScene->mMeshes[0] = new aiMesh(); + pScene->mMeshes = new aiMesh *[1]; + aiMesh *pcMesh = pScene->mMeshes[0] = new aiMesh(); pcMesh->mMaterialIndex = 0; pcMesh->mVertices = new aiVector3D[pcHeader->numverts]; @@ -292,44 +273,44 @@ void HMPImporter::InternReadFile_HMP7( ) const unsigned int width = (unsigned int)pcHeader->fnumverts_x; // generate/load a material for the terrain - CreateMaterial(szCurrent,&szCurrent); + CreateMaterial(szCurrent, &szCurrent); // goto offset 120, I don't know why ... // (fixme) is this the frame header? I assume yes since it starts with 2. szCurrent += 36; - SizeCheck(szCurrent + sizeof(const HMP::Vertex_HMP7)*height*width); + SizeCheck(szCurrent + sizeof(const HMP::Vertex_HMP7) * height * width); // now load all vertices from the file - aiVector3D* pcVertOut = pcMesh->mVertices; - aiVector3D* pcNorOut = pcMesh->mNormals; - const HMP::Vertex_HMP7* src = (const HMP::Vertex_HMP7*) szCurrent; - for (unsigned int y = 0; y < height;++y) - { - for (unsigned int x = 0; x < width;++x) - { + aiVector3D *pcVertOut = pcMesh->mVertices; + aiVector3D *pcNorOut = pcMesh->mNormals; + const HMP::Vertex_HMP7 *src = (const HMP::Vertex_HMP7 *)szCurrent; + for (unsigned int y = 0; y < height; ++y) { + for (unsigned int x = 0; x < width; ++x) { pcVertOut->x = x * pcHeader->ftrisize_x; pcVertOut->y = y * pcHeader->ftrisize_y; // FIXME: What exctly is the correct scaling factor to use? // possibly pcHeader->scale_origin[2] in combination with a // signed interpretation of src->z? - pcVertOut->z = (((float)src->z / 0xffff)-0.5f) * pcHeader->ftrisize_x * 8.0f; + pcVertOut->z = (((float)src->z / 0xffff) - 0.5f) * pcHeader->ftrisize_x * 8.0f; - pcNorOut->x = ((float)src->normal_x / 0x80 ); // * pcHeader->scale_origin[0]; - pcNorOut->y = ((float)src->normal_y / 0x80 ); // * pcHeader->scale_origin[1]; + pcNorOut->x = ((float)src->normal_x / 0x80); // * pcHeader->scale_origin[0]; + pcNorOut->y = ((float)src->normal_y / 0x80); // * pcHeader->scale_origin[1]; pcNorOut->z = 1.0f; pcNorOut->Normalize(); - ++pcVertOut;++pcNorOut;++src; + ++pcVertOut; + ++pcNorOut; + ++src; } } // generate texture coordinates if necessary - if (pcHeader->numskins)GenerateTextureCoords(width,height); + if (pcHeader->numskins) GenerateTextureCoords(width, height); // now build a list of faces - CreateOutputFaceList(width,height); + CreateOutputFaceList(width, height); // there is no nodegraph in HMP files. Simply assign the one mesh // (no, not the One Ring) to the root node @@ -341,96 +322,89 @@ void HMPImporter::InternReadFile_HMP7( ) } // ------------------------------------------------------------------------------------------------ -void HMPImporter::CreateMaterial(const unsigned char* szCurrent, - const unsigned char** szCurrentOut) -{ - aiMesh* const pcMesh = pScene->mMeshes[0]; - const HMP::Header_HMP5* const pcHeader = (const HMP::Header_HMP5*)mBuffer; +void HMPImporter::CreateMaterial(const unsigned char *szCurrent, + const unsigned char **szCurrentOut) { + aiMesh *const pcMesh = pScene->mMeshes[0]; + const HMP::Header_HMP5 *const pcHeader = (const HMP::Header_HMP5 *)mBuffer; // we don't need to generate texture coordinates if // we have no textures in the file ... - if (pcHeader->numskins) - { + if (pcHeader->numskins) { pcMesh->mTextureCoords[0] = new aiVector3D[pcHeader->numverts]; pcMesh->mNumUVComponents[0] = 2; // now read the first skin and skip all others - ReadFirstSkin(pcHeader->numskins,szCurrent,&szCurrent); - } - else - { + ReadFirstSkin(pcHeader->numskins, szCurrent, &szCurrent); + } else { // generate a default material const int iMode = (int)aiShadingMode_Gouraud; - aiMaterial* pcHelper = new aiMaterial(); + aiMaterial *pcHelper = new aiMaterial(); pcHelper->AddProperty(&iMode, 1, AI_MATKEY_SHADING_MODEL); aiColor3D clr; clr.b = clr.g = clr.r = 0.6f; - pcHelper->AddProperty(&clr, 1,AI_MATKEY_COLOR_DIFFUSE); - pcHelper->AddProperty(&clr, 1,AI_MATKEY_COLOR_SPECULAR); + pcHelper->AddProperty(&clr, 1, AI_MATKEY_COLOR_DIFFUSE); + pcHelper->AddProperty(&clr, 1, AI_MATKEY_COLOR_SPECULAR); clr.b = clr.g = clr.r = 0.05f; - pcHelper->AddProperty(&clr, 1,AI_MATKEY_COLOR_AMBIENT); + pcHelper->AddProperty(&clr, 1, AI_MATKEY_COLOR_AMBIENT); aiString szName; szName.Set(AI_DEFAULT_MATERIAL_NAME); - pcHelper->AddProperty(&szName,AI_MATKEY_NAME); + pcHelper->AddProperty(&szName, AI_MATKEY_NAME); // add the material to the scene pScene->mNumMaterials = 1; - pScene->mMaterials = new aiMaterial*[1]; + pScene->mMaterials = new aiMaterial *[1]; pScene->mMaterials[0] = pcHelper; } *szCurrentOut = szCurrent; } // ------------------------------------------------------------------------------------------------ -void HMPImporter::CreateOutputFaceList(unsigned int width,unsigned int height) -{ - aiMesh* const pcMesh = this->pScene->mMeshes[0]; +void HMPImporter::CreateOutputFaceList(unsigned int width, unsigned int height) { + aiMesh *const pcMesh = this->pScene->mMeshes[0]; // Allocate enough storage - pcMesh->mNumFaces = (width-1) * (height-1); + pcMesh->mNumFaces = (width - 1) * (height - 1); pcMesh->mFaces = new aiFace[pcMesh->mNumFaces]; - pcMesh->mNumVertices = pcMesh->mNumFaces*4; - aiVector3D* pcVertices = new aiVector3D[pcMesh->mNumVertices]; - aiVector3D* pcNormals = new aiVector3D[pcMesh->mNumVertices]; + pcMesh->mNumVertices = pcMesh->mNumFaces * 4; + aiVector3D *pcVertices = new aiVector3D[pcMesh->mNumVertices]; + aiVector3D *pcNormals = new aiVector3D[pcMesh->mNumVertices]; - aiFace* pcFaceOut(pcMesh->mFaces); - aiVector3D* pcVertOut = pcVertices; - aiVector3D* pcNorOut = pcNormals; + aiFace *pcFaceOut(pcMesh->mFaces); + aiVector3D *pcVertOut = pcVertices; + aiVector3D *pcNorOut = pcNormals; - aiVector3D* pcUVs = pcMesh->mTextureCoords[0] ? new aiVector3D[pcMesh->mNumVertices] : NULL; - aiVector3D* pcUVOut(pcUVs); + aiVector3D *pcUVs = pcMesh->mTextureCoords[0] ? new aiVector3D[pcMesh->mNumVertices] : nullptr; + aiVector3D *pcUVOut(pcUVs); // Build the terrain square unsigned int iCurrent = 0; - for (unsigned int y = 0; y < height-1;++y) { - for (unsigned int x = 0; x < width-1;++x,++pcFaceOut) { + for (unsigned int y = 0; y < height - 1; ++y) { + for (unsigned int x = 0; x < width - 1; ++x, ++pcFaceOut) { pcFaceOut->mNumIndices = 4; pcFaceOut->mIndices = new unsigned int[4]; - *pcVertOut++ = pcMesh->mVertices[y*width+x]; - *pcVertOut++ = pcMesh->mVertices[(y+1)*width+x]; - *pcVertOut++ = pcMesh->mVertices[(y+1)*width+x+1]; - *pcVertOut++ = pcMesh->mVertices[y*width+x+1]; + *pcVertOut++ = pcMesh->mVertices[y * width + x]; + *pcVertOut++ = pcMesh->mVertices[(y + 1) * width + x]; + *pcVertOut++ = pcMesh->mVertices[(y + 1) * width + x + 1]; + *pcVertOut++ = pcMesh->mVertices[y * width + x + 1]; + *pcNorOut++ = pcMesh->mNormals[y * width + x]; + *pcNorOut++ = pcMesh->mNormals[(y + 1) * width + x]; + *pcNorOut++ = pcMesh->mNormals[(y + 1) * width + x + 1]; + *pcNorOut++ = pcMesh->mNormals[y * width + x + 1]; - *pcNorOut++ = pcMesh->mNormals[y*width+x]; - *pcNorOut++ = pcMesh->mNormals[(y+1)*width+x]; - *pcNorOut++ = pcMesh->mNormals[(y+1)*width+x+1]; - *pcNorOut++ = pcMesh->mNormals[y*width+x+1]; - - if (pcMesh->mTextureCoords[0]) - { - *pcUVOut++ = pcMesh->mTextureCoords[0][y*width+x]; - *pcUVOut++ = pcMesh->mTextureCoords[0][(y+1)*width+x]; - *pcUVOut++ = pcMesh->mTextureCoords[0][(y+1)*width+x+1]; - *pcUVOut++ = pcMesh->mTextureCoords[0][y*width+x+1]; + if (pcMesh->mTextureCoords[0]) { + *pcUVOut++ = pcMesh->mTextureCoords[0][y * width + x]; + *pcUVOut++ = pcMesh->mTextureCoords[0][(y + 1) * width + x]; + *pcUVOut++ = pcMesh->mTextureCoords[0][(y + 1) * width + x + 1]; + *pcUVOut++ = pcMesh->mTextureCoords[0][y * width + x + 1]; } - for (unsigned int i = 0; i < 4;++i) + for (unsigned int i = 0; i < 4; ++i) pcFaceOut->mIndices[i] = iCurrent++; } } @@ -440,58 +414,58 @@ void HMPImporter::CreateOutputFaceList(unsigned int width,unsigned int height) delete[] pcMesh->mNormals; pcMesh->mNormals = pcNormals; - if (pcMesh->mTextureCoords[0]) - { + if (pcMesh->mTextureCoords[0]) { delete[] pcMesh->mTextureCoords[0]; pcMesh->mTextureCoords[0] = pcUVs; } } // ------------------------------------------------------------------------------------------------ -void HMPImporter::ReadFirstSkin(unsigned int iNumSkins, const unsigned char* szCursor, - const unsigned char** szCursorOut) -{ - ai_assert( 0 != iNumSkins ); - ai_assert( nullptr != szCursor); +void HMPImporter::ReadFirstSkin(unsigned int iNumSkins, const unsigned char *szCursor, + const unsigned char **szCursorOut) { + ai_assert(0 != iNumSkins); + ai_assert(nullptr != szCursor); // read the type of the skin ... // sometimes we need to skip 12 bytes here, I don't know why ... - uint32_t iType = *((uint32_t*)szCursor); + uint32_t iType = *((uint32_t *)szCursor); szCursor += sizeof(uint32_t); - if (0 == iType) - { + if (0 == iType) { szCursor += sizeof(uint32_t) * 2; - iType = *((uint32_t*)szCursor); + iType = *((uint32_t *)szCursor); szCursor += sizeof(uint32_t); if (!iType) throw DeadlyImportError("Unable to read HMP7 skin chunk"); - } // read width and height - uint32_t iWidth = *((uint32_t*)szCursor); szCursor += sizeof(uint32_t); - uint32_t iHeight = *((uint32_t*)szCursor); szCursor += sizeof(uint32_t); + uint32_t iWidth = *((uint32_t *)szCursor); + szCursor += sizeof(uint32_t); + uint32_t iHeight = *((uint32_t *)szCursor); + szCursor += sizeof(uint32_t); // allocate an output material - aiMaterial* pcMat = new aiMaterial(); + aiMaterial *pcMat = new aiMaterial(); // read the skin, this works exactly as for MDL7 - ParseSkinLump_3DGS_MDL7(szCursor,&szCursor, - pcMat,iType,iWidth,iHeight); + ParseSkinLump_3DGS_MDL7(szCursor, &szCursor, + pcMat, iType, iWidth, iHeight); // now we need to skip any other skins ... - for (unsigned int i = 1; i< iNumSkins;++i) - { - iType = *((uint32_t*)szCursor); szCursor += sizeof(uint32_t); - iWidth = *((uint32_t*)szCursor); szCursor += sizeof(uint32_t); - iHeight = *((uint32_t*)szCursor); szCursor += sizeof(uint32_t); + for (unsigned int i = 1; i < iNumSkins; ++i) { + iType = *((uint32_t *)szCursor); + szCursor += sizeof(uint32_t); + iWidth = *((uint32_t *)szCursor); + szCursor += sizeof(uint32_t); + iHeight = *((uint32_t *)szCursor); + szCursor += sizeof(uint32_t); - SkipSkinLump_3DGS_MDL7(szCursor,&szCursor,iType,iWidth,iHeight); + SkipSkinLump_3DGS_MDL7(szCursor, &szCursor, iType, iWidth, iHeight); SizeCheck(szCursor); } // setup the material ... pScene->mNumMaterials = 1; - pScene->mMaterials = new aiMaterial*[1]; + pScene->mMaterials = new aiMaterial *[1]; pScene->mMaterials[0] = pcMat; *szCursorOut = szCursor; @@ -500,20 +474,20 @@ void HMPImporter::ReadFirstSkin(unsigned int iNumSkins, const unsigned char* szC // ------------------------------------------------------------------------------------------------ // Generate proepr texture coords void HMPImporter::GenerateTextureCoords( - const unsigned int width, const unsigned int height) -{ - ai_assert(NULL != pScene->mMeshes && NULL != pScene->mMeshes[0] && - NULL != pScene->mMeshes[0]->mTextureCoords[0]); + const unsigned int width, const unsigned int height) { + ai_assert(nullptr != pScene->mMeshes); + ai_assert(nullptr != pScene->mMeshes[0]); + ai_assert(nullptr != pScene->mMeshes[0]->mTextureCoords[0]); - aiVector3D* uv = pScene->mMeshes[0]->mTextureCoords[0]; + aiVector3D *uv = pScene->mMeshes[0]->mTextureCoords[0]; - const float fY = (1.0f / height) + (1.0f / height) / (height-1); - const float fX = (1.0f / width) + (1.0f / width) / (width-1); + const float fY = (1.0f / height) + (1.0f / height) / (height - 1); + const float fX = (1.0f / width) + (1.0f / width) / (width - 1); - for (unsigned int y = 0; y < height;++y) { - for (unsigned int x = 0; x < width;++x,++uv) { - uv->y = fY*y; - uv->x = fX*x; + for (unsigned int y = 0; y < height; ++y) { + for (unsigned int x = 0; x < width; ++x, ++uv) { + uv->y = fY * y; + uv->x = fX * x; uv->z = 0.0f; } } diff --git a/code/AssetLib/IFC/IFCBoolean.cpp b/code/AssetLib/IFC/IFCBoolean.cpp index 22fbaa01d..1e3a0c61f 100644 --- a/code/AssetLib/IFC/IFCBoolean.cpp +++ b/code/AssetLib/IFC/IFCBoolean.cpp @@ -131,7 +131,7 @@ void WritePolygon(std::vector &resultpoly, TempMesh &result) { void ProcessBooleanHalfSpaceDifference(const Schema_2x3::IfcHalfSpaceSolid *hs, TempMesh &result, const TempMesh &first_operand, ConversionData & /*conv*/) { - ai_assert(hs != NULL); + ai_assert(hs != nullptr); const Schema_2x3::IfcPlane *const plane = hs->BaseSurface->ToPtr(); if (!plane) { @@ -366,7 +366,7 @@ bool PointInPoly(const IfcVector3 &p, const std::vector &boundary) { void ProcessPolygonalBoundedBooleanHalfSpaceDifference(const Schema_2x3::IfcPolygonalBoundedHalfSpace *hs, TempMesh &result, const TempMesh &first_operand, ConversionData &conv) { - ai_assert(hs != NULL); + ai_assert(hs != nullptr); const Schema_2x3::IfcPlane *const plane = hs->BaseSurface->ToPtr(); if (!plane) { @@ -665,7 +665,7 @@ void ProcessPolygonalBoundedBooleanHalfSpaceDifference(const Schema_2x3::IfcPoly void ProcessBooleanExtrudedAreaSolidDifference(const Schema_2x3::IfcExtrudedAreaSolid *as, TempMesh &result, const TempMesh &first_operand, ConversionData &conv) { - ai_assert(as != NULL); + ai_assert(as != nullptr); // This case is handled by reduction to an instance of the quadrify() algorithm. // Obviously, this won't work for arbitrarily complex cases. In fact, the first diff --git a/code/AssetLib/IFC/IFCCurve.cpp b/code/AssetLib/IFC/IFCCurve.cpp index 4643574a8..c9d33961d 100644 --- a/code/AssetLib/IFC/IFCCurve.cpp +++ b/code/AssetLib/IFC/IFCCurve.cpp @@ -389,7 +389,8 @@ public: // -------------------------------------------------- void SampleDiscrete(TempMesh& out,IfcFloat a,IfcFloat b) const { - ai_assert(InRange(a) && InRange(b)); + ai_assert(InRange(a)); + ai_assert(InRange(b)); return base->SampleDiscrete(out,TrimParam(a),TrimParam(b)); } @@ -446,7 +447,8 @@ public: // -------------------------------------------------- size_t EstimateSampleCount(IfcFloat a, IfcFloat b) const { - ai_assert(InRange(a) && InRange(b)); + ai_assert(InRange(a)); + ai_assert(InRange(b)); return static_cast( std::ceil(b) - std::floor(a) ); } @@ -489,7 +491,7 @@ Curve* Curve::Convert(const IFC::Schema_2x3::IfcCurve& curve,ConversionData& con } // XXX OffsetCurve2D, OffsetCurve3D not currently supported - return NULL; + return nullptr; } #ifdef ASSIMP_BUILD_DEBUG diff --git a/code/AssetLib/IFC/IFCGeometry.cpp b/code/AssetLib/IFC/IFCGeometry.cpp index f996c8753..7e8a06bbb 100644 --- a/code/AssetLib/IFC/IFCGeometry.cpp +++ b/code/AssetLib/IFC/IFCGeometry.cpp @@ -174,7 +174,7 @@ void ProcessPolygonBoundaries(TempMesh& result, const TempMesh& inmesh, size_t m TempOpening& opening = fake_openings.back(); opening.extrusionDir = master_normal; - opening.solid = NULL; + opening.solid = nullptr; opening.profileMesh = std::make_shared(); opening.profileMesh->mVerts.reserve(*iit); diff --git a/code/AssetLib/IFC/IFCLoader.cpp b/code/AssetLib/IFC/IFCLoader.cpp index 9ec377d21..5201f87b9 100644 --- a/code/AssetLib/IFC/IFCLoader.cpp +++ b/code/AssetLib/IFC/IFCLoader.cpp @@ -172,7 +172,7 @@ void IFCImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy if (GetExtension(pFile) == "ifczip") { #ifndef ASSIMP_BUILD_NO_COMPRESSED_IFC unzFile zip = unzOpen(pFile.c_str()); - if (zip == NULL) { + if (zip == nullptr) { ThrowException("Could not open ifczip file for reading, unzip failed"); } @@ -373,7 +373,7 @@ void SetUnits(ConversionData &conv) { // ------------------------------------------------------------------------------------------------ void SetCoordinateSpace(ConversionData &conv) { - const Schema_2x3::IfcRepresentationContext *fav = NULL; + const Schema_2x3::IfcRepresentationContext *fav = nullptr; for (const Schema_2x3::IfcRepresentationContext &v : conv.proj.RepresentationContexts) { fav = &v; // Model should be the most suitable type of context, hence ignore the others @@ -790,7 +790,7 @@ aiNode *ProcessSpatialStructure(aiNode *parent, const Schema_2x3::IfcProduct &el for (const Schema_2x3::IfcObjectDefinition &def : aggr->RelatedObjects) { if (const Schema_2x3::IfcProduct *const prod = def.ToPtr()) { - aiNode *const ndnew = ProcessSpatialStructure(nd_aggr.get(), *prod, conv, NULL); + aiNode *const ndnew = ProcessSpatialStructure(nd_aggr.get(), *prod, conv, nullptr); if (ndnew) { nd_aggr->mChildren[nd_aggr->mNumChildren++] = ndnew; } @@ -870,7 +870,7 @@ void ProcessSpatialStructures(ConversionData &conv) { if (def.GetID() == prod->GetID()) { IFCImporter::LogVerboseDebug("selecting this spatial structure as root structure"); // got it, this is one primary site. - nodes.push_back(ProcessSpatialStructure(NULL, *prod, conv, NULL)); + nodes.push_back(ProcessSpatialStructure(nullptr, *prod, conv, nullptr)); } } } @@ -887,7 +887,7 @@ void ProcessSpatialStructures(ConversionData &conv) { continue; } - nodes.push_back(ProcessSpatialStructure(NULL, *prod, conv, NULL)); + nodes.push_back(ProcessSpatialStructure(nullptr, *prod, conv, nullptr)); } nb_nodes = nodes.size(); @@ -897,7 +897,7 @@ void ProcessSpatialStructures(ConversionData &conv) { conv.out->mRootNode = nodes[0]; } else if (nb_nodes > 1) { conv.out->mRootNode = new aiNode("Root"); - conv.out->mRootNode->mParent = NULL; + conv.out->mRootNode->mParent = nullptr; conv.out->mRootNode->mNumChildren = static_cast(nb_nodes); conv.out->mRootNode->mChildren = new aiNode *[conv.out->mRootNode->mNumChildren]; diff --git a/code/AssetLib/IFC/IFCReaderGen1_2x3.cpp b/code/AssetLib/IFC/IFCReaderGen1_2x3.cpp index 58ff47113..3376f4d9e 100644 --- a/code/AssetLib/IFC/IFCReaderGen1_2x3.cpp +++ b/code/AssetLib/IFC/IFCReaderGen1_2x3.cpp @@ -54,333 +54,333 @@ namespace { typedef EXPRESS::ConversionSchema::SchemaEntry SchemaEntry; static const SchemaEntry schema_raw_2x3[] = { - SchemaEntry("ifcstairtypeenum",NULL ) -, SchemaEntry("ifcspacetypeenum",NULL ) -, SchemaEntry("ifcwalltypeenum",NULL ) -, SchemaEntry("ifcmonthinyearnumber",NULL ) -, SchemaEntry("ifcheatfluxdensitymeasure",NULL ) -, SchemaEntry("ifckinematicviscositymeasure",NULL ) -, SchemaEntry("ifcsequenceenum",NULL ) -, SchemaEntry("ifcairtoairheatrecoverytypeenum",NULL ) -, SchemaEntry("ifcactorselect",NULL ) -, SchemaEntry("ifctransformertypeenum",NULL ) -, SchemaEntry("ifcunitaryequipmenttypeenum",NULL ) -, SchemaEntry("ifcelectricflowstoragedevicetypeenum",NULL ) -, SchemaEntry("ifcenergysequenceenum",NULL ) -, SchemaEntry("ifcworkcontroltypeenum",NULL ) -, SchemaEntry("ifccurvaturemeasure",NULL ) -, SchemaEntry("ifcparametervalue",NULL ) -, SchemaEntry("ifcappliedvalueselect",NULL ) -, SchemaEntry("ifcwarpingconstantmeasure",NULL ) -, SchemaEntry("ifcarithmeticoperatorenum",NULL ) -, SchemaEntry("ifclinearforcemeasure",NULL ) -, SchemaEntry("ifcwindowpanelpositionenum",NULL ) -, SchemaEntry("ifcflowmetertypeenum",NULL ) -, SchemaEntry("ifcrampflighttypeenum",NULL ) -, SchemaEntry("ifcspecularhighlightselect",NULL ) -, SchemaEntry("ifcactiontypeenum",NULL ) -, SchemaEntry("ifcgeometricprojectionenum",NULL ) -, SchemaEntry("ifctimeseriesdatatypeenum",NULL ) -, SchemaEntry("ifcmagneticfluxmeasure",NULL ) -, SchemaEntry("ifcobjecttypeenum",NULL ) -, SchemaEntry("ifcdataoriginenum",NULL ) -, SchemaEntry("ifcmassdensitymeasure",NULL ) -, SchemaEntry("ifclightfixturetypeenum",NULL ) -, SchemaEntry("ifcservicelifetypeenum",NULL ) -, SchemaEntry("ifcelectricvoltagemeasure",NULL ) -, SchemaEntry("ifcheatingvaluemeasure",NULL ) -, SchemaEntry("ifcpresentabletext",NULL ) -, SchemaEntry("ifcaheadorbehind",NULL ) -, SchemaEntry("ifcsimplevalue",NULL ) -, SchemaEntry("ifcsensortypeenum",NULL ) -, SchemaEntry("ifcderivedunitenum",NULL ) -, SchemaEntry("ifcsizeselect",NULL ) -, SchemaEntry("ifctransportelementtypeenum",NULL ) -, SchemaEntry("ifcinventorytypeenum",NULL ) -, SchemaEntry("ifctextdecoration",NULL ) -, SchemaEntry("ifcdirectionsenseenum",NULL ) -, SchemaEntry("ifcductfittingtypeenum",NULL ) -, SchemaEntry("ifcdocumentstatusenum",NULL ) -, SchemaEntry("ifcslabtypeenum",NULL ) -, SchemaEntry("ifcdoorstyleconstructionenum",NULL ) -, SchemaEntry("ifcvolumemeasure",NULL ) -, SchemaEntry("ifcinductancemeasure",NULL ) -, SchemaEntry("ifccurtainwalltypeenum",NULL ) -, SchemaEntry("ifcsiunitname",NULL ) -, SchemaEntry("ifcspecularexponent",NULL ) -, SchemaEntry("ifcsoundpressuremeasure",NULL ) -, SchemaEntry("ifcanalysistheorytypeenum",NULL ) -, SchemaEntry("ifcgasterminaltypeenum",NULL ) -, SchemaEntry("ifcyearnumber",NULL ) -, SchemaEntry("ifcmodulusofelasticitymeasure",NULL ) -, SchemaEntry("ifcchangeactionenum",NULL ) -, SchemaEntry("ifcdampertypeenum",NULL ) -, SchemaEntry("ifcevaporatortypeenum",NULL ) -, SchemaEntry("ifcionconcentrationmeasure",NULL ) -, SchemaEntry("ifcductsegmenttypeenum",NULL ) -, SchemaEntry("ifcprotectivedevicetypeenum",NULL ) -, SchemaEntry("ifcabsorbeddosemeasure",NULL ) -, SchemaEntry("ifcmassperlengthmeasure",NULL ) -, SchemaEntry("ifctextfontname",NULL ) -, SchemaEntry("ifcorientationselect",NULL ) -, SchemaEntry("ifcilluminancemeasure",NULL ) -, SchemaEntry("ifcfiresuppressionterminaltypeenum",NULL ) -, SchemaEntry("ifcfontstyle",NULL ) -, SchemaEntry("ifcmomentofinertiameasure",NULL ) -, SchemaEntry("ifcmodulusofsubgradereactionmeasure",NULL ) -, SchemaEntry("ifccomplexnumber",NULL ) -, SchemaEntry("ifchumidifiertypeenum",NULL ) -, SchemaEntry("ifcpresentationstyleselect",NULL ) -, SchemaEntry("ifcthermaltransmittancemeasure",NULL ) -, SchemaEntry("ifcribplatedirectionenum",NULL ) -, SchemaEntry("ifcclassificationnotationselect",NULL ) -, SchemaEntry("ifcminuteinhour",NULL ) -, SchemaEntry("ifcinternalorexternalenum",NULL ) -, SchemaEntry("ifcrotationalfrequencymeasure",NULL ) -, SchemaEntry("ifcsanitaryterminaltypeenum",NULL ) -, SchemaEntry("ifcsymbolstyleselect",NULL ) -, SchemaEntry("ifcelementcompositionenum",NULL ) -, SchemaEntry("ifctextpath",NULL ) -, SchemaEntry("ifcpowermeasure",NULL ) -, SchemaEntry("ifcsurfacestyleelementselect",NULL ) -, SchemaEntry("ifcresourceconsumptionenum",NULL ) -, SchemaEntry("ifcelectriccapacitancemeasure",NULL ) -, SchemaEntry("ifclayersetdirectionenum",NULL ) -, SchemaEntry("ifcrailingtypeenum",NULL ) -, SchemaEntry("ifcobjectiveenum",NULL ) -, SchemaEntry("ifcdocumentselect",NULL ) -, SchemaEntry("ifcmodulusoflinearsubgradereactionmeasure",NULL ) -, SchemaEntry("ifcthermaladmittancemeasure",NULL ) -, SchemaEntry("ifctransitioncode",NULL ) -, SchemaEntry("ifcconnectiontypeenum",NULL ) -, SchemaEntry("ifcmonetarymeasure",NULL ) -, SchemaEntry("ifcstackterminaltypeenum",NULL ) -, SchemaEntry("ifccolour",NULL ) -, SchemaEntry("ifctext",NULL ) -, SchemaEntry("ifccontextdependentmeasure",NULL ) -, SchemaEntry("ifcthermalconductivitymeasure",NULL ) -, SchemaEntry("ifcprojectedortruelengthenum",NULL ) -, SchemaEntry("ifcpressuremeasure",NULL ) -, SchemaEntry("ifcmoisturediffusivitymeasure",NULL ) -, SchemaEntry("ifcbooleanoperator",NULL ) -, SchemaEntry("ifcpropertysourceenum",NULL ) -, SchemaEntry("ifctimestamp",NULL ) -, SchemaEntry("ifcmaterialselect",NULL ) -, SchemaEntry("ifcgloballyuniqueid",NULL ) -, SchemaEntry("ifcreflectancemethodenum",NULL ) -, SchemaEntry("ifcvaporpermeabilitymeasure",NULL ) -, SchemaEntry("ifctimeseriesscheduletypeenum",NULL ) -, SchemaEntry("ifclinearmomentmeasure",NULL ) -, SchemaEntry("ifcgeometricsetselect",NULL ) -, SchemaEntry("ifcsectionmodulusmeasure",NULL ) -, SchemaEntry("ifcbsplinecurveform",NULL ) -, SchemaEntry("ifcdimensionextentusage",NULL ) -, SchemaEntry("ifcthermalexpansioncoefficientmeasure",NULL ) -, SchemaEntry("ifchourinday",NULL ) -, SchemaEntry("ifclinearvelocitymeasure",NULL ) -, SchemaEntry("ifctorquemeasure",NULL ) -, SchemaEntry("ifctemperaturegradientmeasure",NULL ) -, SchemaEntry("ifcfillstyleselect",NULL ) -, SchemaEntry("ifcelectricchargemeasure",NULL ) -, SchemaEntry("ifcheatexchangertypeenum",NULL ) -, SchemaEntry("ifcelectriccurrentenum",NULL ) -, SchemaEntry("ifcdaylightsavinghour",NULL ) -, SchemaEntry("ifcshell",NULL ) -, SchemaEntry("ifcdoseequivalentmeasure",NULL ) -, SchemaEntry("ifcprojectordertypeenum",NULL ) -, SchemaEntry("ifcderivedmeasurevalue",NULL ) -, SchemaEntry("ifclightdistributioncurveenum",NULL ) -, SchemaEntry("ifcwarpingmomentmeasure",NULL ) -, SchemaEntry("ifcmembertypeenum",NULL ) -, SchemaEntry("ifcsoundpowermeasure",NULL ) -, SchemaEntry("ifctextalignment",NULL ) -, SchemaEntry("ifccurveoredgecurve",NULL ) -, SchemaEntry("ifcmassflowratemeasure",NULL ) -, SchemaEntry("ifcisothermalmoisturecapacitymeasure",NULL ) -, SchemaEntry("ifccsgselect",NULL ) -, SchemaEntry("ifccoolingtowertypeenum",NULL ) -, SchemaEntry("ifcmassmeasure",NULL ) -, SchemaEntry("ifcpileconstructionenum",NULL ) -, SchemaEntry("ifcdoorstyleoperationenum",NULL ) -, SchemaEntry("ifcflowdirectionenum",NULL ) -, SchemaEntry("ifcthermalloadsourceenum",NULL ) -, SchemaEntry("ifclengthmeasure",NULL ) -, SchemaEntry("ifcconstraintenum",NULL ) -, SchemaEntry("ifcaxis2placement",NULL ) -, SchemaEntry("ifcloadgrouptypeenum",NULL ) -, SchemaEntry("ifcvalue",NULL ) -, SchemaEntry("ifcreinforcingbarsurfaceenum",NULL ) -, SchemaEntry("ifcprojectorderrecordtypeenum",NULL ) -, SchemaEntry("ifcdatetimeselect",NULL ) -, SchemaEntry("ifcstructuralsurfacetypeenum",NULL ) -, SchemaEntry("ifcpermeablecoveringoperationenum",NULL ) -, SchemaEntry("ifcfontweight",NULL ) -, SchemaEntry("ifcphmeasure",NULL ) -, SchemaEntry("ifcdescriptivemeasure",NULL ) -, SchemaEntry("ifccurvestylefontselect",NULL ) -, SchemaEntry("ifcunit",NULL ) -, SchemaEntry("ifchatchlinedistanceselect",NULL ) -, SchemaEntry("ifctextstyleselect",NULL ) -, SchemaEntry("ifcmetricvalueselect",NULL ) -, SchemaEntry("ifcvectorordirection",NULL ) -, SchemaEntry("ifcassemblyplaceenum",NULL ) -, SchemaEntry("ifcairterminaltypeenum",NULL ) -, SchemaEntry("ifccoveringtypeenum",NULL ) -, SchemaEntry("ifcplanarforcemeasure",NULL ) -, SchemaEntry("ifcvalvetypeenum",NULL ) -, SchemaEntry("ifcalarmtypeenum",NULL ) -, SchemaEntry("ifcdynamicviscositymeasure",NULL ) -, SchemaEntry("ifccurrencyenum",NULL ) -, SchemaEntry("ifcmodulusofrotationalsubgradereactionmeasure",NULL ) -, SchemaEntry("ifccablecarrierfittingtypeenum",NULL ) -, SchemaEntry("ifcboolean",NULL ) -, SchemaEntry("ifcactionsourcetypeenum",NULL ) -, SchemaEntry("ifcstructuralactivityassignmentselect",NULL ) -, SchemaEntry("ifcdistributionchamberelementtypeenum",NULL ) -, SchemaEntry("ifcevaporativecoolertypeenum",NULL ) -, SchemaEntry("ifcmagneticfluxdensitymeasure",NULL ) -, SchemaEntry("ifclightdistributiondatasourceselect",NULL ) -, SchemaEntry("ifctubebundletypeenum",NULL ) -, SchemaEntry("ifcaccelerationmeasure",NULL ) -, SchemaEntry("ifcboilertypeenum",NULL ) -, SchemaEntry("ifcramptypeenum",NULL ) -, SchemaEntry("ifcluminousintensitydistributionmeasure",NULL ) -, SchemaEntry("ifctrimmingpreference",NULL ) -, SchemaEntry("ifcspecificheatcapacitymeasure",NULL ) -, SchemaEntry("ifcamountofsubstancemeasure",NULL ) -, SchemaEntry("ifcroleenum",NULL ) -, SchemaEntry("ifcdocumentconfidentialityenum",NULL ) -, SchemaEntry("ifcfrequencymeasure",NULL ) -, SchemaEntry("ifcsectiontypeenum",NULL ) -, SchemaEntry("ifcelementassemblytypeenum",NULL ) -, SchemaEntry("ifcfootingtypeenum",NULL ) -, SchemaEntry("ifclayereditem",NULL ) -, SchemaEntry("ifccablesegmenttypeenum",NULL ) -, SchemaEntry("ifcdefinedsymbolselect",NULL ) -, SchemaEntry("ifcbuildingelementproxytypeenum",NULL ) -, SchemaEntry("ifcelectricgeneratortypeenum",NULL ) -, SchemaEntry("ifcrotationalstiffnessmeasure",NULL ) -, SchemaEntry("ifcspaceheatertypeenum",NULL ) -, SchemaEntry("ifcareameasure",NULL ) -, SchemaEntry("ifclabel",NULL ) -, SchemaEntry("ifccostscheduletypeenum",NULL ) -, SchemaEntry("ifcswitchingdevicetypeenum",NULL ) -, SchemaEntry("ifcelectrictimecontroltypeenum",NULL ) -, SchemaEntry("ifcfiltertypeenum",NULL ) -, SchemaEntry("ifcpositivelengthmeasure",NULL ) -, SchemaEntry("ifcnullstyle",NULL ) -, SchemaEntry("ifcconditioncriterionselect",NULL ) -, SchemaEntry("ifcshearmodulusmeasure",NULL ) -, SchemaEntry("ifcnormalisedratiomeasure",NULL ) -, SchemaEntry("ifcdoorpaneloperationenum",NULL ) -, SchemaEntry("ifcpointorvertexpoint",NULL ) -, SchemaEntry("ifcrooftypeenum",NULL ) -, SchemaEntry("ifccountmeasure",NULL ) -, SchemaEntry("ifcelectricconductancemeasure",NULL ) -, SchemaEntry("ifcproceduretypeenum",NULL ) -, SchemaEntry("ifcflowinstrumenttypeenum",NULL ) -, SchemaEntry("ifcelectricmotortypeenum",NULL ) -, SchemaEntry("ifcsurfaceside",NULL ) -, SchemaEntry("ifcstructuralcurvetypeenum",NULL ) -, SchemaEntry("ifccondensertypeenum",NULL ) -, SchemaEntry("ifclinearstiffnessmeasure",NULL ) -, SchemaEntry("ifcunitenum",NULL ) -, SchemaEntry("ifcoccupanttypeenum",NULL ) -, SchemaEntry("ifcthermalloadtypeenum",NULL ) -, SchemaEntry("ifcreinforcingbarroleenum",NULL ) -, SchemaEntry("ifcbenchmarkenum",NULL ) -, SchemaEntry("ifcpositiveplaneanglemeasure",NULL ) -, SchemaEntry("ifctexttransformation",NULL ) -, SchemaEntry("ifcdraughtingcalloutelement",NULL ) -, SchemaEntry("ifcratiomeasure",NULL ) -, SchemaEntry("ifcsolidanglemeasure",NULL ) -, SchemaEntry("ifcpipesegmenttypeenum",NULL ) -, SchemaEntry("ifccablecarriersegmenttypeenum",NULL ) -, SchemaEntry("ifccolourorfactor",NULL ) -, SchemaEntry("ifcidentifier",NULL ) -, SchemaEntry("ifctendontypeenum",NULL ) -, SchemaEntry("ifccontrollertypeenum",NULL ) -, SchemaEntry("ifcradioactivitymeasure",NULL ) -, SchemaEntry("ifctimemeasure",NULL ) -, SchemaEntry("ifcpumptypeenum",NULL ) -, SchemaEntry("ifcelectricheatertypeenum",NULL ) -, SchemaEntry("ifcbeamtypeenum",NULL ) -, SchemaEntry("ifcstateenum",NULL ) -, SchemaEntry("ifcsiprefix",NULL ) -, SchemaEntry("ifcnumericmeasure",NULL ) -, SchemaEntry("ifcoutlettypeenum",NULL ) -, SchemaEntry("ifccompoundplaneanglemeasure",NULL ) -, SchemaEntry("ifcservicelifefactortypeenum",NULL ) -, SchemaEntry("ifclogicaloperatorenum",NULL ) -, SchemaEntry("ifcbooleanoperand",NULL ) -, SchemaEntry("ifcobjectreferenceselect",NULL ) -, SchemaEntry("ifccooledbeamtypeenum",NULL ) -, SchemaEntry("ifcductsilencertypeenum",NULL ) -, SchemaEntry("ifcsectionalareaintegralmeasure",NULL ) -, SchemaEntry("ifcfontvariant",NULL ) -, SchemaEntry("ifcvolumetricflowratemeasure",NULL ) -, SchemaEntry("ifcplatetypeenum",NULL ) -, SchemaEntry("ifcenvironmentalimpactcategoryenum",NULL ) -, SchemaEntry("ifcvibrationisolatortypeenum",NULL ) -, SchemaEntry("ifcthermodynamictemperaturemeasure",NULL ) -, SchemaEntry("ifcrotationalmassmeasure",NULL ) -, SchemaEntry("ifcsecondinminute",NULL ) -, SchemaEntry("ifcdayinmonthnumber",NULL ) -, SchemaEntry("ifcdimensioncount",NULL ) -, SchemaEntry("ifcwindowstyleoperationenum",NULL ) -, SchemaEntry("ifcthermalresistancemeasure",NULL ) -, SchemaEntry("ifcmeasurevalue",NULL ) -, SchemaEntry("ifcwindowpaneloperationenum",NULL ) -, SchemaEntry("ifcchillertypeenum",NULL ) -, SchemaEntry("ifcpositiveratiomeasure",NULL ) -, SchemaEntry("ifcinteger",NULL ) -, SchemaEntry("ifclogical",NULL ) -, SchemaEntry("ifcjunctionboxtypeenum",NULL ) -, SchemaEntry("ifcaddresstypeenum",NULL ) -, SchemaEntry("ifcwasteterminaltypeenum",NULL ) -, SchemaEntry("ifctrimmingselect",NULL ) -, SchemaEntry("ifclightemissionsourceenum",NULL ) -, SchemaEntry("ifcsoundscaleenum",NULL ) -, SchemaEntry("ifcluminousfluxmeasure",NULL ) -, SchemaEntry("ifcelectricresistancemeasure",NULL ) -, SchemaEntry("ifcintegercountratemeasure",NULL ) -, SchemaEntry("ifcphysicalorvirtualenum",NULL ) -, SchemaEntry("ifcmolecularweightmeasure",NULL ) -, SchemaEntry("ifcprofiletypeenum",NULL ) -, SchemaEntry("ifcboxalignment",NULL ) -, SchemaEntry("ifcglobalorlocalenum",NULL ) -, SchemaEntry("ifcspecularroughness",NULL ) -, SchemaEntry("ifclamptypeenum",NULL ) -, SchemaEntry("ifcpiletypeenum",NULL ) -, SchemaEntry("ifcelectriccurrentmeasure",NULL ) -, SchemaEntry("ifcfantypeenum",NULL ) -, SchemaEntry("ifcsurfaceorfacesurface",NULL ) -, SchemaEntry("ifcpipefittingtypeenum",NULL ) -, SchemaEntry("ifctanktypeenum",NULL ) -, SchemaEntry("ifccurvefontorscaledcurvefontselect",NULL ) -, SchemaEntry("ifcwindowstyleconstructionenum",NULL ) -, SchemaEntry("ifcairterminalboxtypeenum",NULL ) -, SchemaEntry("ifcstairflighttypeenum",NULL ) -, SchemaEntry("ifcluminousintensitymeasure",NULL ) -, SchemaEntry("ifcmotorconnectiontypeenum",NULL ) -, SchemaEntry("ifcplaneanglemeasure",NULL ) -, SchemaEntry("ifcactuatortypeenum",NULL ) -, SchemaEntry("ifccolumntypeenum",NULL ) -, SchemaEntry("ifctextfontselect",NULL ) -, SchemaEntry("ifcdoorpanelpositionenum",NULL ) -, SchemaEntry("ifccoiltypeenum",NULL ) -, SchemaEntry("ifcangularvelocitymeasure",NULL ) -, SchemaEntry("ifcanalysismodeltypeenum",NULL ) -, SchemaEntry("ifclibraryselect",NULL ) -, SchemaEntry("ifcforcemeasure",NULL ) -, SchemaEntry("ifcfillareastyletileshapeselect",NULL ) -, SchemaEntry("ifcelectricappliancetypeenum",NULL ) -, SchemaEntry("ifcsurfacetextureenum",NULL ) -, SchemaEntry("ifccharacterstyleselect",NULL ) -, SchemaEntry("ifcenergymeasure",NULL ) -, SchemaEntry("ifcreal",NULL ) -, SchemaEntry("ifccompressortypeenum",NULL ) -, SchemaEntry("ifcelectricdistributionpointfunctionenum",NULL ) + SchemaEntry("ifcstairtypeenum",nullptr ) +, SchemaEntry("ifcspacetypeenum",nullptr ) +, SchemaEntry("ifcwalltypeenum",nullptr ) +, SchemaEntry("ifcmonthinyearnumber",nullptr ) +, SchemaEntry("ifcheatfluxdensitymeasure",nullptr ) +, SchemaEntry("ifckinematicviscositymeasure",nullptr ) +, SchemaEntry("ifcsequenceenum",nullptr ) +, SchemaEntry("ifcairtoairheatrecoverytypeenum",nullptr ) +, SchemaEntry("ifcactorselect",nullptr ) +, SchemaEntry("ifctransformertypeenum",nullptr ) +, SchemaEntry("ifcunitaryequipmenttypeenum",nullptr ) +, SchemaEntry("ifcelectricflowstoragedevicetypeenum",nullptr ) +, SchemaEntry("ifcenergysequenceenum",nullptr ) +, SchemaEntry("ifcworkcontroltypeenum",nullptr ) +, SchemaEntry("ifccurvaturemeasure",nullptr ) +, SchemaEntry("ifcparametervalue",nullptr ) +, SchemaEntry("ifcappliedvalueselect",nullptr ) +, SchemaEntry("ifcwarpingconstantmeasure",nullptr ) +, SchemaEntry("ifcarithmeticoperatorenum",nullptr ) +, SchemaEntry("ifclinearforcemeasure",nullptr ) +, SchemaEntry("ifcwindowpanelpositionenum",nullptr ) +, SchemaEntry("ifcflowmetertypeenum",nullptr ) +, SchemaEntry("ifcrampflighttypeenum",nullptr ) +, SchemaEntry("ifcspecularhighlightselect",nullptr ) +, SchemaEntry("ifcactiontypeenum",nullptr ) +, SchemaEntry("ifcgeometricprojectionenum",nullptr ) +, SchemaEntry("ifctimeseriesdatatypeenum",nullptr ) +, SchemaEntry("ifcmagneticfluxmeasure",nullptr ) +, SchemaEntry("ifcobjecttypeenum",nullptr ) +, SchemaEntry("ifcdataoriginenum",nullptr ) +, SchemaEntry("ifcmassdensitymeasure",nullptr ) +, SchemaEntry("ifclightfixturetypeenum",nullptr ) +, SchemaEntry("ifcservicelifetypeenum",nullptr ) +, SchemaEntry("ifcelectricvoltagemeasure",nullptr ) +, SchemaEntry("ifcheatingvaluemeasure",nullptr ) +, SchemaEntry("ifcpresentabletext",nullptr ) +, SchemaEntry("ifcaheadorbehind",nullptr ) +, SchemaEntry("ifcsimplevalue",nullptr ) +, SchemaEntry("ifcsensortypeenum",nullptr ) +, SchemaEntry("ifcderivedunitenum",nullptr ) +, SchemaEntry("ifcsizeselect",nullptr ) +, SchemaEntry("ifctransportelementtypeenum",nullptr ) +, SchemaEntry("ifcinventorytypeenum",nullptr ) +, SchemaEntry("ifctextdecoration",nullptr ) +, SchemaEntry("ifcdirectionsenseenum",nullptr ) +, SchemaEntry("ifcductfittingtypeenum",nullptr ) +, SchemaEntry("ifcdocumentstatusenum",nullptr ) +, SchemaEntry("ifcslabtypeenum",nullptr ) +, SchemaEntry("ifcdoorstyleconstructionenum",nullptr ) +, SchemaEntry("ifcvolumemeasure",nullptr ) +, SchemaEntry("ifcinductancemeasure",nullptr ) +, SchemaEntry("ifccurtainwalltypeenum",nullptr ) +, SchemaEntry("ifcsiunitname",nullptr ) +, SchemaEntry("ifcspecularexponent",nullptr ) +, SchemaEntry("ifcsoundpressuremeasure",nullptr ) +, SchemaEntry("ifcanalysistheorytypeenum",nullptr ) +, SchemaEntry("ifcgasterminaltypeenum",nullptr ) +, SchemaEntry("ifcyearnumber",nullptr ) +, SchemaEntry("ifcmodulusofelasticitymeasure",nullptr ) +, SchemaEntry("ifcchangeactionenum",nullptr ) +, SchemaEntry("ifcdampertypeenum",nullptr ) +, SchemaEntry("ifcevaporatortypeenum",nullptr ) +, SchemaEntry("ifcionconcentrationmeasure",nullptr ) +, SchemaEntry("ifcductsegmenttypeenum",nullptr ) +, SchemaEntry("ifcprotectivedevicetypeenum",nullptr ) +, SchemaEntry("ifcabsorbeddosemeasure",nullptr ) +, SchemaEntry("ifcmassperlengthmeasure",nullptr ) +, SchemaEntry("ifctextfontname",nullptr ) +, SchemaEntry("ifcorientationselect",nullptr ) +, SchemaEntry("ifcilluminancemeasure",nullptr ) +, SchemaEntry("ifcfiresuppressionterminaltypeenum",nullptr ) +, SchemaEntry("ifcfontstyle",nullptr ) +, SchemaEntry("ifcmomentofinertiameasure",nullptr ) +, SchemaEntry("ifcmodulusofsubgradereactionmeasure",nullptr ) +, SchemaEntry("ifccomplexnumber",nullptr ) +, SchemaEntry("ifchumidifiertypeenum",nullptr ) +, SchemaEntry("ifcpresentationstyleselect",nullptr ) +, SchemaEntry("ifcthermaltransmittancemeasure",nullptr ) +, SchemaEntry("ifcribplatedirectionenum",nullptr ) +, SchemaEntry("ifcclassificationnotationselect",nullptr ) +, SchemaEntry("ifcminuteinhour",nullptr ) +, SchemaEntry("ifcinternalorexternalenum",nullptr ) +, SchemaEntry("ifcrotationalfrequencymeasure",nullptr ) +, SchemaEntry("ifcsanitaryterminaltypeenum",nullptr ) +, SchemaEntry("ifcsymbolstyleselect",nullptr ) +, SchemaEntry("ifcelementcompositionenum",nullptr ) +, SchemaEntry("ifctextpath",nullptr ) +, SchemaEntry("ifcpowermeasure",nullptr ) +, SchemaEntry("ifcsurfacestyleelementselect",nullptr ) +, SchemaEntry("ifcresourceconsumptionenum",nullptr ) +, SchemaEntry("ifcelectriccapacitancemeasure",nullptr ) +, SchemaEntry("ifclayersetdirectionenum",nullptr ) +, SchemaEntry("ifcrailingtypeenum",nullptr ) +, SchemaEntry("ifcobjectiveenum",nullptr ) +, SchemaEntry("ifcdocumentselect",nullptr ) +, SchemaEntry("ifcmodulusoflinearsubgradereactionmeasure",nullptr ) +, SchemaEntry("ifcthermaladmittancemeasure",nullptr ) +, SchemaEntry("ifctransitioncode",nullptr ) +, SchemaEntry("ifcconnectiontypeenum",nullptr ) +, SchemaEntry("ifcmonetarymeasure",nullptr ) +, SchemaEntry("ifcstackterminaltypeenum",nullptr ) +, SchemaEntry("ifccolour",nullptr ) +, SchemaEntry("ifctext",nullptr ) +, SchemaEntry("ifccontextdependentmeasure",nullptr ) +, SchemaEntry("ifcthermalconductivitymeasure",nullptr ) +, SchemaEntry("ifcprojectedortruelengthenum",nullptr ) +, SchemaEntry("ifcpressuremeasure",nullptr ) +, SchemaEntry("ifcmoisturediffusivitymeasure",nullptr ) +, SchemaEntry("ifcbooleanoperator",nullptr ) +, SchemaEntry("ifcpropertysourceenum",nullptr ) +, SchemaEntry("ifctimestamp",nullptr ) +, SchemaEntry("ifcmaterialselect",nullptr ) +, SchemaEntry("ifcgloballyuniqueid",nullptr ) +, SchemaEntry("ifcreflectancemethodenum",nullptr ) +, SchemaEntry("ifcvaporpermeabilitymeasure",nullptr ) +, SchemaEntry("ifctimeseriesscheduletypeenum",nullptr ) +, SchemaEntry("ifclinearmomentmeasure",nullptr ) +, SchemaEntry("ifcgeometricsetselect",nullptr ) +, SchemaEntry("ifcsectionmodulusmeasure",nullptr ) +, SchemaEntry("ifcbsplinecurveform",nullptr ) +, SchemaEntry("ifcdimensionextentusage",nullptr ) +, SchemaEntry("ifcthermalexpansioncoefficientmeasure",nullptr ) +, SchemaEntry("ifchourinday",nullptr ) +, SchemaEntry("ifclinearvelocitymeasure",nullptr ) +, SchemaEntry("ifctorquemeasure",nullptr ) +, SchemaEntry("ifctemperaturegradientmeasure",nullptr ) +, SchemaEntry("ifcfillstyleselect",nullptr ) +, SchemaEntry("ifcelectricchargemeasure",nullptr ) +, SchemaEntry("ifcheatexchangertypeenum",nullptr ) +, SchemaEntry("ifcelectriccurrentenum",nullptr ) +, SchemaEntry("ifcdaylightsavinghour",nullptr ) +, SchemaEntry("ifcshell",nullptr ) +, SchemaEntry("ifcdoseequivalentmeasure",nullptr ) +, SchemaEntry("ifcprojectordertypeenum",nullptr ) +, SchemaEntry("ifcderivedmeasurevalue",nullptr ) +, SchemaEntry("ifclightdistributioncurveenum",nullptr ) +, SchemaEntry("ifcwarpingmomentmeasure",nullptr ) +, SchemaEntry("ifcmembertypeenum",nullptr ) +, SchemaEntry("ifcsoundpowermeasure",nullptr ) +, SchemaEntry("ifctextalignment",nullptr ) +, SchemaEntry("ifccurveoredgecurve",nullptr ) +, SchemaEntry("ifcmassflowratemeasure",nullptr ) +, SchemaEntry("ifcisothermalmoisturecapacitymeasure",nullptr ) +, SchemaEntry("ifccsgselect",nullptr ) +, SchemaEntry("ifccoolingtowertypeenum",nullptr ) +, SchemaEntry("ifcmassmeasure",nullptr ) +, SchemaEntry("ifcpileconstructionenum",nullptr ) +, SchemaEntry("ifcdoorstyleoperationenum",nullptr ) +, SchemaEntry("ifcflowdirectionenum",nullptr ) +, SchemaEntry("ifcthermalloadsourceenum",nullptr ) +, SchemaEntry("ifclengthmeasure",nullptr ) +, SchemaEntry("ifcconstraintenum",nullptr ) +, SchemaEntry("ifcaxis2placement",nullptr ) +, SchemaEntry("ifcloadgrouptypeenum",nullptr ) +, SchemaEntry("ifcvalue",nullptr ) +, SchemaEntry("ifcreinforcingbarsurfaceenum",nullptr ) +, SchemaEntry("ifcprojectorderrecordtypeenum",nullptr ) +, SchemaEntry("ifcdatetimeselect",nullptr ) +, SchemaEntry("ifcstructuralsurfacetypeenum",nullptr ) +, SchemaEntry("ifcpermeablecoveringoperationenum",nullptr ) +, SchemaEntry("ifcfontweight",nullptr ) +, SchemaEntry("ifcphmeasure",nullptr ) +, SchemaEntry("ifcdescriptivemeasure",nullptr ) +, SchemaEntry("ifccurvestylefontselect",nullptr ) +, SchemaEntry("ifcunit",nullptr ) +, SchemaEntry("ifchatchlinedistanceselect",nullptr ) +, SchemaEntry("ifctextstyleselect",nullptr ) +, SchemaEntry("ifcmetricvalueselect",nullptr ) +, SchemaEntry("ifcvectorordirection",nullptr ) +, SchemaEntry("ifcassemblyplaceenum",nullptr ) +, SchemaEntry("ifcairterminaltypeenum",nullptr ) +, SchemaEntry("ifccoveringtypeenum",nullptr ) +, SchemaEntry("ifcplanarforcemeasure",nullptr ) +, SchemaEntry("ifcvalvetypeenum",nullptr ) +, SchemaEntry("ifcalarmtypeenum",nullptr ) +, SchemaEntry("ifcdynamicviscositymeasure",nullptr ) +, SchemaEntry("ifccurrencyenum",nullptr ) +, SchemaEntry("ifcmodulusofrotationalsubgradereactionmeasure",nullptr ) +, SchemaEntry("ifccablecarrierfittingtypeenum",nullptr ) +, SchemaEntry("ifcboolean",nullptr ) +, SchemaEntry("ifcactionsourcetypeenum",nullptr ) +, SchemaEntry("ifcstructuralactivityassignmentselect",nullptr ) +, SchemaEntry("ifcdistributionchamberelementtypeenum",nullptr ) +, SchemaEntry("ifcevaporativecoolertypeenum",nullptr ) +, SchemaEntry("ifcmagneticfluxdensitymeasure",nullptr ) +, SchemaEntry("ifclightdistributiondatasourceselect",nullptr ) +, SchemaEntry("ifctubebundletypeenum",nullptr ) +, SchemaEntry("ifcaccelerationmeasure",nullptr ) +, SchemaEntry("ifcboilertypeenum",nullptr ) +, SchemaEntry("ifcramptypeenum",nullptr ) +, SchemaEntry("ifcluminousintensitydistributionmeasure",nullptr ) +, SchemaEntry("ifctrimmingpreference",nullptr ) +, SchemaEntry("ifcspecificheatcapacitymeasure",nullptr ) +, SchemaEntry("ifcamountofsubstancemeasure",nullptr ) +, SchemaEntry("ifcroleenum",nullptr ) +, SchemaEntry("ifcdocumentconfidentialityenum",nullptr ) +, SchemaEntry("ifcfrequencymeasure",nullptr ) +, SchemaEntry("ifcsectiontypeenum",nullptr ) +, SchemaEntry("ifcelementassemblytypeenum",nullptr ) +, SchemaEntry("ifcfootingtypeenum",nullptr ) +, SchemaEntry("ifclayereditem",nullptr ) +, SchemaEntry("ifccablesegmenttypeenum",nullptr ) +, SchemaEntry("ifcdefinedsymbolselect",nullptr ) +, SchemaEntry("ifcbuildingelementproxytypeenum",nullptr ) +, SchemaEntry("ifcelectricgeneratortypeenum",nullptr ) +, SchemaEntry("ifcrotationalstiffnessmeasure",nullptr ) +, SchemaEntry("ifcspaceheatertypeenum",nullptr ) +, SchemaEntry("ifcareameasure",nullptr ) +, SchemaEntry("ifclabel",nullptr ) +, SchemaEntry("ifccostscheduletypeenum",nullptr ) +, SchemaEntry("ifcswitchingdevicetypeenum",nullptr ) +, SchemaEntry("ifcelectrictimecontroltypeenum",nullptr ) +, SchemaEntry("ifcfiltertypeenum",nullptr ) +, SchemaEntry("ifcpositivelengthmeasure",nullptr ) +, SchemaEntry("ifcnullstyle",nullptr ) +, SchemaEntry("ifcconditioncriterionselect",nullptr ) +, SchemaEntry("ifcshearmodulusmeasure",nullptr ) +, SchemaEntry("ifcnormalisedratiomeasure",nullptr ) +, SchemaEntry("ifcdoorpaneloperationenum",nullptr ) +, SchemaEntry("ifcpointorvertexpoint",nullptr ) +, SchemaEntry("ifcrooftypeenum",nullptr ) +, SchemaEntry("ifccountmeasure",nullptr ) +, SchemaEntry("ifcelectricconductancemeasure",nullptr ) +, SchemaEntry("ifcproceduretypeenum",nullptr ) +, SchemaEntry("ifcflowinstrumenttypeenum",nullptr ) +, SchemaEntry("ifcelectricmotortypeenum",nullptr ) +, SchemaEntry("ifcsurfaceside",nullptr ) +, SchemaEntry("ifcstructuralcurvetypeenum",nullptr ) +, SchemaEntry("ifccondensertypeenum",nullptr ) +, SchemaEntry("ifclinearstiffnessmeasure",nullptr ) +, SchemaEntry("ifcunitenum",nullptr ) +, SchemaEntry("ifcoccupanttypeenum",nullptr ) +, SchemaEntry("ifcthermalloadtypeenum",nullptr ) +, SchemaEntry("ifcreinforcingbarroleenum",nullptr ) +, SchemaEntry("ifcbenchmarkenum",nullptr ) +, SchemaEntry("ifcpositiveplaneanglemeasure",nullptr ) +, SchemaEntry("ifctexttransformation",nullptr ) +, SchemaEntry("ifcdraughtingcalloutelement",nullptr ) +, SchemaEntry("ifcratiomeasure",nullptr ) +, SchemaEntry("ifcsolidanglemeasure",nullptr ) +, SchemaEntry("ifcpipesegmenttypeenum",nullptr ) +, SchemaEntry("ifccablecarriersegmenttypeenum",nullptr ) +, SchemaEntry("ifccolourorfactor",nullptr ) +, SchemaEntry("ifcidentifier",nullptr ) +, SchemaEntry("ifctendontypeenum",nullptr ) +, SchemaEntry("ifccontrollertypeenum",nullptr ) +, SchemaEntry("ifcradioactivitymeasure",nullptr ) +, SchemaEntry("ifctimemeasure",nullptr ) +, SchemaEntry("ifcpumptypeenum",nullptr ) +, SchemaEntry("ifcelectricheatertypeenum",nullptr ) +, SchemaEntry("ifcbeamtypeenum",nullptr ) +, SchemaEntry("ifcstateenum",nullptr ) +, SchemaEntry("ifcsiprefix",nullptr ) +, SchemaEntry("ifcnumericmeasure",nullptr ) +, SchemaEntry("ifcoutlettypeenum",nullptr ) +, SchemaEntry("ifccompoundplaneanglemeasure",nullptr ) +, SchemaEntry("ifcservicelifefactortypeenum",nullptr ) +, SchemaEntry("ifclogicaloperatorenum",nullptr ) +, SchemaEntry("ifcbooleanoperand",nullptr ) +, SchemaEntry("ifcobjectreferenceselect",nullptr ) +, SchemaEntry("ifccooledbeamtypeenum",nullptr ) +, SchemaEntry("ifcductsilencertypeenum",nullptr ) +, SchemaEntry("ifcsectionalareaintegralmeasure",nullptr ) +, SchemaEntry("ifcfontvariant",nullptr ) +, SchemaEntry("ifcvolumetricflowratemeasure",nullptr ) +, SchemaEntry("ifcplatetypeenum",nullptr ) +, SchemaEntry("ifcenvironmentalimpactcategoryenum",nullptr ) +, SchemaEntry("ifcvibrationisolatortypeenum",nullptr ) +, SchemaEntry("ifcthermodynamictemperaturemeasure",nullptr ) +, SchemaEntry("ifcrotationalmassmeasure",nullptr ) +, SchemaEntry("ifcsecondinminute",nullptr ) +, SchemaEntry("ifcdayinmonthnumber",nullptr ) +, SchemaEntry("ifcdimensioncount",nullptr ) +, SchemaEntry("ifcwindowstyleoperationenum",nullptr ) +, SchemaEntry("ifcthermalresistancemeasure",nullptr ) +, SchemaEntry("ifcmeasurevalue",nullptr ) +, SchemaEntry("ifcwindowpaneloperationenum",nullptr ) +, SchemaEntry("ifcchillertypeenum",nullptr ) +, SchemaEntry("ifcpositiveratiomeasure",nullptr ) +, SchemaEntry("ifcinteger",nullptr ) +, SchemaEntry("ifclogical",nullptr ) +, SchemaEntry("ifcjunctionboxtypeenum",nullptr ) +, SchemaEntry("ifcaddresstypeenum",nullptr ) +, SchemaEntry("ifcwasteterminaltypeenum",nullptr ) +, SchemaEntry("ifctrimmingselect",nullptr ) +, SchemaEntry("ifclightemissionsourceenum",nullptr ) +, SchemaEntry("ifcsoundscaleenum",nullptr ) +, SchemaEntry("ifcluminousfluxmeasure",nullptr ) +, SchemaEntry("ifcelectricresistancemeasure",nullptr ) +, SchemaEntry("ifcintegercountratemeasure",nullptr ) +, SchemaEntry("ifcphysicalorvirtualenum",nullptr ) +, SchemaEntry("ifcmolecularweightmeasure",nullptr ) +, SchemaEntry("ifcprofiletypeenum",nullptr ) +, SchemaEntry("ifcboxalignment",nullptr ) +, SchemaEntry("ifcglobalorlocalenum",nullptr ) +, SchemaEntry("ifcspecularroughness",nullptr ) +, SchemaEntry("ifclamptypeenum",nullptr ) +, SchemaEntry("ifcpiletypeenum",nullptr ) +, SchemaEntry("ifcelectriccurrentmeasure",nullptr ) +, SchemaEntry("ifcfantypeenum",nullptr ) +, SchemaEntry("ifcsurfaceorfacesurface",nullptr ) +, SchemaEntry("ifcpipefittingtypeenum",nullptr ) +, SchemaEntry("ifctanktypeenum",nullptr ) +, SchemaEntry("ifccurvefontorscaledcurvefontselect",nullptr ) +, SchemaEntry("ifcwindowstyleconstructionenum",nullptr ) +, SchemaEntry("ifcairterminalboxtypeenum",nullptr ) +, SchemaEntry("ifcstairflighttypeenum",nullptr ) +, SchemaEntry("ifcluminousintensitymeasure",nullptr ) +, SchemaEntry("ifcmotorconnectiontypeenum",nullptr ) +, SchemaEntry("ifcplaneanglemeasure",nullptr ) +, SchemaEntry("ifcactuatortypeenum",nullptr ) +, SchemaEntry("ifccolumntypeenum",nullptr ) +, SchemaEntry("ifctextfontselect",nullptr ) +, SchemaEntry("ifcdoorpanelpositionenum",nullptr ) +, SchemaEntry("ifccoiltypeenum",nullptr ) +, SchemaEntry("ifcangularvelocitymeasure",nullptr ) +, SchemaEntry("ifcanalysismodeltypeenum",nullptr ) +, SchemaEntry("ifclibraryselect",nullptr ) +, SchemaEntry("ifcforcemeasure",nullptr ) +, SchemaEntry("ifcfillareastyletileshapeselect",nullptr ) +, SchemaEntry("ifcelectricappliancetypeenum",nullptr ) +, SchemaEntry("ifcsurfacetextureenum",nullptr ) +, SchemaEntry("ifccharacterstyleselect",nullptr ) +, SchemaEntry("ifcenergymeasure",nullptr ) +, SchemaEntry("ifcreal",nullptr ) +, SchemaEntry("ifccompressortypeenum",nullptr ) +, SchemaEntry("ifcelectricdistributionpointfunctionenum",nullptr ) , SchemaEntry("ifcroot",&STEP::ObjectHelper::Construct ) , SchemaEntry("ifcobjectdefinition",&STEP::ObjectHelper::Construct ) , SchemaEntry("ifctypeobject",&STEP::ObjectHelper::Construct ) diff --git a/code/AssetLib/IFC/IFCUtil.cpp b/code/AssetLib/IFC/IFCUtil.cpp index e7c04bd89..e1a733828 100644 --- a/code/AssetLib/IFC/IFCUtil.cpp +++ b/code/AssetLib/IFC/IFCUtil.cpp @@ -71,7 +71,7 @@ aiMesh* TempMesh::ToMesh() ai_assert(mVerts.size() == std::accumulate(mVertcnt.begin(),mVertcnt.end(),size_t(0))); if (mVerts.empty()) { - return NULL; + return nullptr; } std::unique_ptr mesh(new aiMesh()); diff --git a/code/AssetLib/IFC/IFCUtil.h b/code/AssetLib/IFC/IFCUtil.h index b9aad4440..2b7fba3b2 100644 --- a/code/AssetLib/IFC/IFCUtil.h +++ b/code/AssetLib/IFC/IFCUtil.h @@ -201,7 +201,7 @@ struct ConversionData struct MeshCacheIndex { const IFC::Schema_2x3::IfcRepresentationItem* item; unsigned int matindex; - MeshCacheIndex() : item(NULL), matindex(0) { } + MeshCacheIndex() : item(nullptr), matindex(0) { } MeshCacheIndex(const IFC::Schema_2x3::IfcRepresentationItem* i, unsigned int mi) : item(i), matindex(mi) { } bool operator == (const MeshCacheIndex& o) const { return item == o.item && matindex == o.matindex; } bool operator < (const MeshCacheIndex& o) const { return item < o.item || (item == o.item && matindex < o.matindex); } diff --git a/code/AssetLib/Irr/IRRLoader.cpp b/code/AssetLib/Irr/IRRLoader.cpp index c22a818bc..19efb732b 100644 --- a/code/AssetLib/Irr/IRRLoader.cpp +++ b/code/AssetLib/Irr/IRRLoader.cpp @@ -82,8 +82,13 @@ static const aiImporterDesc desc = { // ------------------------------------------------------------------------------------------------ // Constructor to be privately used by Importer IRRImporter::IRRImporter() : +<<<<<<< HEAD fps(), configSpeedFlag() { // empty +======= + fps(), configSpeedFlag() { + // empty +>>>>>>> master } // ------------------------------------------------------------------------------------------------ @@ -95,6 +100,7 @@ IRRImporter::~IRRImporter() { // ------------------------------------------------------------------------------------------------ // Returns whether the class can handle the format of the given file. bool IRRImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const { +<<<<<<< HEAD const std::string extension = GetExtension(pFile); if (extension == "irr") { return true; @@ -111,15 +117,38 @@ bool IRRImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool c } return false; +======= + const std::string extension = GetExtension(pFile); + if (extension == "irr") { + return true; + } else if (extension == "xml" || checkSig) { + /* If CanRead() is called in order to check whether we + * support a specific file extension in general pIOHandler + * might be nullptr and it's our duty to return true here. + */ + if (nullptr == pIOHandler) { + return true; + } + const char *tokens[] = { "irr_scene" }; + return SearchFileHeaderForToken(pIOHandler, pFile, tokens, 1); + } + + return false; +>>>>>>> master } // ------------------------------------------------------------------------------------------------ const aiImporterDesc *IRRImporter::GetInfo() const { +<<<<<<< HEAD return &desc; +======= + return &desc; +>>>>>>> master } // ------------------------------------------------------------------------------------------------ void IRRImporter::SetupProperties(const Importer *pImp) { +<<<<<<< HEAD // read the output frame rate of all node animation channels fps = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_IRR_ANIM_FPS, 100); if (fps < 10.) { @@ -129,11 +158,23 @@ void IRRImporter::SetupProperties(const Importer *pImp) { // AI_CONFIG_FAVOUR_SPEED configSpeedFlag = (0 != pImp->GetPropertyInteger(AI_CONFIG_FAVOUR_SPEED, 0)); +======= + // read the output frame rate of all node animation channels + fps = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_IRR_ANIM_FPS, 100); + if (fps < 10.) { + ASSIMP_LOG_ERROR("IRR: Invalid FPS configuration"); + fps = 100; + } + + // AI_CONFIG_FAVOUR_SPEED + configSpeedFlag = (0 != pImp->GetPropertyInteger(AI_CONFIG_FAVOUR_SPEED, 0)); +>>>>>>> master } // ------------------------------------------------------------------------------------------------ // Build a mesh tha consists of a single squad (a side of a skybox) aiMesh *IRRImporter::BuildSingleQuadMesh(const SkyboxVertex &v1, +<<<<<<< HEAD const SkyboxVertex &v2, const SkyboxVertex &v3, const SkyboxVertex &v4) { @@ -175,10 +216,54 @@ aiMesh *IRRImporter::BuildSingleQuadMesh(const SkyboxVertex &v1, *vec++ = v3.uv; *vec = v4.uv; return out; +======= + const SkyboxVertex &v2, + const SkyboxVertex &v3, + const SkyboxVertex &v4) { + // allocate and prepare the mesh + aiMesh *out = new aiMesh(); + + out->mPrimitiveTypes = aiPrimitiveType_POLYGON; + out->mNumFaces = 1; + + // build the face + out->mFaces = new aiFace[1]; + aiFace &face = out->mFaces[0]; + + face.mNumIndices = 4; + face.mIndices = new unsigned int[4]; + for (unsigned int i = 0; i < 4; ++i) + face.mIndices[i] = i; + + out->mNumVertices = 4; + + // copy vertex positions + aiVector3D *vec = out->mVertices = new aiVector3D[4]; + *vec++ = v1.position; + *vec++ = v2.position; + *vec++ = v3.position; + *vec = v4.position; + + // copy vertex normals + vec = out->mNormals = new aiVector3D[4]; + *vec++ = v1.normal; + *vec++ = v2.normal; + *vec++ = v3.normal; + *vec = v4.normal; + + // copy texture coordinates + vec = out->mTextureCoords[0] = new aiVector3D[4]; + *vec++ = v1.uv; + *vec++ = v2.uv; + *vec++ = v3.uv; + *vec = v4.uv; + return out; +>>>>>>> master } // ------------------------------------------------------------------------------------------------ void IRRImporter::BuildSkybox(std::vector &meshes, std::vector materials) { +<<<<<<< HEAD // Update the material of the skybox - replace the name and disable shading for skyboxes. for (unsigned int i = 0; i < 6; ++i) { aiMaterial *out = (aiMaterial *)(*(materials.end() - (6 - i))); @@ -244,10 +329,78 @@ void IRRImporter::BuildSkybox(std::vector &meshes, std::vectormMaterialIndex = static_cast(materials.size() - 1u); +======= + // Update the material of the skybox - replace the name and disable shading for skyboxes. + for (unsigned int i = 0; i < 6; ++i) { + aiMaterial *out = (aiMaterial *)(*(materials.end() - (6 - i))); + + aiString s; + s.length = ::ai_snprintf(s.data, MAXLEN, "SkyboxSide_%u", i); + out->AddProperty(&s, AI_MATKEY_NAME); + + int shading = aiShadingMode_NoShading; + out->AddProperty(&shading, 1, AI_MATKEY_SHADING_MODEL); + } + + // Skyboxes are much more difficult. They are represented + // by six single planes with different textures, so we'll + // need to build six meshes. + + const ai_real l = 10.0; // the size used by Irrlicht + + // FRONT SIDE + meshes.push_back(BuildSingleQuadMesh( + SkyboxVertex(-l, -l, -l, 0, 0, 1, 1.0, 1.0), + SkyboxVertex(l, -l, -l, 0, 0, 1, 0.0, 1.0), + SkyboxVertex(l, l, -l, 0, 0, 1, 0.0, 0.0), + SkyboxVertex(-l, l, -l, 0, 0, 1, 1.0, 0.0))); + meshes.back()->mMaterialIndex = static_cast(materials.size() - 6u); + + // LEFT SIDE + meshes.push_back(BuildSingleQuadMesh( + SkyboxVertex(l, -l, -l, -1, 0, 0, 1.0, 1.0), + SkyboxVertex(l, -l, l, -1, 0, 0, 0.0, 1.0), + SkyboxVertex(l, l, l, -1, 0, 0, 0.0, 0.0), + SkyboxVertex(l, l, -l, -1, 0, 0, 1.0, 0.0))); + meshes.back()->mMaterialIndex = static_cast(materials.size() - 5u); + + // BACK SIDE + meshes.push_back(BuildSingleQuadMesh( + SkyboxVertex(l, -l, l, 0, 0, -1, 1.0, 1.0), + SkyboxVertex(-l, -l, l, 0, 0, -1, 0.0, 1.0), + SkyboxVertex(-l, l, l, 0, 0, -1, 0.0, 0.0), + SkyboxVertex(l, l, l, 0, 0, -1, 1.0, 0.0))); + meshes.back()->mMaterialIndex = static_cast(materials.size() - 4u); + + // RIGHT SIDE + meshes.push_back(BuildSingleQuadMesh( + SkyboxVertex(-l, -l, l, 1, 0, 0, 1.0, 1.0), + SkyboxVertex(-l, -l, -l, 1, 0, 0, 0.0, 1.0), + SkyboxVertex(-l, l, -l, 1, 0, 0, 0.0, 0.0), + SkyboxVertex(-l, l, l, 1, 0, 0, 1.0, 0.0))); + meshes.back()->mMaterialIndex = static_cast(materials.size() - 3u); + + // TOP SIDE + meshes.push_back(BuildSingleQuadMesh( + SkyboxVertex(l, l, -l, 0, -1, 0, 1.0, 1.0), + SkyboxVertex(l, l, l, 0, -1, 0, 0.0, 1.0), + SkyboxVertex(-l, l, l, 0, -1, 0, 0.0, 0.0), + SkyboxVertex(-l, l, -l, 0, -1, 0, 1.0, 0.0))); + meshes.back()->mMaterialIndex = static_cast(materials.size() - 2u); + + // BOTTOM SIDE + meshes.push_back(BuildSingleQuadMesh( + SkyboxVertex(l, -l, l, 0, 1, 0, 0.0, 0.0), + SkyboxVertex(l, -l, -l, 0, 1, 0, 1.0, 0.0), + SkyboxVertex(-l, -l, -l, 0, 1, 0, 1.0, 1.0), + SkyboxVertex(-l, -l, l, 0, 1, 0, 0.0, 1.0))); + meshes.back()->mMaterialIndex = static_cast(materials.size() - 1u); +>>>>>>> master } // ------------------------------------------------------------------------------------------------ void IRRImporter::CopyMaterial(std::vector &materials, +<<<<<<< HEAD std::vector> &inmaterials, unsigned int &defMatIdx, aiMesh *mesh) { @@ -257,6 +410,17 @@ void IRRImporter::CopyMaterial(std::vector &materials, defMatIdx = (unsigned int)materials.size(); //TODO: add this materials to someone? /*aiMaterial* mat = new aiMaterial(); +======= + std::vector> &inmaterials, + unsigned int &defMatIdx, + aiMesh *mesh) { + if (inmaterials.empty()) { + // Do we have a default material? If not we need to create one + if (UINT_MAX == defMatIdx) { + defMatIdx = (unsigned int)materials.size(); + //TODO: add this materials to someone? + /*aiMaterial* mat = new aiMaterial(); +>>>>>>> master aiString s; s.Set(AI_DEFAULT_MATERIAL_NAME); @@ -264,6 +428,7 @@ void IRRImporter::CopyMaterial(std::vector &materials, aiColor3D c(0.6f,0.6f,0.6f); mat->AddProperty(&c,1,AI_MATKEY_COLOR_DIFFUSE);*/ +<<<<<<< HEAD } mesh->mMaterialIndex = defMatIdx; return; @@ -273,15 +438,31 @@ void IRRImporter::CopyMaterial(std::vector &materials, mesh->mMaterialIndex = (unsigned int)materials.size(); materials.push_back(inmaterials[0].first); +======= + } + mesh->mMaterialIndex = defMatIdx; + return; + } else if (inmaterials.size() > 1) { + ASSIMP_LOG_INFO("IRR: Skipping additional materials"); + } + + mesh->mMaterialIndex = (unsigned int)materials.size(); + materials.push_back(inmaterials[0].first); +>>>>>>> master } // ------------------------------------------------------------------------------------------------ inline int ClampSpline(int idx, int size) { +<<<<<<< HEAD return (idx < 0 ? size + idx : (idx >= size ? idx - size : idx)); +======= + return (idx < 0 ? size + idx : (idx >= size ? idx - size : idx)); +>>>>>>> master } // ------------------------------------------------------------------------------------------------ inline void FindSuitableMultiple(int &angle) { +<<<<<<< HEAD if (angle < 3) angle = 3; else if (angle < 10) @@ -290,10 +471,21 @@ inline void FindSuitableMultiple(int &angle) { angle = 20; else if (angle < 30) angle = 30; +======= + if (angle < 3) + angle = 3; + else if (angle < 10) + angle = 10; + else if (angle < 20) + angle = 20; + else if (angle < 30) + angle = 30; +>>>>>>> master } // ------------------------------------------------------------------------------------------------ void IRRImporter::ComputeAnimations(Node *root, aiNode *real, std::vector &anims) { +<<<<<<< HEAD ai_assert(nullptr != root && nullptr != real); // XXX totally WIP - doesn't produce proper results, need to evaluate @@ -395,6 +587,110 @@ void IRRImporter::ComputeAnimations(Node *root, aiNode *real, std::vectoranimators.empty()) { + return; + } + unsigned int total(0); + for (std::list::iterator it = root->animators.begin(); it != root->animators.end(); ++it) { + if ((*it).type == Animator::UNKNOWN || (*it).type == Animator::OTHER) { + ASSIMP_LOG_WARN("IRR: Skipping unknown or unsupported animator"); + continue; + } + ++total; + } + if (!total) { + return; + } else if (1 == total) { + ASSIMP_LOG_WARN("IRR: Adding dummy nodes to simulate multiple animators"); + } + + // NOTE: 1 tick == i millisecond + + unsigned int cur = 0; + for (std::list::iterator it = root->animators.begin(); + it != root->animators.end(); ++it) { + if ((*it).type == Animator::UNKNOWN || (*it).type == Animator::OTHER) continue; + + Animator &in = *it; + aiNodeAnim *anim = new aiNodeAnim(); + + if (cur != total - 1) { + // Build a new name - a prefix instead of a suffix because it is + // easier to check against + anim->mNodeName.length = ::ai_snprintf(anim->mNodeName.data, MAXLEN, + "$INST_DUMMY_%i_%s", total - 1, + (root->name.length() ? root->name.c_str() : "")); + + // we'll also need to insert a dummy in the node hierarchy. + aiNode *dummy = new aiNode(); + + for (unsigned int i = 0; i < real->mParent->mNumChildren; ++i) + if (real->mParent->mChildren[i] == real) + real->mParent->mChildren[i] = dummy; + + dummy->mParent = real->mParent; + dummy->mName = anim->mNodeName; + + dummy->mNumChildren = 1; + dummy->mChildren = new aiNode *[dummy->mNumChildren]; + dummy->mChildren[0] = real; + + // the transformation matrix of the dummy node is the identity + + real->mParent = dummy; + } else + anim->mNodeName.Set(root->name); + ++cur; + + switch (in.type) { + case Animator::ROTATION: { + // ----------------------------------------------------- + // find out how long a full rotation will take + // This is the least common multiple of 360.f and all + // three euler angles. Although we'll surely find a + // possible multiple (haha) it could be somewhat large + // for our purposes. So we need to modify the angles + // here in order to get good results. + // ----------------------------------------------------- + int angles[3]; + angles[0] = (int)(in.direction.x * 100); + angles[1] = (int)(in.direction.y * 100); + angles[2] = (int)(in.direction.z * 100); + + angles[0] %= 360; + angles[1] %= 360; + angles[2] %= 360; + + if ((angles[0] * angles[1]) != 0 && (angles[1] * angles[2]) != 0) { + FindSuitableMultiple(angles[0]); + FindSuitableMultiple(angles[1]); + FindSuitableMultiple(angles[2]); + } + + int lcm = 360; + + if (angles[0]) + lcm = Math::lcm(lcm, angles[0]); + + if (angles[1]) + lcm = Math::lcm(lcm, angles[1]); + + if (angles[2]) + lcm = Math::lcm(lcm, angles[2]); + + if (360 == lcm) + break; +>>>>>>> master #if 0 // This can be a division through zero, but we don't care @@ -403,6 +699,7 @@ void IRRImporter::ComputeAnimations(Node *root, aiNode *real, std::vectormNumRotationKeys = (unsigned int)(max * fps); + anim->mRotationKeys = new aiQuatKey[anim->mNumRotationKeys]; + + // begin with a zero angle + aiVector3D angle; + for (unsigned int i = 0; i < anim->mNumRotationKeys; ++i) { + // build the quaternion for the given euler angles + aiQuatKey &q = anim->mRotationKeys[i]; + + q.mValue = aiQuaternion(angle.x, angle.y, angle.z); + q.mTime = (double)i; + + // increase the angle + angle += in.direction; + } + + // This animation is repeated and repeated ... + anim->mPostState = anim->mPreState = aiAnimBehaviour_REPEAT; + } break; + + case Animator::FLY_CIRCLE: { + // ----------------------------------------------------- + // Find out how much time we'll need to perform a + // full circle. + // ----------------------------------------------------- + const double seconds = (1. / in.speed) / 1000.; + const double tdelta = 1000. / fps; + + anim->mNumPositionKeys = (unsigned int)(fps * seconds); + anim->mPositionKeys = new aiVectorKey[anim->mNumPositionKeys]; + + // from Irrlicht, what else should we do than copying it? + aiVector3D vecU, vecV; + if (in.direction.y) { + vecV = aiVector3D(50, 0, 0) ^ in.direction; + } else + vecV = aiVector3D(0, 50, 00) ^ in.direction; + vecV.Normalize(); + vecU = (vecV ^ in.direction).Normalize(); + + // build the output keys + for (unsigned int i = 0; i < anim->mNumPositionKeys; ++i) { + aiVectorKey &key = anim->mPositionKeys[i]; + key.mTime = i * tdelta; + + const ai_real t = (ai_real)(in.speed * key.mTime); + key.mValue = in.circleCenter + in.circleRadius * ((vecU * std::cos(t)) + (vecV * std::sin(t))); + } + + // This animation is repeated and repeated ... + anim->mPostState = anim->mPreState = aiAnimBehaviour_REPEAT; + } break; + + case Animator::FLY_STRAIGHT: { + anim->mPostState = anim->mPreState = (in.loop ? aiAnimBehaviour_REPEAT : aiAnimBehaviour_CONSTANT); + const double seconds = in.timeForWay / 1000.; + const double tdelta = 1000. / fps; + + anim->mNumPositionKeys = (unsigned int)(fps * seconds); + anim->mPositionKeys = new aiVectorKey[anim->mNumPositionKeys]; + + aiVector3D diff = in.direction - in.circleCenter; + const ai_real lengthOfWay = diff.Length(); + diff.Normalize(); + + const double timeFactor = lengthOfWay / in.timeForWay; + + // build the output keys + for (unsigned int i = 0; i < anim->mNumPositionKeys; ++i) { + aiVectorKey &key = anim->mPositionKeys[i]; + key.mTime = i * tdelta; + key.mValue = in.circleCenter + diff * ai_real(timeFactor * key.mTime); + } + } break; + + case Animator::FOLLOW_SPLINE: { + // repeat outside the defined time range + anim->mPostState = anim->mPreState = aiAnimBehaviour_REPEAT; + const int size = (int)in.splineKeys.size(); + if (!size) { + // We have no point in the spline. That's bad. Really bad. + ASSIMP_LOG_WARN("IRR: Spline animators with no points defined"); + + delete anim; + anim = nullptr; + break; + } else if (size == 1) { + // We have just one point in the spline so we don't need the full calculation + anim->mNumPositionKeys = 1; + anim->mPositionKeys = new aiVectorKey[anim->mNumPositionKeys]; + + anim->mPositionKeys[0].mValue = in.splineKeys[0].mValue; + anim->mPositionKeys[0].mTime = 0.f; + break; + } + + unsigned int ticksPerFull = 15; + anim->mNumPositionKeys = (unsigned int)(ticksPerFull * fps); + anim->mPositionKeys = new aiVectorKey[anim->mNumPositionKeys]; + + for (unsigned int i = 0; i < anim->mNumPositionKeys; ++i) { + aiVectorKey &key = anim->mPositionKeys[i]; + + const ai_real dt = (i * in.speed * ai_real(0.001)); + const ai_real u = dt - std::floor(dt); + const int idx = (int)std::floor(dt) % size; + + // get the 4 current points to evaluate the spline + const aiVector3D &p0 = in.splineKeys[ClampSpline(idx - 1, size)].mValue; + const aiVector3D &p1 = in.splineKeys[ClampSpline(idx + 0, size)].mValue; + const aiVector3D &p2 = in.splineKeys[ClampSpline(idx + 1, size)].mValue; + const aiVector3D &p3 = in.splineKeys[ClampSpline(idx + 2, size)].mValue; + + // compute polynomials + const ai_real u2 = u * u; + const ai_real u3 = u2 * 2; + + const ai_real h1 = ai_real(2.0) * u3 - ai_real(3.0) * u2 + ai_real(1.0); + const ai_real h2 = ai_real(-2.0) * u3 + ai_real(3.0) * u3; + const ai_real h3 = u3 - ai_real(2.0) * u3; + const ai_real h4 = u3 - u2; + + // compute the spline tangents + const aiVector3D t1 = (p2 - p0) * in.tightness; + aiVector3D t2 = (p3 - p1) * in.tightness; + + // and use them to get the interpolated point + t2 = (h1 * p1 + p2 * h2 + t1 * h3 + h4 * t2); + + // build a simple translation matrix from it + key.mValue = t2; + key.mTime = (double)i; + } + } break; + default: + // UNKNOWN , OTHER + break; + }; + if (anim) { + anims.push_back(anim); + ++total; + } + } +>>>>>>> master } // ------------------------------------------------------------------------------------------------ // This function is maybe more generic than we'd need it here void SetupMapping(aiMaterial *mat, aiTextureMapping mode, const aiVector3D &axis = aiVector3D(0.f, 0.f, -1.f)) { +<<<<<<< HEAD if (nullptr == mat) { return; } @@ -620,10 +1074,67 @@ void SetupMapping(aiMaterial *mat, aiTextureMapping mode, const aiVector3D &axis } mat->mNumProperties = (unsigned int)p.size(); ::memcpy(mat->mProperties, &p[0], sizeof(void *) * mat->mNumProperties); +======= + // Check whether there are texture properties defined - setup + // the desired texture mapping mode for all of them and ignore + // all UV settings we might encounter. WE HAVE NO UVS! + + std::vector p; + p.reserve(mat->mNumProperties + 1); + + for (unsigned int i = 0; i < mat->mNumProperties; ++i) { + aiMaterialProperty *prop = mat->mProperties[i]; + if (!::strcmp(prop->mKey.data, "$tex.file")) { + // Setup the mapping key + aiMaterialProperty *m = new aiMaterialProperty(); + m->mKey.Set("$tex.mapping"); + m->mIndex = prop->mIndex; + m->mSemantic = prop->mSemantic; + m->mType = aiPTI_Integer; + + m->mDataLength = 4; + m->mData = new char[4]; + *((int *)m->mData) = mode; + + p.push_back(prop); + p.push_back(m); + + // Setup the mapping axis + if (mode == aiTextureMapping_CYLINDER || mode == aiTextureMapping_PLANE || mode == aiTextureMapping_SPHERE) { + m = new aiMaterialProperty(); + m->mKey.Set("$tex.mapaxis"); + m->mIndex = prop->mIndex; + m->mSemantic = prop->mSemantic; + m->mType = aiPTI_Float; + + m->mDataLength = 12; + m->mData = new char[12]; + *((aiVector3D *)m->mData) = axis; + p.push_back(m); + } + } else if (!::strcmp(prop->mKey.data, "$tex.uvwsrc")) { + delete mat->mProperties[i]; + } else + p.push_back(prop); + } + + if (p.empty()) return; + + // rebuild the output array + if (p.size() > mat->mNumAllocated) { + delete[] mat->mProperties; + mat->mProperties = new aiMaterialProperty *[p.size() * 2]; + + mat->mNumAllocated = static_cast(p.size() * 2); + } + mat->mNumProperties = (unsigned int)p.size(); + ::memcpy(mat->mProperties, &p[0], sizeof(void *) * mat->mNumProperties); +>>>>>>> master } // ------------------------------------------------------------------------------------------------ void IRRImporter::GenerateGraph(Node *root, aiNode *rootOut, aiScene *scene, +<<<<<<< HEAD BatchLoader &batch, std::vector &meshes, std::vector &anims, @@ -856,11 +1367,246 @@ void IRRImporter::GenerateGraph(Node *root, aiNode *rootOut, aiScene *scene, anims, attach, materials, defMatIdx); } } +======= + BatchLoader &batch, + std::vector &meshes, + std::vector &anims, + std::vector &attach, + std::vector &materials, + unsigned int &defMatIdx) { + unsigned int oldMeshSize = (unsigned int)meshes.size(); + //unsigned int meshTrafoAssign = 0; + + // Now determine the type of the node + switch (root->type) { + case Node::ANIMMESH: + case Node::MESH: { + if (!root->meshPath.length()) + break; + + // Get the loaded mesh from the scene and add it to + // the list of all scenes to be attached to the + // graph we're currently building + aiScene *localScene = batch.GetImport(root->id); + if (!localScene) { + ASSIMP_LOG_ERROR("IRR: Unable to load external file: " + root->meshPath); + break; + } + attach.push_back(AttachmentInfo(localScene, rootOut)); + + // Now combine the material we've loaded for this mesh + // with the real materials we got from the file. As we + // don't execute any pp-steps on the file, the numbers + // should be equal. If they are not, we can impossibly + // do this ... + if (root->materials.size() != (unsigned int)localScene->mNumMaterials) { + ASSIMP_LOG_WARN("IRR: Failed to match imported materials " + "with the materials found in the IRR scene file"); + + break; + } + for (unsigned int i = 0; i < localScene->mNumMaterials; ++i) { + // Delete the old material, we don't need it anymore + delete localScene->mMaterials[i]; + + std::pair &src = root->materials[i]; + localScene->mMaterials[i] = src.first; + } + + // NOTE: Each mesh should have exactly one material assigned, + // but we do it in a separate loop if this behaviour changes + // in future. + for (unsigned int i = 0; i < localScene->mNumMeshes; ++i) { + // Process material flags + aiMesh *mesh = localScene->mMeshes[i]; + + // If "trans_vertex_alpha" mode is enabled, search all vertex colors + // and check whether they have a common alpha value. This is quite + // often the case so we can simply extract it to a shared oacity + // value. + std::pair &src = root->materials[mesh->mMaterialIndex]; + aiMaterial *mat = (aiMaterial *)src.first; + + if (mesh->HasVertexColors(0) && src.second & AI_IRRMESH_MAT_trans_vertex_alpha) { + bool bdo = true; + for (unsigned int a = 1; a < mesh->mNumVertices; ++a) { + + if (mesh->mColors[0][a].a != mesh->mColors[0][a - 1].a) { + bdo = false; + break; + } + } + if (bdo) { + ASSIMP_LOG_INFO("IRR: Replacing mesh vertex alpha with common opacity"); + + for (unsigned int a = 0; a < mesh->mNumVertices; ++a) + mesh->mColors[0][a].a = 1.f; + + mat->AddProperty(&mesh->mColors[0][0].a, 1, AI_MATKEY_OPACITY); + } + } + + // If we have a second texture coordinate set and a second texture + // (either lightmap, normalmap, 2layered material) we need to + // setup the correct UV index for it. The texture can either + // be diffuse (lightmap & 2layer) or a normal map (normal & parallax) + if (mesh->HasTextureCoords(1)) { + + int idx = 1; + if (src.second & (AI_IRRMESH_MAT_solid_2layer | AI_IRRMESH_MAT_lightmap)) { + mat->AddProperty(&idx, 1, AI_MATKEY_UVWSRC_DIFFUSE(0)); + } else if (src.second & AI_IRRMESH_MAT_normalmap_solid) { + mat->AddProperty(&idx, 1, AI_MATKEY_UVWSRC_NORMALS(0)); + } + } + } + } break; + + case Node::LIGHT: + case Node::CAMERA: + + // We're already finished with lights and cameras + break; + + case Node::SPHERE: { + // Generate the sphere model. Our input parameter to + // the sphere generation algorithm is the number of + // subdivisions of each triangle - but here we have + // the number of poylgons on a specific axis. Just + // use some hardcoded limits to approximate this ... + unsigned int mul = root->spherePolyCountX * root->spherePolyCountY; + if (mul < 100) + mul = 2; + else if (mul < 300) + mul = 3; + else + mul = 4; + + meshes.push_back(StandardShapes::MakeMesh(mul, + &StandardShapes::MakeSphere)); + + // Adjust scaling + root->scaling *= root->sphereRadius / 2; + + // Copy one output material + CopyMaterial(materials, root->materials, defMatIdx, meshes.back()); + + // Now adjust this output material - if there is a first texture + // set, setup spherical UV mapping around the Y axis. + SetupMapping((aiMaterial *)materials.back(), aiTextureMapping_SPHERE); + } break; + + case Node::CUBE: { + // Generate an unit cube first + meshes.push_back(StandardShapes::MakeMesh( + &StandardShapes::MakeHexahedron)); + + // Adjust scaling + root->scaling *= root->sphereRadius; + + // Copy one output material + CopyMaterial(materials, root->materials, defMatIdx, meshes.back()); + + // Now adjust this output material - if there is a first texture + // set, setup cubic UV mapping + SetupMapping((aiMaterial *)materials.back(), aiTextureMapping_BOX); + } break; + + case Node::SKYBOX: { + // A skybox is defined by six materials + if (root->materials.size() < 6) { + ASSIMP_LOG_ERROR("IRR: There should be six materials for a skybox"); + break; + } + + // copy those materials and generate 6 meshes for our new skybox + materials.reserve(materials.size() + 6); + for (unsigned int i = 0; i < 6; ++i) + materials.insert(materials.end(), root->materials[i].first); + + BuildSkybox(meshes, materials); + + // ************************************************************* + // Skyboxes will require a different code path for rendering, + // so there must be a way for the user to add special support + // for IRR skyboxes. We add a 'IRR.SkyBox_' prefix to the node. + // ************************************************************* + root->name = "IRR.SkyBox_" + root->name; + ASSIMP_LOG_INFO("IRR: Loading skybox, this will " + "require special handling to be displayed correctly"); + } break; + + case Node::TERRAIN: { + // to support terrains, we'd need to have a texture decoder + ASSIMP_LOG_ERROR("IRR: Unsupported node - TERRAIN"); + } break; + default: + // DUMMY + break; + }; + + // Check whether we added a mesh (or more than one ...). In this case + // we'll also need to attach it to the node + if (oldMeshSize != (unsigned int)meshes.size()) { + + rootOut->mNumMeshes = (unsigned int)meshes.size() - oldMeshSize; + rootOut->mMeshes = new unsigned int[rootOut->mNumMeshes]; + + for (unsigned int a = 0; a < rootOut->mNumMeshes; ++a) { + rootOut->mMeshes[a] = oldMeshSize + a; + } + } + + // Setup the name of this node + rootOut->mName.Set(root->name); + + // Now compute the final local transformation matrix of the + // node from the given translation, rotation and scaling values. + // (the rotation is given in Euler angles, XYZ order) + //std::swap((float&)root->rotation.z,(float&)root->rotation.y); + rootOut->mTransformation.FromEulerAnglesXYZ(AI_DEG_TO_RAD(root->rotation)); + + // apply scaling + aiMatrix4x4 &mat = rootOut->mTransformation; + mat.a1 *= root->scaling.x; + mat.b1 *= root->scaling.x; + mat.c1 *= root->scaling.x; + mat.a2 *= root->scaling.y; + mat.b2 *= root->scaling.y; + mat.c2 *= root->scaling.y; + mat.a3 *= root->scaling.z; + mat.b3 *= root->scaling.z; + mat.c3 *= root->scaling.z; + + // apply translation + mat.a4 += root->position.x; + mat.b4 += root->position.y; + mat.c4 += root->position.z; + + // now compute animations for the node + ComputeAnimations(root, rootOut, anims); + + // Add all children recursively. First allocate enough storage + // for them, then call us again + rootOut->mNumChildren = (unsigned int)root->children.size(); + if (rootOut->mNumChildren) { + + rootOut->mChildren = new aiNode *[rootOut->mNumChildren]; + for (unsigned int i = 0; i < rootOut->mNumChildren; ++i) { + + aiNode *node = rootOut->mChildren[i] = new aiNode(); + node->mParent = rootOut; + GenerateGraph(root->children[i], node, scene, batch, meshes, + anims, attach, materials, defMatIdx); + } + } +>>>>>>> master } // ------------------------------------------------------------------------------------------------ // Imports the given file into the given scene structure. void IRRImporter::InternReadFile(const std::string &pFile, +<<<<<<< HEAD aiScene *pScene, IOSystem *pIOHandler) { std::unique_ptr file(pIOHandler->Open(pFile)); @@ -990,6 +1736,136 @@ void IRRImporter::InternReadFile(const std::string &pFile, // We should have a valid node here // FIX: no ... the scene root node is also contained in an attributes block if (!curNode) { +======= + aiScene *pScene, IOSystem *pIOHandler) { + std::unique_ptr file(pIOHandler->Open(pFile)); + + // Check whether we can read from the file + if (file.get() == nullptr) { + throw DeadlyImportError("Failed to open IRR file " + pFile + ""); + } + + // Construct the irrXML parser + CIrrXML_IOStreamReader st(file.get()); + reader = createIrrXMLReader((IFileReadCallBack *)&st); + + // The root node of the scene + Node *root = new Node(Node::DUMMY); + root->parent = nullptr; + root->name = ""; + + // Current node parent + Node *curParent = root; + + // Scenegraph node we're currently working on + Node *curNode = nullptr; + + // List of output cameras + std::vector cameras; + + // List of output lights + std::vector lights; + + // Batch loader used to load external models + BatchLoader batch(pIOHandler); + // batch.SetBasePath(pFile); + + cameras.reserve(5); + lights.reserve(5); + + bool inMaterials = false, inAnimator = false; + unsigned int guessedAnimCnt = 0, guessedMeshCnt = 0, guessedMatCnt = 0; + + // Parse the XML file + while (reader->read()) { + switch (reader->getNodeType()) { + case EXN_ELEMENT: + + if (!ASSIMP_stricmp(reader->getNodeName(), "node")) { + // *********************************************************************** + /* What we're going to do with the node depends + * on its type: + * + * "mesh" - Load a mesh from an external file + * "cube" - Generate a cube + * "skybox" - Generate a skybox + * "light" - A light source + * "sphere" - Generate a sphere mesh + * "animatedMesh" - Load an animated mesh from an external file + * and join its animation channels with ours. + * "empty" - A dummy node + * "camera" - A camera + * "terrain" - a terrain node (data comes from a heightmap) + * "billboard", "" + * + * Each of these nodes can be animated and all can have multiple + * materials assigned (except lights, cameras and dummies, of course). + */ + // *********************************************************************** + const char *sz = reader->getAttributeValueSafe("type"); + Node *nd; + if (!ASSIMP_stricmp(sz, "mesh") || !ASSIMP_stricmp(sz, "octTree")) { + // OctTree's and meshes are treated equally + nd = new Node(Node::MESH); + } else if (!ASSIMP_stricmp(sz, "cube")) { + nd = new Node(Node::CUBE); + ++guessedMeshCnt; + // meshes.push_back(StandardShapes::MakeMesh(&StandardShapes::MakeHexahedron)); + } else if (!ASSIMP_stricmp(sz, "skybox")) { + nd = new Node(Node::SKYBOX); + guessedMeshCnt += 6; + } else if (!ASSIMP_stricmp(sz, "camera")) { + nd = new Node(Node::CAMERA); + + // Setup a temporary name for the camera + aiCamera *cam = new aiCamera(); + cam->mName.Set(nd->name); + cameras.push_back(cam); + } else if (!ASSIMP_stricmp(sz, "light")) { + nd = new Node(Node::LIGHT); + + // Setup a temporary name for the light + aiLight *cam = new aiLight(); + cam->mName.Set(nd->name); + lights.push_back(cam); + } else if (!ASSIMP_stricmp(sz, "sphere")) { + nd = new Node(Node::SPHERE); + ++guessedMeshCnt; + } else if (!ASSIMP_stricmp(sz, "animatedMesh")) { + nd = new Node(Node::ANIMMESH); + } else if (!ASSIMP_stricmp(sz, "empty")) { + nd = new Node(Node::DUMMY); + } else if (!ASSIMP_stricmp(sz, "terrain")) { + nd = new Node(Node::TERRAIN); + } else if (!ASSIMP_stricmp(sz, "billBoard")) { + // We don't support billboards, so ignore them + ASSIMP_LOG_ERROR("IRR: Billboards are not supported by Assimp"); + nd = new Node(Node::DUMMY); + } else { + ASSIMP_LOG_WARN("IRR: Found unknown node: " + std::string(sz)); + + /* We skip the contents of nodes we don't know. + * We parse the transformation and all animators + * and skip the rest. + */ + nd = new Node(Node::DUMMY); + } + + /* Attach the newly created node to the scenegraph + */ + curNode = nd; + nd->parent = curParent; + curParent->children.push_back(nd); + } else if (!ASSIMP_stricmp(reader->getNodeName(), "materials")) { + inMaterials = true; + } else if (!ASSIMP_stricmp(reader->getNodeName(), "animators")) { + inAnimator = true; + } else if (!ASSIMP_stricmp(reader->getNodeName(), "attributes")) { + /* We should have a valid node here + * FIX: no ... the scene root node is also contained in an attributes block + */ + if (!curNode) { +>>>>>>> master #if 0 ASSIMP_LOG_ERROR("IRR: Encountered element, but " "there is no node active"); @@ -997,6 +1873,7 @@ void IRRImporter::InternReadFile(const std::string &pFile, continue; } +<<<<<<< HEAD Animator *curAnim = nullptr; // Materials can occur for nearly any type of node @@ -1006,6 +1883,16 @@ void IRRImporter::InternReadFile(const std::string &pFile, std::pair &p = curNode->materials.back(); p.first = ParseMaterial(p.second); +======= + Animator *curAnim = nullptr; + + // Materials can occur for nearly any type of node + if (inMaterials && curNode->type != Node::DUMMY) { + /* This is a material description - parse it! + */ + curNode->materials.push_back(std::pair()); + std::pair &p = curNode->materials.back(); +>>>>>>> master ++guessedMatCnt; continue; @@ -1015,6 +1902,7 @@ void IRRImporter::InternReadFile(const std::string &pFile, curNode->animators.push_back(Animator()); curAnim = &curNode->animators.back(); +<<<<<<< HEAD ++guessedAnimCnt; } @@ -1196,6 +2084,191 @@ void IRRImporter::InternReadFile(const std::string &pFile, } else if ((prop.name == "Mesh" && Node::MESH == curNode->type) || Node::ANIMMESH == curNode->type) { /* This is the file name of the mesh - either +======= + ++guessedMatCnt; + continue; + } else if (inAnimator) { + /* This is an animation path - add a new animator + * to the list. + */ + curNode->animators.push_back(Animator()); + curAnim = &curNode->animators.back(); + + ++guessedAnimCnt; + } + + /* Parse all elements in the attributes block + * and process them. + */ + while (reader->read()) { + if (reader->getNodeType() == EXN_ELEMENT) { + if (!ASSIMP_stricmp(reader->getNodeName(), "vector3d")) { + VectorProperty prop; + ReadVectorProperty(prop); + + if (inAnimator) { + if (curAnim->type == Animator::ROTATION && prop.name == "Rotation") { + // We store the rotation euler angles in 'direction' + curAnim->direction = prop.value; + } else if (curAnim->type == Animator::FOLLOW_SPLINE) { + // Check whether the vector follows the PointN naming scheme, + // here N is the ONE-based index of the point + if (prop.name.length() >= 6 && prop.name.substr(0, 5) == "Point") { + // Add a new key to the list + curAnim->splineKeys.push_back(aiVectorKey()); + aiVectorKey &key = curAnim->splineKeys.back(); + + // and parse its properties + key.mValue = prop.value; + key.mTime = strtoul10(&prop.name[5]); + } + } else if (curAnim->type == Animator::FLY_CIRCLE) { + if (prop.name == "Center") { + curAnim->circleCenter = prop.value; + } else if (prop.name == "Direction") { + curAnim->direction = prop.value; + + // From Irrlicht's source - a workaround for backward compatibility with Irrlicht 1.1 + if (curAnim->direction == aiVector3D()) { + curAnim->direction = aiVector3D(0.f, 1.f, 0.f); + } else + curAnim->direction.Normalize(); + } + } else if (curAnim->type == Animator::FLY_STRAIGHT) { + if (prop.name == "Start") { + // We reuse the field here + curAnim->circleCenter = prop.value; + } else if (prop.name == "End") { + // We reuse the field here + curAnim->direction = prop.value; + } + } + } else { + if (prop.name == "Position") { + curNode->position = prop.value; + } else if (prop.name == "Rotation") { + curNode->rotation = prop.value; + } else if (prop.name == "Scale") { + curNode->scaling = prop.value; + } else if (Node::CAMERA == curNode->type) { + aiCamera *cam = cameras.back(); + if (prop.name == "Target") { + cam->mLookAt = prop.value; + } else if (prop.name == "UpVector") { + cam->mUp = prop.value; + } + } + } + } else if (!ASSIMP_stricmp(reader->getNodeName(), "bool")) { + BoolProperty prop; + ReadBoolProperty(prop); + + if (inAnimator && curAnim->type == Animator::FLY_CIRCLE && prop.name == "Loop") { + curAnim->loop = prop.value; + } + } else if (!ASSIMP_stricmp(reader->getNodeName(), "float")) { + FloatProperty prop; + ReadFloatProperty(prop); + + if (inAnimator) { + // The speed property exists for several animators + if (prop.name == "Speed") { + curAnim->speed = prop.value; + } else if (curAnim->type == Animator::FLY_CIRCLE && prop.name == "Radius") { + curAnim->circleRadius = prop.value; + } else if (curAnim->type == Animator::FOLLOW_SPLINE && prop.name == "Tightness") { + curAnim->tightness = prop.value; + } + } else { + if (prop.name == "FramesPerSecond" && Node::ANIMMESH == curNode->type) { + curNode->framesPerSecond = prop.value; + } else if (Node::CAMERA == curNode->type) { + /* This is the vertical, not the horizontal FOV. + * We need to compute the right FOV from the + * screen aspect which we don't know yet. + */ + if (prop.name == "Fovy") { + cameras.back()->mHorizontalFOV = prop.value; + } else if (prop.name == "Aspect") { + cameras.back()->mAspect = prop.value; + } else if (prop.name == "ZNear") { + cameras.back()->mClipPlaneNear = prop.value; + } else if (prop.name == "ZFar") { + cameras.back()->mClipPlaneFar = prop.value; + } + } else if (Node::LIGHT == curNode->type) { + /* Additional light information + */ + if (prop.name == "Attenuation") { + lights.back()->mAttenuationLinear = prop.value; + } else if (prop.name == "OuterCone") { + lights.back()->mAngleOuterCone = AI_DEG_TO_RAD(prop.value); + } else if (prop.name == "InnerCone") { + lights.back()->mAngleInnerCone = AI_DEG_TO_RAD(prop.value); + } + } + // radius of the sphere to be generated - + // or alternatively, size of the cube + else if ((Node::SPHERE == curNode->type && prop.name == "Radius") || (Node::CUBE == curNode->type && prop.name == "Size")) { + + curNode->sphereRadius = prop.value; + } + } + } else if (!ASSIMP_stricmp(reader->getNodeName(), "int")) { + IntProperty prop; + ReadIntProperty(prop); + + if (inAnimator) { + if (curAnim->type == Animator::FLY_STRAIGHT && prop.name == "TimeForWay") { + curAnim->timeForWay = prop.value; + } + } else { + // sphere polgon numbers in each direction + if (Node::SPHERE == curNode->type) { + + if (prop.name == "PolyCountX") { + curNode->spherePolyCountX = prop.value; + } else if (prop.name == "PolyCountY") { + curNode->spherePolyCountY = prop.value; + } + } + } + } else if (!ASSIMP_stricmp(reader->getNodeName(), "string") || !ASSIMP_stricmp(reader->getNodeName(), "enum")) { + StringProperty prop; + ReadStringProperty(prop); + if (prop.value.length()) { + if (prop.name == "Name") { + curNode->name = prop.value; + + /* If we're either a camera or a light source + * we need to update the name in the aiLight/ + * aiCamera structure, too. + */ + if (Node::CAMERA == curNode->type) { + cameras.back()->mName.Set(prop.value); + } else if (Node::LIGHT == curNode->type) { + lights.back()->mName.Set(prop.value); + } + } else if (Node::LIGHT == curNode->type && "LightType" == prop.name) { + if (prop.value == "Spot") + lights.back()->mType = aiLightSource_SPOT; + else if (prop.value == "Point") + lights.back()->mType = aiLightSource_POINT; + else if (prop.value == "Directional") + lights.back()->mType = aiLightSource_DIRECTIONAL; + else { + // We won't pass the validation with aiLightSourceType_UNDEFINED, + // so we remove the light and replace it with a silly dummy node + delete lights.back(); + lights.pop_back(); + curNode->type = Node::DUMMY; + + ASSIMP_LOG_ERROR("Ignoring light of unknown type: " + prop.value); + } + } else if ((prop.name == "Mesh" && Node::MESH == curNode->type) || + Node::ANIMMESH == curNode->type) { + /* This is the file name of the mesh - either +>>>>>>> master * animated or not. We need to make sure we setup * the correct post-processing settings here. */ @@ -1204,6 +2277,7 @@ void IRRImporter::InternReadFile(const std::string &pFile, /* If the mesh is a static one remove all animations from the impor data */ +<<<<<<< HEAD if (Node::ANIMMESH != curNode->type) { pp |= aiProcess_RemoveComponent; SetGenericProperty(map.ints, AI_CONFIG_PP_RVC_FLAGS, @@ -1378,6 +2452,191 @@ void IRRImporter::InternReadFile(const std::string &pFile, // Finished ... everything destructs automatically and all // temporary scenes have already been deleted by MergeScenes() delete root; +======= + if (Node::ANIMMESH != curNode->type) { + pp |= aiProcess_RemoveComponent; + SetGenericProperty(map.ints, AI_CONFIG_PP_RVC_FLAGS, + aiComponent_ANIMATIONS | aiComponent_BONEWEIGHTS); + } + + /* TODO: maybe implement the protection against recursive + * loading calls directly in BatchLoader? The current + * implementation is not absolutely safe. A LWS and an IRR + * file referencing each other *could* cause the system to + * recurse forever. + */ + + const std::string extension = GetExtension(prop.value); + if ("irr" == extension) { + ASSIMP_LOG_ERROR("IRR: Can't load another IRR file recursively"); + } else { + curNode->id = batch.AddLoadRequest(prop.value, pp, &map); + curNode->meshPath = prop.value; + } + } else if (inAnimator && prop.name == "Type") { + // type of the animator + if (prop.value == "rotation") { + curAnim->type = Animator::ROTATION; + } else if (prop.value == "flyCircle") { + curAnim->type = Animator::FLY_CIRCLE; + } else if (prop.value == "flyStraight") { + curAnim->type = Animator::FLY_CIRCLE; + } else if (prop.value == "followSpline") { + curAnim->type = Animator::FOLLOW_SPLINE; + } else { + ASSIMP_LOG_WARN("IRR: Ignoring unknown animator: " + prop.value); + + curAnim->type = Animator::UNKNOWN; + } + } + } + } + } else if (reader->getNodeType() == EXN_ELEMENT_END && !ASSIMP_stricmp(reader->getNodeName(), "attributes")) { + break; + } + } + } + break; + + case EXN_ELEMENT_END: + + // If we reached the end of a node, we need to continue processing its parent + if (!ASSIMP_stricmp(reader->getNodeName(), "node")) { + if (!curNode) { + // currently is no node set. We need to go + // back in the node hierarchy + if (!curParent) { + curParent = root; + ASSIMP_LOG_ERROR("IRR: Too many closing elements"); + } else + curParent = curParent->parent; + } else + curNode = nullptr; + } + // clear all flags + else if (!ASSIMP_stricmp(reader->getNodeName(), "materials")) { + inMaterials = false; + } else if (!ASSIMP_stricmp(reader->getNodeName(), "animators")) { + inAnimator = false; + } + break; + + default: + // GCC complains that not all enumeration values are handled + break; + } + } + + // Now iterate through all cameras and compute their final (horizontal) FOV + for (aiCamera *cam : cameras) { + // screen aspect could be missing + if (cam->mAspect) { + cam->mHorizontalFOV *= cam->mAspect; + } else { + ASSIMP_LOG_WARN("IRR: Camera aspect is not given, can't compute horizontal FOV"); + } + } + + batch.LoadAll(); + + /* Allocate a tempoary scene data structure + */ + aiScene *tempScene = new aiScene(); + tempScene->mRootNode = new aiNode(); + tempScene->mRootNode->mName.Set(""); + + /* Copy the cameras to the output array + */ + if (!cameras.empty()) { + tempScene->mNumCameras = (unsigned int)cameras.size(); + tempScene->mCameras = new aiCamera *[tempScene->mNumCameras]; + ::memcpy(tempScene->mCameras, &cameras[0], sizeof(void *) * tempScene->mNumCameras); + } + + /* Copy the light sources to the output array + */ + if (!lights.empty()) { + tempScene->mNumLights = (unsigned int)lights.size(); + tempScene->mLights = new aiLight *[tempScene->mNumLights]; + ::memcpy(tempScene->mLights, &lights[0], sizeof(void *) * tempScene->mNumLights); + } + + // temporary data + std::vector anims; + std::vector materials; + std::vector attach; + std::vector meshes; + + // try to guess how much storage we'll need + anims.reserve(guessedAnimCnt + (guessedAnimCnt >> 2)); + meshes.reserve(guessedMeshCnt + (guessedMeshCnt >> 2)); + materials.reserve(guessedMatCnt + (guessedMatCnt >> 2)); + + /* Now process our scenegraph recursively: generate final + * meshes and generate animation channels for all nodes. + */ + unsigned int defMatIdx = UINT_MAX; + GenerateGraph(root, tempScene->mRootNode, tempScene, + batch, meshes, anims, attach, materials, defMatIdx); + + if (!anims.empty()) { + tempScene->mNumAnimations = 1; + tempScene->mAnimations = new aiAnimation *[tempScene->mNumAnimations]; + aiAnimation *an = tempScene->mAnimations[0] = new aiAnimation(); + + // *********************************************************** + // This is only the global animation channel of the scene. + // If there are animated models, they will have separate + // animation channels in the scene. To display IRR scenes + // correctly, users will need to combine the global anim + // channel with all the local animations they want to play + // *********************************************************** + an->mName.Set("Irr_GlobalAnimChannel"); + + // copy all node animation channels to the global channel + an->mNumChannels = (unsigned int)anims.size(); + an->mChannels = new aiNodeAnim *[an->mNumChannels]; + ::memcpy(an->mChannels, &anims[0], sizeof(void *) * an->mNumChannels); + } + if (!meshes.empty()) { + // copy all meshes to the temporary scene + tempScene->mNumMeshes = (unsigned int)meshes.size(); + tempScene->mMeshes = new aiMesh *[tempScene->mNumMeshes]; + ::memcpy(tempScene->mMeshes, &meshes[0], tempScene->mNumMeshes * sizeof(void *)); + } + + /* Copy all materials to the output array + */ + if (!materials.empty()) { + tempScene->mNumMaterials = (unsigned int)materials.size(); + tempScene->mMaterials = new aiMaterial *[tempScene->mNumMaterials]; + ::memcpy(tempScene->mMaterials, &materials[0], sizeof(void *) * tempScene->mNumMaterials); + } + + /* Now merge all sub scenes and attach them to the correct + * attachment points in the scenegraph. + */ + SceneCombiner::MergeScenes(&pScene, tempScene, attach, + AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES | (!configSpeedFlag ? ( + AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES_IF_NECESSARY | AI_INT_MERGE_SCENE_GEN_UNIQUE_MATNAMES) : + 0)); + + /* If we have no meshes | no materials now set the INCOMPLETE + * scene flag. This is necessary if we failed to load all + * models from external files + */ + if (!pScene->mNumMeshes || !pScene->mNumMaterials) { + ASSIMP_LOG_WARN("IRR: No meshes loaded, setting AI_SCENE_FLAGS_INCOMPLETE"); + pScene->mFlags |= AI_SCENE_FLAGS_INCOMPLETE; + } + + /* Finished ... everything destructs automatically and all + * temporary scenes have already been deleted by MergeScenes() + */ + + delete root; + delete reader; +>>>>>>> master } #endif // !! ASSIMP_BUILD_NO_IRR_IMPORTER diff --git a/code/AssetLib/Irr/IRRMeshLoader.cpp b/code/AssetLib/Irr/IRRMeshLoader.cpp index 904210d48..4c9fcd5d3 100644 --- a/code/AssetLib/Irr/IRRMeshLoader.cpp +++ b/code/AssetLib/Irr/IRRMeshLoader.cpp @@ -129,6 +129,7 @@ static void releaseMesh(aiMesh **mesh) { // ------------------------------------------------------------------------------------------------ // Imports the given file into the given scene structure. +<<<<<<< HEAD void IRRMeshImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler) { std::unique_ptr file(pIOHandler->Open(pFile)); @@ -511,6 +512,406 @@ void IRRMeshImporter::InternReadFile(const std::string &pFile, pScene->mRootNode->mMeshes[i] = i; } +======= +void IRRMeshImporter::InternReadFile( const std::string& pFile, + aiScene* pScene, IOSystem* pIOHandler) +{ + std::unique_ptr file( pIOHandler->Open( pFile)); + + // Check whether we can read from the file + if (file.get() == nullptr) { + throw DeadlyImportError("Failed to open IRRMESH file " + pFile + "."); + } + + // Construct the irrXML parser + CIrrXML_IOStreamReader st(file.get()); + reader = createIrrXMLReader((IFileReadCallBack*) &st); + + // final data + std::vector materials; + std::vector meshes; + materials.reserve (5); + meshes.reserve(5); + + // temporary data - current mesh buffer + aiMaterial* curMat = nullptr; + aiMesh* curMesh = nullptr; + unsigned int curMatFlags = 0; + + std::vector curVertices,curNormals,curTangents,curBitangents; + std::vector curColors; + std::vector curUVs,curUV2s; + + // some temporary variables + int textMeaning = 0; + int vertexFormat = 0; // 0 = normal; 1 = 2 tcoords, 2 = tangents + bool useColors = false; + + // Parse the XML file + while (reader->read()) { + switch (reader->getNodeType()) { + case EXN_ELEMENT: + + if (!ASSIMP_stricmp(reader->getNodeName(),"buffer") && (curMat || curMesh)) { + // end of previous buffer. A material and a mesh should be there + if ( !curMat || !curMesh) { + ASSIMP_LOG_ERROR("IRRMESH: A buffer must contain a mesh and a material"); + releaseMaterial( &curMat ); + releaseMesh( &curMesh ); + } else { + materials.push_back(curMat); + meshes.push_back(curMesh); + } + curMat = nullptr; + curMesh = nullptr; + + curVertices.clear(); + curColors.clear(); + curNormals.clear(); + curUV2s.clear(); + curUVs.clear(); + curTangents.clear(); + curBitangents.clear(); + } + + + if (!ASSIMP_stricmp(reader->getNodeName(),"material")) { + if (curMat) { + ASSIMP_LOG_WARN("IRRMESH: Only one material description per buffer, please"); + releaseMaterial( &curMat ); + } + curMat = ParseMaterial(curMatFlags); + } + /* no else here! */ if (!ASSIMP_stricmp(reader->getNodeName(),"vertices")) + { + int num = reader->getAttributeValueAsInt("vertexCount"); + + if (!num) { + // This is possible ... remove the mesh from the list and skip further reading + ASSIMP_LOG_WARN("IRRMESH: Found mesh with zero vertices"); + + releaseMaterial( &curMat ); + releaseMesh( &curMesh ); + textMeaning = 0; + continue; + } + + curVertices.reserve(num); + curNormals.reserve(num); + curColors.reserve(num); + curUVs.reserve(num); + + // Determine the file format + const char* t = reader->getAttributeValueSafe("type"); + if (!ASSIMP_stricmp("2tcoords", t)) { + curUV2s.reserve (num); + vertexFormat = 1; + + if (curMatFlags & AI_IRRMESH_EXTRA_2ND_TEXTURE) { + // ********************************************************* + // We have a second texture! So use this UV channel + // for it. The 2nd texture can be either a normal + // texture (solid_2layer or lightmap_xxx) or a normal + // map (normal_..., parallax_...) + // ********************************************************* + int idx = 1; + aiMaterial* mat = ( aiMaterial* ) curMat; + + if (curMatFlags & AI_IRRMESH_MAT_lightmap){ + mat->AddProperty(&idx,1,AI_MATKEY_UVWSRC_LIGHTMAP(0)); + } + else if (curMatFlags & AI_IRRMESH_MAT_normalmap_solid){ + mat->AddProperty(&idx,1,AI_MATKEY_UVWSRC_NORMALS(0)); + } + else if (curMatFlags & AI_IRRMESH_MAT_solid_2layer) { + mat->AddProperty(&idx,1,AI_MATKEY_UVWSRC_DIFFUSE(1)); + } + } + } + else if (!ASSIMP_stricmp("tangents", t)) { + curTangents.reserve (num); + curBitangents.reserve (num); + vertexFormat = 2; + } + else if (ASSIMP_stricmp("standard", t)) { + releaseMaterial( &curMat ); + ASSIMP_LOG_WARN("IRRMESH: Unknown vertex format"); + } + else vertexFormat = 0; + textMeaning = 1; + } + else if (!ASSIMP_stricmp(reader->getNodeName(),"indices")) { + if (curVertices.empty() && curMat) { + releaseMaterial( &curMat ); + throw DeadlyImportError("IRRMESH: indices must come after vertices"); + } + + textMeaning = 2; + + // start a new mesh + curMesh = new aiMesh(); + + // allocate storage for all faces + curMesh->mNumVertices = reader->getAttributeValueAsInt("indexCount"); + if (!curMesh->mNumVertices) { + // This is possible ... remove the mesh from the list and skip further reading + ASSIMP_LOG_WARN("IRRMESH: Found mesh with zero indices"); + + // mesh - away + releaseMesh( &curMesh ); + + // material - away + releaseMaterial( &curMat ); + + textMeaning = 0; + continue; + } + + if (curMesh->mNumVertices % 3) { + ASSIMP_LOG_WARN("IRRMESH: Number if indices isn't divisible by 3"); + } + + curMesh->mNumFaces = curMesh->mNumVertices / 3; + curMesh->mFaces = new aiFace[curMesh->mNumFaces]; + + // setup some members + curMesh->mMaterialIndex = (unsigned int)materials.size(); + curMesh->mPrimitiveTypes = aiPrimitiveType_TRIANGLE; + + // allocate storage for all vertices + curMesh->mVertices = new aiVector3D[curMesh->mNumVertices]; + + if (curNormals.size() == curVertices.size()) { + curMesh->mNormals = new aiVector3D[curMesh->mNumVertices]; + } + if (curTangents.size() == curVertices.size()) { + curMesh->mTangents = new aiVector3D[curMesh->mNumVertices]; + } + if (curBitangents.size() == curVertices.size()) { + curMesh->mBitangents = new aiVector3D[curMesh->mNumVertices]; + } + if (curColors.size() == curVertices.size() && useColors) { + curMesh->mColors[0] = new aiColor4D[curMesh->mNumVertices]; + } + if (curUVs.size() == curVertices.size()) { + curMesh->mTextureCoords[0] = new aiVector3D[curMesh->mNumVertices]; + } + if (curUV2s.size() == curVertices.size()) { + curMesh->mTextureCoords[1] = new aiVector3D[curMesh->mNumVertices]; + } + } + break; + + case EXN_TEXT: + { + const char* sz = reader->getNodeData(); + if (textMeaning == 1) { + textMeaning = 0; + + // read vertices + do { + SkipSpacesAndLineEnd(&sz); + aiVector3D temp;aiColor4D c; + + // Read the vertex position + sz = fast_atoreal_move(sz,(float&)temp.x); + SkipSpaces(&sz); + + sz = fast_atoreal_move(sz,(float&)temp.y); + SkipSpaces(&sz); + + sz = fast_atoreal_move(sz,(float&)temp.z); + SkipSpaces(&sz); + curVertices.push_back(temp); + + // Read the vertex normals + sz = fast_atoreal_move(sz,(float&)temp.x); + SkipSpaces(&sz); + + sz = fast_atoreal_move(sz,(float&)temp.y); + SkipSpaces(&sz); + + sz = fast_atoreal_move(sz,(float&)temp.z); + SkipSpaces(&sz); + curNormals.push_back(temp); + + // read the vertex colors + uint32_t clr = strtoul16(sz,&sz); + ColorFromARGBPacked(clr,c); + + if (!curColors.empty() && c != *(curColors.end()-1)) + useColors = true; + + curColors.push_back(c); + SkipSpaces(&sz); + + + // read the first UV coordinate set + sz = fast_atoreal_move(sz,(float&)temp.x); + SkipSpaces(&sz); + + sz = fast_atoreal_move(sz,(float&)temp.y); + SkipSpaces(&sz); + temp.z = 0.f; + temp.y = 1.f - temp.y; // DX to OGL + curUVs.push_back(temp); + + // read the (optional) second UV coordinate set + if (vertexFormat == 1) { + sz = fast_atoreal_move(sz,(float&)temp.x); + SkipSpaces(&sz); + + sz = fast_atoreal_move(sz,(float&)temp.y); + temp.y = 1.f - temp.y; // DX to OGL + curUV2s.push_back(temp); + } + // read optional tangent and bitangent vectors + else if (vertexFormat == 2) { + // tangents + sz = fast_atoreal_move(sz,(float&)temp.x); + SkipSpaces(&sz); + + sz = fast_atoreal_move(sz,(float&)temp.z); + SkipSpaces(&sz); + + sz = fast_atoreal_move(sz,(float&)temp.y); + SkipSpaces(&sz); + temp.y *= -1.0f; + curTangents.push_back(temp); + + // bitangents + sz = fast_atoreal_move(sz,(float&)temp.x); + SkipSpaces(&sz); + + sz = fast_atoreal_move(sz,(float&)temp.z); + SkipSpaces(&sz); + + sz = fast_atoreal_move(sz,(float&)temp.y); + SkipSpaces(&sz); + temp.y *= -1.0f; + curBitangents.push_back(temp); + } + } + + /* IMPORTANT: We assume that each vertex is specified in one + line. So we can skip the rest of the line - unknown vertex + elements are ignored. + */ + + while (SkipLine(&sz)); + } + else if (textMeaning == 2) { + textMeaning = 0; + + // read indices + aiFace* curFace = curMesh->mFaces; + aiFace* const faceEnd = curMesh->mFaces + curMesh->mNumFaces; + + aiVector3D* pcV = curMesh->mVertices; + aiVector3D* pcN = curMesh->mNormals; + aiVector3D* pcT = curMesh->mTangents; + aiVector3D* pcB = curMesh->mBitangents; + aiColor4D* pcC0 = curMesh->mColors[0]; + aiVector3D* pcT0 = curMesh->mTextureCoords[0]; + aiVector3D* pcT1 = curMesh->mTextureCoords[1]; + + unsigned int curIdx = 0; + unsigned int total = 0; + while(SkipSpacesAndLineEnd(&sz)) { + if (curFace >= faceEnd) { + ASSIMP_LOG_ERROR("IRRMESH: Too many indices"); + break; + } + if (!curIdx) { + curFace->mNumIndices = 3; + curFace->mIndices = new unsigned int[3]; + } + + unsigned int idx = strtoul10(sz,&sz); + if (idx >= curVertices.size()) { + ASSIMP_LOG_ERROR("IRRMESH: Index out of range"); + idx = 0; + } + + curFace->mIndices[curIdx] = total++; + + *pcV++ = curVertices[idx]; + if (pcN)*pcN++ = curNormals[idx]; + if (pcT)*pcT++ = curTangents[idx]; + if (pcB)*pcB++ = curBitangents[idx]; + if (pcC0)*pcC0++ = curColors[idx]; + if (pcT0)*pcT0++ = curUVs[idx]; + if (pcT1)*pcT1++ = curUV2s[idx]; + + if (++curIdx == 3) { + ++curFace; + curIdx = 0; + } + } + + if (curFace != faceEnd) + ASSIMP_LOG_ERROR("IRRMESH: Not enough indices"); + + // Finish processing the mesh - do some small material workarounds + if (curMatFlags & AI_IRRMESH_MAT_trans_vertex_alpha && !useColors) { + // Take the opacity value of the current material + // from the common vertex color alpha + aiMaterial* mat = (aiMaterial*)curMat; + mat->AddProperty(&curColors[0].a,1,AI_MATKEY_OPACITY); + } + }} + break; + + default: + // GCC complains here ... + break; + + }; + } + + // End of the last buffer. A material and a mesh should be there + if (curMat || curMesh) { + if ( !curMat || !curMesh) { + ASSIMP_LOG_ERROR("IRRMESH: A buffer must contain a mesh and a material"); + releaseMaterial( &curMat ); + releaseMesh( &curMesh ); + } + else { + materials.push_back(curMat); + meshes.push_back(curMesh); + } + } + + if (materials.empty()) + throw DeadlyImportError("IRRMESH: Unable to read a mesh from this file"); + + + // now generate the output scene + pScene->mNumMeshes = (unsigned int)meshes.size(); + pScene->mMeshes = new aiMesh*[pScene->mNumMeshes]; + for (unsigned int i = 0; i < pScene->mNumMeshes;++i) { + pScene->mMeshes[i] = meshes[i]; + + // clean this value ... + pScene->mMeshes[i]->mNumUVComponents[3] = 0; + } + + pScene->mNumMaterials = (unsigned int)materials.size(); + pScene->mMaterials = new aiMaterial*[pScene->mNumMaterials]; + ::memcpy(pScene->mMaterials,&materials[0],sizeof(void*)*pScene->mNumMaterials); + + pScene->mRootNode = new aiNode(); + pScene->mRootNode->mName.Set(""); + pScene->mRootNode->mNumMeshes = pScene->mNumMeshes; + pScene->mRootNode->mMeshes = new unsigned int[pScene->mNumMeshes]; + + for (unsigned int i = 0; i < pScene->mNumMeshes;++i) + pScene->mRootNode->mMeshes[i] = i; + + // clean up and return + delete reader; + AI_DEBUG_INVALIDATE_PTR(reader); +>>>>>>> master } #endif // !! ASSIMP_BUILD_NO_IRRMESH_IMPORTER diff --git a/code/AssetLib/LWO/LWOAnimation.cpp b/code/AssetLib/LWO/LWOAnimation.cpp index 228dea26d..d4b69b00b 100644 --- a/code/AssetLib/LWO/LWOAnimation.cpp +++ b/code/AssetLib/LWO/LWOAnimation.cpp @@ -538,11 +538,11 @@ void AnimResolver::GetKeys(std::vector &out, // ------------------------------------------------------------------------------------------------ // Extract animation channel void AnimResolver::ExtractAnimChannel(aiNodeAnim **out, unsigned int /*= 0*/) { - *out = NULL; + *out = nullptr; //FIXME: crashes if more than one component is animated at different timings, to be resolved. - // If we have no envelopes, return NULL + // If we have no envelopes, return nullptr if (envelopes.empty()) { return; } diff --git a/code/AssetLib/LWO/LWOAnimation.h b/code/AssetLib/LWO/LWOAnimation.h index a46787965..329548ef4 100644 --- a/code/AssetLib/LWO/LWOAnimation.h +++ b/code/AssetLib/LWO/LWOAnimation.h @@ -211,7 +211,7 @@ public: // ------------------------------------------------------------------ /** @brief Extract a node animation channel * @param out Receives a pointer to a newly allocated node anim. - * If there's just one keyframe defined, *out is set to NULL and + * If there's just one keyframe defined, *out is set to nullptr and * no animation channel is computed. * @param flags Any combination of the AI_LWO_ANIM_FLAG_XXX flags. */ @@ -261,7 +261,7 @@ protected: * @param envl_y Y-component envelope * @param envl_z Z-component envelope * @param flags Any combination of the AI_LWO_ANIM_FLAG_XXX flags. - * @note Up to two input envelopes may be NULL + * @note Up to two input envelopes may be nullptr */ void GetKeys(std::vector& out, LWO::Envelope* envl_x, diff --git a/code/AssetLib/LWO/LWOBLoader.cpp b/code/AssetLib/LWO/LWOBLoader.cpp index fe542df1b..751a7c18a 100644 --- a/code/AssetLib/LWO/LWOBLoader.cpp +++ b/code/AssetLib/LWO/LWOBLoader.cpp @@ -255,7 +255,7 @@ void LWOImporter::LoadLWOBSurface(unsigned int size) mSurfaces->push_back( LWO::Surface () ); LWO::Surface& surf = mSurfaces->back(); - LWO::Texture* pTex = NULL; + LWO::Texture *pTex = nullptr; GetS0(surf.mName,size); bool running = true; diff --git a/code/AssetLib/LWO/LWOLoader.cpp b/code/AssetLib/LWO/LWOLoader.cpp index c0431c2d9..ef11f2d15 100644 --- a/code/AssetLib/LWO/LWOLoader.cpp +++ b/code/AssetLib/LWO/LWOLoader.cpp @@ -917,7 +917,7 @@ inline void CreateNewEntry(std::vector &list, unsigned int srcIdx) { // ------------------------------------------------------------------------------------------------ inline void LWOImporter::DoRecursiveVMAPAssignment(VMapEntry *base, unsigned int numRead, unsigned int idx, float *data) { - ai_assert(NULL != data); + ai_assert(nullptr != data); LWO::ReferrerList &refList = mCurLayer->mPointReferrers; unsigned int i; diff --git a/code/AssetLib/LWO/LWOLoader.h b/code/AssetLib/LWO/LWOLoader.h index e9eb7ff1c..1ab85033f 100644 --- a/code/AssetLib/LWO/LWOLoader.h +++ b/code/AssetLib/LWO/LWOLoader.h @@ -305,7 +305,7 @@ private: /** Add children to a node * @param node Node to become a father * @param parent Index of the node - * @param apcNodes Flat list of nodes - used nodes are set to NULL. + * @param apcNodes Flat list of nodes - used nodes are set to nullptr. */ void AddChildren(aiNode* node, uint16_t parent, std::vector& apcNodes); diff --git a/code/AssetLib/LWO/LWOMaterial.cpp b/code/AssetLib/LWO/LWOMaterial.cpp index d7b08011f..be2892829 100644 --- a/code/AssetLib/LWO/LWOMaterial.cpp +++ b/code/AssetLib/LWO/LWOMaterial.cpp @@ -79,7 +79,7 @@ inline aiTextureMapMode GetMapMode(LWO::Texture::Wrap in) { // ------------------------------------------------------------------------------------------------ bool LWOImporter::HandleTextures(aiMaterial *pcMat, const TextureList &in, aiTextureType type) { - ai_assert(NULL != pcMat); + ai_assert(nullptr != pcMat); unsigned int cur = 0, temp = 0; aiString s; @@ -603,7 +603,7 @@ void LWOImporter::LoadLWO2TextureBlock(LE_NCONST IFF::SubChunkHeader *head, unsi } // get the destination channel - TextureList *listRef = NULL; + TextureList *listRef = nullptr; switch (tex.type) { case AI_LWO_COLR: listRef = &surf.mColorTextures; diff --git a/code/AssetLib/LWS/LWSLoader.cpp b/code/AssetLib/LWS/LWSLoader.cpp index 6e4d759ac..38b44f842 100644 --- a/code/AssetLib/LWS/LWSLoader.cpp +++ b/code/AssetLib/LWS/LWSLoader.cpp @@ -342,7 +342,7 @@ void LWSImporter::BuildGraph(aiNode *nd, LWS::NodeDesc &src, std::vectormRootNode->mChildren[0]; - obj->mRootNode->mChildren[0] = NULL; + obj->mRootNode->mChildren[0] = nullptr; delete obj->mRootNode; obj->mRootNode = newRootNode; @@ -600,7 +600,7 @@ void LWSImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy d.number = cur_object++; } std::string path = FindLWOFile(c); - d.id = batch.AddLoadRequest(path, 0, NULL); + d.id = batch.AddLoadRequest(path, 0, nullptr); d.path = path; nodes.push_back(d); diff --git a/code/AssetLib/LWS/LWSLoader.h b/code/AssetLib/LWS/LWSLoader.h index cc181fa43..5f4cb204f 100644 --- a/code/AssetLib/LWS/LWSLoader.h +++ b/code/AssetLib/LWS/LWSLoader.h @@ -84,7 +84,19 @@ public: */ struct NodeDesc { NodeDesc() : - type(), id(), number(0), parent(0), name(""), isPivotSet(false), lightColor(1.f, 1.f, 1.f), lightIntensity(1.f), lightType(0), lightFalloffType(0), lightConeAngle(45.f), lightEdgeAngle(), parent_resolved(NULL) {} + type(), + id(), + number(0), + parent(0), + name(""), + isPivotSet(false), + lightColor(1.f, 1.f, 1.f), + lightIntensity(1.f), + lightType(0), + lightFalloffType(0), + lightConeAngle(45.f), + lightEdgeAngle(), + parent_resolved(nullptr) {} enum { diff --git a/code/AssetLib/M3D/M3DExporter.cpp b/code/AssetLib/M3D/M3DExporter.cpp index 17ba24a44..9583636a1 100644 --- a/code/AssetLib/M3D/M3DExporter.cpp +++ b/code/AssetLib/M3D/M3DExporter.cpp @@ -181,7 +181,7 @@ M3D_INDEX addMaterial(const Assimp::M3DWrapper &m3d, const aiMaterial *mat) { } m3d->material[mi].name = SafeStr(name, true); m3d->material[mi].numprop = 0; - m3d->material[mi].prop = NULL; + m3d->material[mi].prop = nullptr; // iterate through the material property table and see what we got for (k = 0; k < 15; k++) { unsigned int j; @@ -229,8 +229,8 @@ M3D_INDEX addMaterial(const Assimp::M3DWrapper &m3d, const aiMaterial *mat) { } if (aiTxProps[k].pKey && mat->GetTexture((aiTextureType)aiTxProps[k].type, - aiTxProps[k].index, &name, NULL, NULL, NULL, - NULL, NULL) == AI_SUCCESS) { + aiTxProps[k].index, &name, nullptr, nullptr, nullptr, + nullptr, nullptr) == AI_SUCCESS) { unsigned int i; for (j = name.length - 1; j > 0 && name.data[j] != '.'; j++) ; @@ -259,7 +259,7 @@ M3D_INDEX addMaterial(const Assimp::M3DWrapper &m3d, const aiMaterial *mat) { m3d->texture[i].name = fn; m3d->texture[i].w = 0; m3d->texture[i].h = 0; - m3d->texture[i].d = NULL; + m3d->texture[i].d = nullptr; } addProp(&m3d->material[mi], m3d_propertytypes[k].id + 128, i); diff --git a/code/AssetLib/M3D/M3DImporter.cpp b/code/AssetLib/M3D/M3DImporter.cpp index c69783c30..d6fe678ec 100644 --- a/code/AssetLib/M3D/M3DImporter.cpp +++ b/code/AssetLib/M3D/M3DImporter.cpp @@ -618,8 +618,10 @@ aiColor4D M3DImporter::mkColor(uint32_t c) { void M3DImporter::convertPose(const M3DWrapper &m3d, aiMatrix4x4 *m, unsigned int posid, unsigned int orientid) { ai_assert(m != nullptr); ai_assert(m3d); - ai_assert(posid != M3D_UNDEF && posid < m3d->numvertex); - ai_assert(orientid != M3D_UNDEF && orientid < m3d->numvertex); + ai_assert(posid != M3D_UNDEF); + ai_assert(posid < m3d->numvertex); + ai_assert(orientid != M3D_UNDEF); + ai_assert(orientid < m3d->numvertex); if (!m3d->numvertex || !m3d->vertex) return; m3dv_t *p = &m3d->vertex[posid]; diff --git a/code/AssetLib/M3D/M3DMaterials.h b/code/AssetLib/M3D/M3DMaterials.h index 469ddf52b..1aa6f7536 100644 --- a/code/AssetLib/M3D/M3DMaterials.h +++ b/code/AssetLib/M3D/M3DMaterials.h @@ -71,14 +71,14 @@ static const aiMatProp aiProps[] = { { AI_MATKEY_OPACITY }, /* m3dp_d */ { AI_MATKEY_SHADING_MODEL }, /* m3dp_il */ - { NULL, 0, 0 }, /* m3dp_Pr */ + { nullptr, 0, 0 }, /* m3dp_Pr */ { AI_MATKEY_REFLECTIVITY }, /* m3dp_Pm */ - { NULL, 0, 0 }, /* m3dp_Ps */ + { nullptr, 0, 0 }, /* m3dp_Ps */ { AI_MATKEY_REFRACTI }, /* m3dp_Ni */ - { NULL, 0, 0 }, /* m3dp_Nt */ - { NULL, 0, 0 }, - { NULL, 0, 0 }, - { NULL, 0, 0 } + { nullptr, 0, 0 }, /* m3dp_Nt */ + { nullptr, 0, 0 }, + { nullptr, 0, 0 }, + { nullptr, 0, 0 } }; /* --- Texture Map Properties --- !!!!! must match m3d_propertytypes !!!!! */ @@ -88,19 +88,19 @@ static const aiMatProp aiTxProps[] = { { AI_MATKEY_TEXTURE_SPECULAR(0) }, /* m3dp_map_Ks */ { AI_MATKEY_TEXTURE_SHININESS(0) }, /* m3dp_map_Ns */ { AI_MATKEY_TEXTURE_EMISSIVE(0) }, /* m3dp_map_Ke */ - { NULL, 0, 0 }, /* m3dp_map_Tf */ + { nullptr, 0, 0 }, /* m3dp_map_Tf */ { AI_MATKEY_TEXTURE_HEIGHT(0) }, /* m3dp_bump */ { AI_MATKEY_TEXTURE_OPACITY(0) }, /* m3dp_map_d */ { AI_MATKEY_TEXTURE_NORMALS(0) }, /* m3dp_map_N */ { AI_MATKEY_TEXTURE(aiTextureType_DIFFUSE_ROUGHNESS,0) },/* m3dp_map_Pr */ { AI_MATKEY_TEXTURE(aiTextureType_METALNESS,0) }, /* m3dp_map_Pm */ - { NULL, 0, 0 }, /* m3dp_map_Ps */ + { nullptr, 0, 0 }, /* m3dp_map_Ps */ { AI_MATKEY_TEXTURE(aiTextureType_REFLECTION,0) }, /* m3dp_map_Ni */ - { NULL, 0, 0 }, /* m3dp_map_Nt */ - { NULL, 0, 0 }, - { NULL, 0, 0 }, - { NULL, 0, 0 } + { nullptr, 0, 0 }, /* m3dp_map_Nt */ + { nullptr, 0, 0 }, + { nullptr, 0, 0 }, + { nullptr, 0, 0 } }; #endif // AI_M3DMATERIALS_H_INC diff --git a/code/AssetLib/M3D/M3DWrapper.cpp b/code/AssetLib/M3D/M3DWrapper.cpp index 98792217f..b72812377 100644 --- a/code/AssetLib/M3D/M3DWrapper.cpp +++ b/code/AssetLib/M3D/M3DWrapper.cpp @@ -72,7 +72,7 @@ unsigned char *m3dimporter_readfile(char *fn, unsigned int *size) { std::unique_ptr pStream( (reinterpret_cast(m3dimporter_pIOHandler))->Open(file, "rb")); size_t fileSize = 0; - unsigned char *data = NULL; + unsigned char *data = nullptr; // sometimes pStream is nullptr in a single-threaded scenario too for some reason // (should be an empty object returning nothing I guess) if (pStream) { diff --git a/code/AssetLib/M3D/m3d.h b/code/AssetLib/M3D/m3d.h index 75bcdfeb7..3d7a2564c 100644 --- a/code/AssetLib/M3D/m3d.h +++ b/code/AssetLib/M3D/m3d.h @@ -5071,7 +5071,7 @@ unsigned char *m3d_save(m3d_t *model, int quality, int flags, unsigned int *size ptr += sprintf(ptr, "\r\n"); } /* mathematical shapes face */ - if (model->numshape && model->numshape && !(flags & M3D_EXP_NOFACE)) { + if (model->numshape !(flags & M3D_EXP_NOFACE)) { for (j = 0; j < model->numshape; j++) { sn = _m3d_safestr(model->shape[j].name, 0); if (!sn) { diff --git a/code/AssetLib/MD2/MD2Loader.cpp b/code/AssetLib/MD2/MD2Loader.cpp index 473ab99bc..abc5f06ff 100644 --- a/code/AssetLib/MD2/MD2Loader.cpp +++ b/code/AssetLib/MD2/MD2Loader.cpp @@ -221,20 +221,21 @@ void MD2Importer::InternReadFile( const std::string& pFile, std::unique_ptr file( pIOHandler->Open( pFile)); // Check whether we can read from the file - if( file.get() == NULL) - throw DeadlyImportError( "Failed to open MD2 file " + pFile + ""); + if (file.get() == nullptr) { + throw DeadlyImportError("Failed to open MD2 file " + pFile + ""); + } // check whether the md3 file is large enough to contain // at least the file header fileSize = (unsigned int)file->FileSize(); - if( fileSize < sizeof(MD2::Header)) - throw DeadlyImportError( "MD2 File is too small"); + if (fileSize < sizeof(MD2::Header)) { + throw DeadlyImportError("MD2 File is too small"); + } std::vector mBuffer2(fileSize); file->Read(&mBuffer2[0], 1, fileSize); mBuffer = &mBuffer2[0]; - m_pcHeader = (BE_NCONST MD2::Header*)mBuffer; #ifdef AI_BUILD_BIG_ENDIAN diff --git a/code/AssetLib/MD3/MD3Loader.cpp b/code/AssetLib/MD3/MD3Loader.cpp index e8176865c..92d567801 100644 --- a/code/AssetLib/MD3/MD3Loader.cpp +++ b/code/AssetLib/MD3/MD3Loader.cpp @@ -50,21 +50,20 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * http://www.heppler.com/shader/shader/ */ - #ifndef ASSIMP_BUILD_NO_MD3_IMPORTER #include "AssetLib/MD3/MD3Loader.h" #include "Common/Importer.h" -#include #include -#include #include -#include -#include +#include +#include +#include #include #include -#include +#include +#include #include #include @@ -86,8 +85,7 @@ static const aiImporterDesc desc = { // ------------------------------------------------------------------------------------------------ // Convert a Q3 shader blend function to the appropriate enum value -Q3Shader::BlendFunc StringToBlendFunc(const std::string& m) -{ +Q3Shader::BlendFunc StringToBlendFunc(const std::string &m) { if (m == "GL_ONE") { return Q3Shader::BLEND_GL_ONE; } @@ -109,9 +107,8 @@ Q3Shader::BlendFunc StringToBlendFunc(const std::string& m) // ------------------------------------------------------------------------------------------------ // Load a Quake 3 shader -bool Q3Shader::LoadShader(ShaderData& fill, const std::string& pFile,IOSystem* io) -{ - std::unique_ptr file( io->Open( pFile, "rt")); +bool Q3Shader::LoadShader(ShaderData &fill, const std::string &pFile, IOSystem *io) { + std::unique_ptr file(io->Open(pFile, "rt")); if (!file.get()) return false; // if we can't access the file, don't worry and return @@ -119,19 +116,19 @@ bool Q3Shader::LoadShader(ShaderData& fill, const std::string& pFile,IOSystem* i // read file in memory const size_t s = file->FileSize(); - std::vector _buff(s+1); - file->Read(&_buff[0],s,1); + std::vector _buff(s + 1); + file->Read(&_buff[0], s, 1); _buff[s] = 0; // remove comments from it (C++ style) - CommentRemover::RemoveLineComments("//",&_buff[0]); - const char* buff = &_buff[0]; + CommentRemover::RemoveLineComments("//", &_buff[0]); + const char *buff = &_buff[0]; - Q3Shader::ShaderDataBlock* curData = NULL; - Q3Shader::ShaderMapBlock* curMap = NULL; + Q3Shader::ShaderDataBlock *curData = nullptr; + Q3Shader::ShaderMapBlock *curMap = nullptr; // read line per line - for (;SkipSpacesAndLineEnd(&buff);SkipLine(&buff)) { + for (; SkipSpacesAndLineEnd(&buff); SkipLine(&buff)) { if (*buff == '{') { ++buff; @@ -143,74 +140,67 @@ bool Q3Shader::LoadShader(ShaderData& fill, const std::string& pFile,IOSystem* i } // read this data section - for (;SkipSpacesAndLineEnd(&buff);SkipLine(&buff)) { + for (; SkipSpacesAndLineEnd(&buff); SkipLine(&buff)) { if (*buff == '{') { ++buff; // add new map section curData->maps.push_back(Q3Shader::ShaderMapBlock()); curMap = &curData->maps.back(); - for (;SkipSpacesAndLineEnd(&buff);SkipLine(&buff)) { + for (; SkipSpacesAndLineEnd(&buff); SkipLine(&buff)) { // 'map' - Specifies texture file name - if (TokenMatchI(buff,"map",3) || TokenMatchI(buff,"clampmap",8)) { + if (TokenMatchI(buff, "map", 3) || TokenMatchI(buff, "clampmap", 8)) { curMap->name = GetNextToken(buff); } // 'blendfunc' - Alpha blending mode - else if (TokenMatchI(buff,"blendfunc",9)) { + else if (TokenMatchI(buff, "blendfunc", 9)) { const std::string blend_src = GetNextToken(buff); if (blend_src == "add") { - curMap->blend_src = Q3Shader::BLEND_GL_ONE; + curMap->blend_src = Q3Shader::BLEND_GL_ONE; curMap->blend_dest = Q3Shader::BLEND_GL_ONE; - } - else if (blend_src == "filter") { - curMap->blend_src = Q3Shader::BLEND_GL_DST_COLOR; + } else if (blend_src == "filter") { + curMap->blend_src = Q3Shader::BLEND_GL_DST_COLOR; curMap->blend_dest = Q3Shader::BLEND_GL_ZERO; - } - else if (blend_src == "blend") { - curMap->blend_src = Q3Shader::BLEND_GL_SRC_ALPHA; + } else if (blend_src == "blend") { + curMap->blend_src = Q3Shader::BLEND_GL_SRC_ALPHA; curMap->blend_dest = Q3Shader::BLEND_GL_ONE_MINUS_SRC_ALPHA; - } - else { - curMap->blend_src = StringToBlendFunc(blend_src); + } else { + curMap->blend_src = StringToBlendFunc(blend_src); curMap->blend_dest = StringToBlendFunc(GetNextToken(buff)); } } // 'alphafunc' - Alpha testing mode - else if (TokenMatchI(buff,"alphafunc",9)) { + else if (TokenMatchI(buff, "alphafunc", 9)) { const std::string at = GetNextToken(buff); if (at == "GT0") { curMap->alpha_test = Q3Shader::AT_GT0; - } - else if (at == "LT128") { + } else if (at == "LT128") { curMap->alpha_test = Q3Shader::AT_LT128; - } - else if (at == "GE128") { + } else if (at == "GE128") { curMap->alpha_test = Q3Shader::AT_GE128; } - } - else if (*buff == '}') { + } else if (*buff == '}') { ++buff; // close this map section - curMap = NULL; + curMap = nullptr; break; } } - } - else if (*buff == '}') { + } else if (*buff == '}') { ++buff; - curData = NULL; + curData = nullptr; break; } // 'cull' specifies culling behaviour for the model - else if (TokenMatchI(buff,"cull",4)) { + else if (TokenMatchI(buff, "cull", 4)) { SkipSpaces(&buff); - if (!ASSIMP_strincmp(buff,"back",4)) { + if (!ASSIMP_strincmp(buff, "back", 4)) { curData->cull = Q3Shader::CULL_CCW; - } else if (!ASSIMP_strincmp(buff,"front",5)) { + } else if (!ASSIMP_strincmp(buff, "front", 5)) { curData->cull = Q3Shader::CULL_CW; - } else if (!ASSIMP_strincmp(buff,"none",4) || !ASSIMP_strincmp(buff,"disable",7)) { + } else if (!ASSIMP_strincmp(buff, "none", 4) || !ASSIMP_strincmp(buff, "disable", 7)) { curData->cull = Q3Shader::CULL_NONE; } else { ASSIMP_LOG_ERROR("Q3Shader: Unrecognized cull mode"); @@ -231,9 +221,8 @@ bool Q3Shader::LoadShader(ShaderData& fill, const std::string& pFile,IOSystem* i // ------------------------------------------------------------------------------------------------ // Load a Quake 3 skin -bool Q3Shader::LoadSkin(SkinData& fill, const std::string& pFile,IOSystem* io) -{ - std::unique_ptr file( io->Open( pFile, "rt")); +bool Q3Shader::LoadSkin(SkinData &fill, const std::string &pFile, IOSystem *io) { + std::unique_ptr file(io->Open(pFile, "rt")); if (!file.get()) return false; // if we can't access the file, don't worry and return @@ -241,28 +230,29 @@ bool Q3Shader::LoadSkin(SkinData& fill, const std::string& pFile,IOSystem* io) // read file in memory const size_t s = file->FileSize(); - std::vector _buff(s+1);const char* buff = &_buff[0]; - file->Read(&_buff[0],s,1); + std::vector _buff(s + 1); + const char *buff = &_buff[0]; + file->Read(&_buff[0], s, 1); _buff[s] = 0; // remove commas - std::replace(_buff.begin(),_buff.end(),',',' '); + std::replace(_buff.begin(), _buff.end(), ',', ' '); // read token by token and fill output table - for (;*buff;) { + for (; *buff;) { SkipSpacesAndLineEnd(&buff); // get first identifier std::string ss = GetNextToken(buff); // ignore tokens starting with tag_ - if (!::strncmp(&ss[0],"tag_",std::min((size_t)4, ss.length()))) + if (!::strncmp(&ss[0], "tag_", std::min((size_t)4, ss.length()))) continue; fill.textures.push_back(SkinData::TextureEntry()); SkinData::TextureEntry &entry = fill.textures.back(); - entry.first = ss; + entry.first = ss; entry.second = GetNextToken(buff); } return true; @@ -270,9 +260,8 @@ bool Q3Shader::LoadSkin(SkinData& fill, const std::string& pFile,IOSystem* io) // ------------------------------------------------------------------------------------------------ // Convert Q3Shader to material -void Q3Shader::ConvertShaderToMaterial(aiMaterial* out, const ShaderDataBlock& shader) -{ - ai_assert(NULL != out); +void Q3Shader::ConvertShaderToMaterial(aiMaterial *out, const ShaderDataBlock &shader) { + ai_assert(nullptr != out); /* IMPORTANT: This is not a real conversion. Actually we're just guessing and * hacking around to build an aiMaterial that looks nearly equal to the @@ -284,13 +273,13 @@ void Q3Shader::ConvertShaderToMaterial(aiMaterial* out, const ShaderDataBlock& s // Two-sided material? if (shader.cull == Q3Shader::CULL_NONE) { const int twosided = 1; - out->AddProperty(&twosided,1,AI_MATKEY_TWOSIDED); + out->AddProperty(&twosided, 1, AI_MATKEY_TWOSIDED); } - unsigned int cur_emissive = 0, cur_diffuse = 0, cur_lm =0; + unsigned int cur_emissive = 0, cur_diffuse = 0, cur_lm = 0; // Iterate through all textures - for (std::list< Q3Shader::ShaderMapBlock >::const_iterator it = shader.maps.begin(); it != shader.maps.end();++it) { + for (std::list::const_iterator it = shader.maps.begin(); it != shader.maps.end(); ++it) { // CONVERSION BEHAVIOUR: // @@ -309,70 +298,58 @@ void Q3Shader::ConvertShaderToMaterial(aiMaterial* out, const ShaderDataBlock& s // Textures with alpha funcs // - aiTextureFlags_UseAlpha is set (otherwise aiTextureFlags_NoAlpha is explicitly set) aiString s((*it).name); - aiTextureType type; unsigned int index; + aiTextureType type; + unsigned int index; if ((*it).blend_src == Q3Shader::BLEND_GL_ONE && (*it).blend_dest == Q3Shader::BLEND_GL_ONE) { if (it == shader.maps.begin()) { const int additive = aiBlendMode_Additive; - out->AddProperty(&additive,1,AI_MATKEY_BLEND_FUNC); + out->AddProperty(&additive, 1, AI_MATKEY_BLEND_FUNC); index = cur_diffuse++; - type = aiTextureType_DIFFUSE; - } - else { + type = aiTextureType_DIFFUSE; + } else { index = cur_emissive++; - type = aiTextureType_EMISSIVE; + type = aiTextureType_EMISSIVE; } - } - else if ((*it).blend_src == Q3Shader::BLEND_GL_DST_COLOR && (*it).blend_dest == Q3Shader::BLEND_GL_ZERO) { + } else if ((*it).blend_src == Q3Shader::BLEND_GL_DST_COLOR && (*it).blend_dest == Q3Shader::BLEND_GL_ZERO) { index = cur_lm++; - type = aiTextureType_LIGHTMAP; - } - else { + type = aiTextureType_LIGHTMAP; + } else { const int blend = aiBlendMode_Default; - out->AddProperty(&blend,1,AI_MATKEY_BLEND_FUNC); + out->AddProperty(&blend, 1, AI_MATKEY_BLEND_FUNC); index = cur_diffuse++; - type = aiTextureType_DIFFUSE; + type = aiTextureType_DIFFUSE; } // setup texture - out->AddProperty(&s,AI_MATKEY_TEXTURE(type,index)); + out->AddProperty(&s, AI_MATKEY_TEXTURE(type, index)); // setup texture flags const int use_alpha = ((*it).alpha_test != Q3Shader::AT_NONE ? aiTextureFlags_UseAlpha : aiTextureFlags_IgnoreAlpha); - out->AddProperty(&use_alpha,1,AI_MATKEY_TEXFLAGS(type,index)); + out->AddProperty(&use_alpha, 1, AI_MATKEY_TEXFLAGS(type, index)); } // If at least one emissive texture was set, set the emissive base color to 1 to ensure // the texture is actually displayed. if (0 != cur_emissive) { - aiColor3D one(1.f,1.f,1.f); - out->AddProperty(&one,1,AI_MATKEY_COLOR_EMISSIVE); + aiColor3D one(1.f, 1.f, 1.f); + out->AddProperty(&one, 1, AI_MATKEY_COLOR_EMISSIVE); } } // ------------------------------------------------------------------------------------------------ // Constructor to be privately used by Importer -MD3Importer::MD3Importer() - : configFrameID (0) - , configHandleMP (true) - , configSpeedFlag() - , pcHeader() - , mBuffer() - , fileSize() - , mScene() - , mIOHandler() -{} +MD3Importer::MD3Importer() : + configFrameID(0), configHandleMP(true), configSpeedFlag(), pcHeader(), mBuffer(), fileSize(), mScene(), mIOHandler() {} // ------------------------------------------------------------------------------------------------ // Destructor, private as well -MD3Importer::~MD3Importer() -{} +MD3Importer::~MD3Importer() {} // ------------------------------------------------------------------------------------------------ // Returns whether the class can handle the format of the given file. -bool MD3Importer::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const -{ +bool MD3Importer::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const { const std::string extension = GetExtension(pFile); if (extension == "md3") return true; @@ -381,55 +358,53 @@ bool MD3Importer::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool if (!extension.length() || checkSig) { uint32_t tokens[1]; tokens[0] = AI_MD3_MAGIC_NUMBER_LE; - return CheckMagicToken(pIOHandler,pFile,tokens,1); + return CheckMagicToken(pIOHandler, pFile, tokens, 1); } return false; } // ------------------------------------------------------------------------------------------------ -void MD3Importer::ValidateHeaderOffsets() -{ +void MD3Importer::ValidateHeaderOffsets() { // Check magic number if (pcHeader->IDENT != AI_MD3_MAGIC_NUMBER_BE && - pcHeader->IDENT != AI_MD3_MAGIC_NUMBER_LE) - throw DeadlyImportError( "Invalid MD3 file: Magic bytes not found"); + pcHeader->IDENT != AI_MD3_MAGIC_NUMBER_LE) + throw DeadlyImportError("Invalid MD3 file: Magic bytes not found"); // Check file format version if (pcHeader->VERSION > 15) - ASSIMP_LOG_WARN( "Unsupported MD3 file version. Continuing happily ..."); + ASSIMP_LOG_WARN("Unsupported MD3 file version. Continuing happily ..."); // Check some offset values whether they are valid if (!pcHeader->NUM_SURFACES) - throw DeadlyImportError( "Invalid md3 file: NUM_SURFACES is 0"); + throw DeadlyImportError("Invalid md3 file: NUM_SURFACES is 0"); if (pcHeader->OFS_FRAMES >= fileSize || pcHeader->OFS_SURFACES >= fileSize || - pcHeader->OFS_EOF > fileSize) { + pcHeader->OFS_EOF > fileSize) { throw DeadlyImportError("Invalid MD3 header: some offsets are outside the file"); } - if (pcHeader->NUM_SURFACES > AI_MAX_ALLOC(MD3::Surface)) { + if (pcHeader->NUM_SURFACES > AI_MAX_ALLOC(MD3::Surface)) { throw DeadlyImportError("Invalid MD3 header: too many surfaces, would overflow"); - } + } if (pcHeader->OFS_SURFACES + pcHeader->NUM_SURFACES * sizeof(MD3::Surface) >= fileSize) { throw DeadlyImportError("Invalid MD3 header: some surfaces are outside the file"); } - if (pcHeader->NUM_FRAMES <= configFrameID ) + if (pcHeader->NUM_FRAMES <= configFrameID) throw DeadlyImportError("The requested frame is not existing the file"); } // ------------------------------------------------------------------------------------------------ -void MD3Importer::ValidateSurfaceHeaderOffsets(const MD3::Surface* pcSurf) -{ +void MD3Importer::ValidateSurfaceHeaderOffsets(const MD3::Surface *pcSurf) { // Calculate the relative offset of the surface - const int32_t ofs = int32_t((const unsigned char*)pcSurf-this->mBuffer); + const int32_t ofs = int32_t((const unsigned char *)pcSurf - this->mBuffer); // Check whether all data chunks are inside the valid range - if (pcSurf->OFS_TRIANGLES + ofs + pcSurf->NUM_TRIANGLES * sizeof(MD3::Triangle) > fileSize || - pcSurf->OFS_SHADERS + ofs + pcSurf->NUM_SHADER * sizeof(MD3::Shader) > fileSize || - pcSurf->OFS_ST + ofs + pcSurf->NUM_VERTICES * sizeof(MD3::TexCoord) > fileSize || - pcSurf->OFS_XYZNORMAL + ofs + pcSurf->NUM_VERTICES * sizeof(MD3::Vertex) > fileSize) { + if (pcSurf->OFS_TRIANGLES + ofs + pcSurf->NUM_TRIANGLES * sizeof(MD3::Triangle) > fileSize || + pcSurf->OFS_SHADERS + ofs + pcSurf->NUM_SHADER * sizeof(MD3::Shader) > fileSize || + pcSurf->OFS_ST + ofs + pcSurf->NUM_VERTICES * sizeof(MD3::TexCoord) > fileSize || + pcSurf->OFS_XYZNORMAL + ofs + pcSurf->NUM_VERTICES * sizeof(MD3::Vertex) > fileSize) { throw DeadlyImportError("Invalid MD3 surface header: some offsets are outside the file"); } @@ -454,39 +429,37 @@ void MD3Importer::ValidateSurfaceHeaderOffsets(const MD3::Surface* pcSurf) } // ------------------------------------------------------------------------------------------------ -const aiImporterDesc* MD3Importer::GetInfo () const { +const aiImporterDesc *MD3Importer::GetInfo() const { return &desc; } // ------------------------------------------------------------------------------------------------ // Setup configuration properties -void MD3Importer::SetupProperties(const Importer* pImp) -{ +void MD3Importer::SetupProperties(const Importer *pImp) { // The // AI_CONFIG_IMPORT_MD3_KEYFRAME option overrides the // AI_CONFIG_IMPORT_GLOBAL_KEYFRAME option. - configFrameID = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_MD3_KEYFRAME,-1); - if(static_cast(-1) == configFrameID) { - configFrameID = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_GLOBAL_KEYFRAME,0); + configFrameID = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_MD3_KEYFRAME, -1); + if (static_cast(-1) == configFrameID) { + configFrameID = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_GLOBAL_KEYFRAME, 0); } // AI_CONFIG_IMPORT_MD3_HANDLE_MULTIPART - configHandleMP = (0 != pImp->GetPropertyInteger(AI_CONFIG_IMPORT_MD3_HANDLE_MULTIPART,1)); + configHandleMP = (0 != pImp->GetPropertyInteger(AI_CONFIG_IMPORT_MD3_HANDLE_MULTIPART, 1)); // AI_CONFIG_IMPORT_MD3_SKIN_NAME - configSkinFile = (pImp->GetPropertyString(AI_CONFIG_IMPORT_MD3_SKIN_NAME,"default")); + configSkinFile = (pImp->GetPropertyString(AI_CONFIG_IMPORT_MD3_SKIN_NAME, "default")); // AI_CONFIG_IMPORT_MD3_SHADER_SRC - configShaderFile = (pImp->GetPropertyString(AI_CONFIG_IMPORT_MD3_SHADER_SRC,"")); + configShaderFile = (pImp->GetPropertyString(AI_CONFIG_IMPORT_MD3_SHADER_SRC, "")); // AI_CONFIG_FAVOUR_SPEED - configSpeedFlag = (0 != pImp->GetPropertyInteger(AI_CONFIG_FAVOUR_SPEED,0)); + configSpeedFlag = (0 != pImp->GetPropertyInteger(AI_CONFIG_FAVOUR_SPEED, 0)); } // ------------------------------------------------------------------------------------------------ // Try to read the skin for a MD3 file -void MD3Importer::ReadSkin(Q3Shader::SkinData& fill) const -{ +void MD3Importer::ReadSkin(Q3Shader::SkinData &fill) const { // skip any postfixes (e.g. lower_1.md3) std::string::size_type s = filename.find_last_of('_'); if (s == std::string::npos) { @@ -497,51 +470,47 @@ void MD3Importer::ReadSkin(Q3Shader::SkinData& fill) const } ai_assert(s != std::string::npos); - const std::string skin_file = path + filename.substr(0,s) + "_" + configSkinFile + ".skin"; - Q3Shader::LoadSkin(fill,skin_file,mIOHandler); + const std::string skin_file = path + filename.substr(0, s) + "_" + configSkinFile + ".skin"; + Q3Shader::LoadSkin(fill, skin_file, mIOHandler); } // ------------------------------------------------------------------------------------------------ // Try to read the shader for a MD3 file -void MD3Importer::ReadShader(Q3Shader::ShaderData& fill) const -{ +void MD3Importer::ReadShader(Q3Shader::ShaderData &fill) const { // Determine Q3 model name from given path - const std::string::size_type s = path.find_last_of("\\/",path.length()-2); - const std::string model_file = path.substr(s+1,path.length()-(s+2)); + const std::string::size_type s = path.find_last_of("\\/", path.length() - 2); + const std::string model_file = path.substr(s + 1, path.length() - (s + 2)); // If no specific dir or file is given, use our default search behaviour if (!configShaderFile.length()) { - if(!Q3Shader::LoadShader(fill,path + "..\\..\\..\\scripts\\" + model_file + ".shader",mIOHandler)) { - Q3Shader::LoadShader(fill,path + "..\\..\\..\\scripts\\" + filename + ".shader",mIOHandler); + if (!Q3Shader::LoadShader(fill, path + "..\\..\\..\\scripts\\" + model_file + ".shader", mIOHandler)) { + Q3Shader::LoadShader(fill, path + "..\\..\\..\\scripts\\" + filename + ".shader", mIOHandler); } - } - else { + } else { // If the given string specifies a file, load this file. // Otherwise it's a directory. const std::string::size_type st = configShaderFile.find_last_of('.'); if (st == std::string::npos) { - if(!Q3Shader::LoadShader(fill,configShaderFile + model_file + ".shader",mIOHandler)) { - Q3Shader::LoadShader(fill,configShaderFile + filename + ".shader",mIOHandler); + if (!Q3Shader::LoadShader(fill, configShaderFile + model_file + ".shader", mIOHandler)) { + Q3Shader::LoadShader(fill, configShaderFile + filename + ".shader", mIOHandler); } - } - else { - Q3Shader::LoadShader(fill,configShaderFile,mIOHandler); + } else { + Q3Shader::LoadShader(fill, configShaderFile, mIOHandler); } } } // ------------------------------------------------------------------------------------------------ // Tiny helper to remove a single node from its parent' list -void RemoveSingleNodeFromList(aiNode* nd) -{ - if (!nd || nd->mNumChildren || !nd->mParent)return; - aiNode* par = nd->mParent; - for (unsigned int i = 0; i < par->mNumChildren;++i) { +void RemoveSingleNodeFromList(aiNode *nd) { + if (!nd || nd->mNumChildren || !nd->mParent) return; + aiNode *par = nd->mParent; + for (unsigned int i = 0; i < par->mNumChildren; ++i) { if (par->mChildren[i] == nd) { --par->mNumChildren; - for (;i < par->mNumChildren;++i) { - par->mChildren[i] = par->mChildren[i+1]; + for (; i < par->mNumChildren; ++i) { + par->mChildren[i] = par->mChildren[i + 1]; } delete nd; break; @@ -551,8 +520,7 @@ void RemoveSingleNodeFromList(aiNode* nd) // ------------------------------------------------------------------------------------------------ // Read a multi-part Q3 player model -bool MD3Importer::ReadMultipartFile() -{ +bool MD3Importer::ReadMultipartFile() { // check whether the file name contains a common postfix, e.g lower_2.md3 std::string::size_type s = filename.find_last_of('_'), t = filename.find_last_of('.'); @@ -561,38 +529,38 @@ bool MD3Importer::ReadMultipartFile() if (s == std::string::npos) s = t; - const std::string mod_filename = filename.substr(0,s); - const std::string suffix = filename.substr(s,t-s); + const std::string mod_filename = filename.substr(0, s); + const std::string suffix = filename.substr(s, t - s); - if (mod_filename == "lower" || mod_filename == "upper" || mod_filename == "head"){ + if (mod_filename == "lower" || mod_filename == "upper" || mod_filename == "head") { const std::string lower = path + "lower" + suffix + ".md3"; const std::string upper = path + "upper" + suffix + ".md3"; - const std::string head = path + "head" + suffix + ".md3"; + const std::string head = path + "head" + suffix + ".md3"; - aiScene* scene_upper = NULL; - aiScene* scene_lower = NULL; - aiScene* scene_head = NULL; + aiScene *scene_upper = nullptr; + aiScene *scene_lower = nullptr; + aiScene *scene_head = nullptr; std::string failure; - aiNode* tag_torso, *tag_head; + aiNode *tag_torso, *tag_head; std::vector attach; ASSIMP_LOG_INFO("Multi part MD3 player model: lower, upper and head parts are joined"); // ensure we won't try to load ourselves recursively BatchLoader::PropertyMap props; - SetGenericProperty( props.ints, AI_CONFIG_IMPORT_MD3_HANDLE_MULTIPART, 0); + SetGenericProperty(props.ints, AI_CONFIG_IMPORT_MD3_HANDLE_MULTIPART, 0); // now read these three files BatchLoader batch(mIOHandler); - const unsigned int _lower = batch.AddLoadRequest(lower,0,&props); - const unsigned int _upper = batch.AddLoadRequest(upper,0,&props); - const unsigned int _head = batch.AddLoadRequest(head,0,&props); + const unsigned int _lower = batch.AddLoadRequest(lower, 0, &props); + const unsigned int _upper = batch.AddLoadRequest(upper, 0, &props); + const unsigned int _head = batch.AddLoadRequest(head, 0, &props); batch.LoadAll(); // now construct a dummy scene to place these three parts in - aiScene* master = new aiScene(); - aiNode* nd = master->mRootNode = new aiNode(); + aiScene *master = new aiScene(); + aiNode *nd = master->mRootNode = new aiNode(); nd->mName.Set(""); // ... and get them. We need all of them. @@ -610,7 +578,7 @@ bool MD3Importer::ReadMultipartFile() goto error_cleanup; } - scene_head = batch.GetImport(_head); + scene_head = batch.GetImport(_head); if (!scene_head) { ASSIMP_LOG_ERROR("M3D: Failed to read multi part model, head.md3 fails to load"); failure = "head"; @@ -630,43 +598,43 @@ bool MD3Importer::ReadMultipartFile() goto error_cleanup; } scene_upper->mRootNode->mName.Set("upper"); - attach.push_back(AttachmentInfo(scene_upper,tag_torso)); + attach.push_back(AttachmentInfo(scene_upper, tag_torso)); // tag_head tag_head = scene_upper->mRootNode->FindNode("tag_head"); if (!tag_head) { - ASSIMP_LOG_ERROR( "M3D: Failed to find attachment tag for multi part model: tag_head expected"); + ASSIMP_LOG_ERROR("M3D: Failed to find attachment tag for multi part model: tag_head expected"); goto error_cleanup; } scene_head->mRootNode->mName.Set("head"); - attach.push_back(AttachmentInfo(scene_head,tag_head)); + attach.push_back(AttachmentInfo(scene_head, tag_head)); // Remove tag_head and tag_torso from all other model parts ... // this ensures (together with AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES_IF_NECESSARY) // that tag_torso/tag_head is also the name of the (unique) output node - RemoveSingleNodeFromList (scene_upper->mRootNode->FindNode("tag_torso")); - RemoveSingleNodeFromList (scene_head-> mRootNode->FindNode("tag_head" )); + RemoveSingleNodeFromList(scene_upper->mRootNode->FindNode("tag_torso")); + RemoveSingleNodeFromList(scene_head->mRootNode->FindNode("tag_head")); // Undo the rotations which we applied to the coordinate systems. We're // working in global Quake space here - scene_head->mRootNode->mTransformation = aiMatrix4x4(); + scene_head->mRootNode->mTransformation = aiMatrix4x4(); scene_lower->mRootNode->mTransformation = aiMatrix4x4(); scene_upper->mRootNode->mTransformation = aiMatrix4x4(); // and merge the scenes - SceneCombiner::MergeScenes(&mScene,master, attach, - AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES | - AI_INT_MERGE_SCENE_GEN_UNIQUE_MATNAMES | - AI_INT_MERGE_SCENE_RESOLVE_CROSS_ATTACHMENTS | - (!configSpeedFlag ? AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES_IF_NECESSARY : 0)); + SceneCombiner::MergeScenes(&mScene, master, attach, + AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES | + AI_INT_MERGE_SCENE_GEN_UNIQUE_MATNAMES | + AI_INT_MERGE_SCENE_RESOLVE_CROSS_ATTACHMENTS | + (!configSpeedFlag ? AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES_IF_NECESSARY : 0)); // Now rotate the whole scene 90 degrees around the x axis to convert to internal coordinate system - mScene->mRootNode->mTransformation = aiMatrix4x4(1.f,0.f,0.f,0.f, - 0.f,0.f,1.f,0.f,0.f,-1.f,0.f,0.f,0.f,0.f,0.f,1.f); + mScene->mRootNode->mTransformation = aiMatrix4x4(1.f, 0.f, 0.f, 0.f, + 0.f, 0.f, 1.f, 0.f, 0.f, -1.f, 0.f, 0.f, 0.f, 0.f, 0.f, 1.f); return true; -error_cleanup: + error_cleanup: delete scene_upper; delete scene_lower; delete scene_head; @@ -681,36 +649,35 @@ error_cleanup: // ------------------------------------------------------------------------------------------------ // Convert a MD3 path to a proper value -void MD3Importer::ConvertPath(const char* texture_name, const char* header_name, std::string& out) const -{ +void MD3Importer::ConvertPath(const char *texture_name, const char *header_name, std::string &out) const { // If the MD3's internal path itself and the given path are using // the same directory, remove it completely to get right output paths. - const char* end1 = ::strrchr(header_name,'\\'); - if (!end1)end1 = ::strrchr(header_name,'/'); + const char *end1 = ::strrchr(header_name, '\\'); + if (!end1) end1 = ::strrchr(header_name, '/'); - const char* end2 = ::strrchr(texture_name,'\\'); - if (!end2)end2 = ::strrchr(texture_name,'/'); + const char *end2 = ::strrchr(texture_name, '\\'); + if (!end2) end2 = ::strrchr(texture_name, '/'); // HACK: If the paths starts with "models", ignore the // next two hierarchy levels, it specifies just the model name. // Ignored by Q3, it might be not equal to the real model location. - if (end2) { + if (end2) { size_t len2; const size_t len1 = (size_t)(end1 - header_name); - if (!ASSIMP_strincmp(texture_name,"models",6) && (texture_name[6] == '/' || texture_name[6] == '\\')) { + if (!ASSIMP_strincmp(texture_name, "models", 6) && (texture_name[6] == '/' || texture_name[6] == '\\')) { len2 = 6; // ignore the seventh - could be slash or backslash if (!header_name[0]) { // Use the file name only - out = end2+1; + out = end2 + 1; return; } - } - else len2 = std::min (len1, (size_t)(end2 - texture_name )); - if (!ASSIMP_strincmp(texture_name,header_name,static_cast(len2))) { + } else + len2 = std::min(len1, (size_t)(end2 - texture_name)); + if (!ASSIMP_strincmp(texture_name, header_name, static_cast(len2))) { // Use the file name only - out = end2+1; + out = end2 + 1; return; } } @@ -720,7 +687,7 @@ void MD3Importer::ConvertPath(const char* texture_name, const char* header_name, // ------------------------------------------------------------------------------------------------ // Imports the given file into the given scene structure. -void MD3Importer::InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler) { +void MD3Importer::InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler) { mFile = pFile; mScene = pScene; mIOHandler = pIOHandler; @@ -735,7 +702,7 @@ void MD3Importer::InternReadFile( const std::string& pFile, aiScene* pScene, IOS } filename = mFile.substr(s), path = mFile.substr(0, s); for (std::string::iterator it = filename.begin(); it != filename.end(); ++it) { - *it = static_cast( tolower(*it) ); + *it = static_cast(tolower(*it)); } // Load multi-part model file, if necessary @@ -744,23 +711,24 @@ void MD3Importer::InternReadFile( const std::string& pFile, aiScene* pScene, IOS return; } - std::unique_ptr file( pIOHandler->Open( pFile)); + std::unique_ptr file(pIOHandler->Open(pFile)); // Check whether we can read from the file - if( file.get() == NULL) - throw DeadlyImportError( "Failed to open MD3 file " + pFile + "."); + if (file.get() == nullptr) { + throw DeadlyImportError("Failed to open MD3 file " + pFile + "."); + } // Check whether the md3 file is large enough to contain the header fileSize = (unsigned int)file->FileSize(); - if( fileSize < sizeof(MD3::Header)) - throw DeadlyImportError( "MD3 File is too small."); + if (fileSize < sizeof(MD3::Header)) + throw DeadlyImportError("MD3 File is too small."); // Allocate storage and copy the contents of the file to a memory buffer - std::vector mBuffer2 (fileSize); - file->Read( &mBuffer2[0], 1, fileSize); + std::vector mBuffer2(fileSize); + file->Read(&mBuffer2[0], 1, fileSize); mBuffer = &mBuffer2[0]; - pcHeader = (BE_NCONST MD3::Header*)mBuffer; + pcHeader = (BE_NCONST MD3::Header *)mBuffer; // Ensure correct endianness #ifdef AI_BUILD_BIG_ENDIAN @@ -783,10 +751,10 @@ void MD3Importer::InternReadFile( const std::string& pFile, aiScene* pScene, IOS ValidateHeaderOffsets(); // Navigate to the list of surfaces - BE_NCONST MD3::Surface* pcSurfaces = (BE_NCONST MD3::Surface*)(mBuffer + pcHeader->OFS_SURFACES); + BE_NCONST MD3::Surface *pcSurfaces = (BE_NCONST MD3::Surface *)(mBuffer + pcHeader->OFS_SURFACES); // Navigate to the list of tags - BE_NCONST MD3::Tag* pcTags = (BE_NCONST MD3::Tag*)(mBuffer + pcHeader->OFS_TAGS); + BE_NCONST MD3::Tag *pcTags = (BE_NCONST MD3::Tag *)(mBuffer + pcHeader->OFS_TAGS); // Allocate output storage pScene->mNumMeshes = pcHeader->NUM_SURFACES; @@ -797,14 +765,14 @@ void MD3Importer::InternReadFile( const std::string& pFile, aiScene* pScene, IOS // since those pointers will eventually have to point to real objects throw DeadlyImportError("MD3: Too many surfaces, would run out of memory"); } - pScene->mMeshes = new aiMesh*[pScene->mNumMeshes]; + pScene->mMeshes = new aiMesh *[pScene->mNumMeshes]; pScene->mNumMaterials = pcHeader->NUM_SURFACES; - pScene->mMaterials = new aiMaterial*[pScene->mNumMeshes]; + pScene->mMaterials = new aiMaterial *[pScene->mNumMeshes]; // Set arrays to zero to ensue proper destruction if an exception is raised - ::memset(pScene->mMeshes,0,pScene->mNumMeshes*sizeof(aiMesh*)); - ::memset(pScene->mMaterials,0,pScene->mNumMaterials*sizeof(aiMaterial*)); + ::memset(pScene->mMeshes, 0, pScene->mNumMeshes * sizeof(aiMesh *)); + ::memset(pScene->mMaterials, 0, pScene->mNumMaterials * sizeof(aiMaterial *)); // Now read possible skins from .skin file Q3Shader::SkinData skins; @@ -815,13 +783,13 @@ void MD3Importer::InternReadFile( const std::string& pFile, aiScene* pScene, IOS ReadShader(shaders); // Adjust all texture paths in the shader - const char* header_name = pcHeader->NAME; + const char *header_name = pcHeader->NAME; if (!shaders.blocks.empty()) { - for (std::list< Q3Shader::ShaderDataBlock >::iterator dit = shaders.blocks.begin(); dit != shaders.blocks.end(); ++dit) { - ConvertPath((*dit).name.c_str(),header_name,(*dit).name); + for (std::list::iterator dit = shaders.blocks.begin(); dit != shaders.blocks.end(); ++dit) { + ConvertPath((*dit).name.c_str(), header_name, (*dit).name); - for (std::list< Q3Shader::ShaderMapBlock >::iterator mit = (*dit).maps.begin(); mit != (*dit).maps.end(); ++mit) { - ConvertPath((*mit).name.c_str(),header_name,(*mit).name); + for (std::list::iterator mit = (*dit).maps.begin(); mit != (*dit).maps.end(); ++mit) { + ConvertPath((*mit).name.c_str(), header_name, (*mit).name); } } } @@ -829,7 +797,7 @@ void MD3Importer::InternReadFile( const std::string& pFile, aiScene* pScene, IOS // Read all surfaces from the file unsigned int iNum = pcHeader->NUM_SURFACES; unsigned int iNumMaterials = 0; - while (iNum-- > 0) { + while (iNum-- > 0) { // Ensure correct endianness #ifdef AI_BUILD_BIG_ENDIAN @@ -852,57 +820,52 @@ void MD3Importer::InternReadFile( const std::string& pFile, aiScene* pScene, IOS ValidateSurfaceHeaderOffsets(pcSurfaces); // Navigate to the vertex list of the surface - BE_NCONST MD3::Vertex* pcVertices = (BE_NCONST MD3::Vertex*) - (((uint8_t*)pcSurfaces) + pcSurfaces->OFS_XYZNORMAL); + BE_NCONST MD3::Vertex *pcVertices = (BE_NCONST MD3::Vertex *)(((uint8_t *)pcSurfaces) + pcSurfaces->OFS_XYZNORMAL); // Navigate to the triangle list of the surface - BE_NCONST MD3::Triangle* pcTriangles = (BE_NCONST MD3::Triangle*) - (((uint8_t*)pcSurfaces) + pcSurfaces->OFS_TRIANGLES); + BE_NCONST MD3::Triangle *pcTriangles = (BE_NCONST MD3::Triangle *)(((uint8_t *)pcSurfaces) + pcSurfaces->OFS_TRIANGLES); // Navigate to the texture coordinate list of the surface - BE_NCONST MD3::TexCoord* pcUVs = (BE_NCONST MD3::TexCoord*) - (((uint8_t*)pcSurfaces) + pcSurfaces->OFS_ST); + BE_NCONST MD3::TexCoord *pcUVs = (BE_NCONST MD3::TexCoord *)(((uint8_t *)pcSurfaces) + pcSurfaces->OFS_ST); // Navigate to the shader list of the surface - BE_NCONST MD3::Shader* pcShaders = (BE_NCONST MD3::Shader*) - (((uint8_t*)pcSurfaces) + pcSurfaces->OFS_SHADERS); + BE_NCONST MD3::Shader *pcShaders = (BE_NCONST MD3::Shader *)(((uint8_t *)pcSurfaces) + pcSurfaces->OFS_SHADERS); // If the submesh is empty ignore it - if (0 == pcSurfaces->NUM_VERTICES || 0 == pcSurfaces->NUM_TRIANGLES) - { - pcSurfaces = (BE_NCONST MD3::Surface*)(((uint8_t*)pcSurfaces) + pcSurfaces->OFS_END); + if (0 == pcSurfaces->NUM_VERTICES || 0 == pcSurfaces->NUM_TRIANGLES) { + pcSurfaces = (BE_NCONST MD3::Surface *)(((uint8_t *)pcSurfaces) + pcSurfaces->OFS_END); pScene->mNumMeshes--; continue; } // Allocate output mesh pScene->mMeshes[iNum] = new aiMesh(); - aiMesh* pcMesh = pScene->mMeshes[iNum]; + aiMesh *pcMesh = pScene->mMeshes[iNum]; std::string _texture_name; - const char* texture_name = NULL; + const char *texture_name = nullptr; // Check whether we have a texture record for this surface in the .skin file - std::list< Q3Shader::SkinData::TextureEntry >::iterator it = std::find( - skins.textures.begin(), skins.textures.end(), pcSurfaces->NAME ); + std::list::iterator it = std::find( + skins.textures.begin(), skins.textures.end(), pcSurfaces->NAME); if (it != skins.textures.end()) { - texture_name = &*( _texture_name = (*it).second).begin(); + texture_name = &*(_texture_name = (*it).second).begin(); ASSIMP_LOG_VERBOSE_DEBUG_F("MD3: Assigning skin texture ", (*it).second, " to surface ", pcSurfaces->NAME); (*it).resolved = true; // mark entry as resolved } // Get the first shader (= texture?) assigned to the surface - if (!texture_name && pcSurfaces->NUM_SHADER) { + if (!texture_name && pcSurfaces->NUM_SHADER) { texture_name = pcShaders->NAME; } std::string convertedPath; if (texture_name) { - ConvertPath(texture_name,header_name,convertedPath); + ConvertPath(texture_name, header_name, convertedPath); } - const Q3Shader::ShaderDataBlock* shader = NULL; + const Q3Shader::ShaderDataBlock *shader = nullptr; // Now search the current shader for a record with this name ( // excluding texture file extension) @@ -912,18 +875,18 @@ void MD3Importer::InternReadFile( const std::string& pFile, aiScene* pScene, IOS sh = convertedPath.length(); } - const std::string without_ext = convertedPath.substr(0,sh); - std::list< Q3Shader::ShaderDataBlock >::const_iterator dit = std::find(shaders.blocks.begin(),shaders.blocks.end(),without_ext); + const std::string without_ext = convertedPath.substr(0, sh); + std::list::const_iterator dit = std::find(shaders.blocks.begin(), shaders.blocks.end(), without_ext); if (dit != shaders.blocks.end()) { // We made it! shader = &*dit; - ASSIMP_LOG_INFO("Found shader record for " +without_ext ); + ASSIMP_LOG_INFO("Found shader record for " + without_ext); } else { ASSIMP_LOG_WARN("Unable to find shader record for " + without_ext); } } - aiMaterial* pcHelper = new aiMaterial(); + aiMaterial *pcHelper = new aiMaterial(); const int iMode = (int)aiShadingMode_Gouraud; pcHelper->AddProperty(&iMode, 1, AI_MATKEY_SHADING_MODEL); @@ -931,51 +894,51 @@ void MD3Importer::InternReadFile( const std::string& pFile, aiScene* pScene, IOS // Add a small ambient color value - Quake 3 seems to have one aiColor3D clr; clr.b = clr.g = clr.r = 0.05f; - pcHelper->AddProperty(&clr, 1,AI_MATKEY_COLOR_AMBIENT); + pcHelper->AddProperty(&clr, 1, AI_MATKEY_COLOR_AMBIENT); clr.b = clr.g = clr.r = 1.0f; - pcHelper->AddProperty(&clr, 1,AI_MATKEY_COLOR_DIFFUSE); - pcHelper->AddProperty(&clr, 1,AI_MATKEY_COLOR_SPECULAR); + pcHelper->AddProperty(&clr, 1, AI_MATKEY_COLOR_DIFFUSE); + pcHelper->AddProperty(&clr, 1, AI_MATKEY_COLOR_SPECULAR); // use surface name + skin_name as material name aiString name; name.Set("MD3_[" + configSkinFile + "][" + pcSurfaces->NAME + "]"); - pcHelper->AddProperty(&name,AI_MATKEY_NAME); + pcHelper->AddProperty(&name, AI_MATKEY_NAME); if (!shader) { // Setup dummy texture file name to ensure UV coordinates are kept during postprocessing aiString szString; if (convertedPath.length()) { szString.Set(convertedPath); - } else { + } else { ASSIMP_LOG_WARN("Texture file name has zero length. Using default name"); szString.Set("dummy_texture.bmp"); } - pcHelper->AddProperty(&szString,AI_MATKEY_TEXTURE_DIFFUSE(0)); + pcHelper->AddProperty(&szString, AI_MATKEY_TEXTURE_DIFFUSE(0)); // prevent transparency by default int no_alpha = aiTextureFlags_IgnoreAlpha; - pcHelper->AddProperty(&no_alpha,1,AI_MATKEY_TEXFLAGS_DIFFUSE(0)); + pcHelper->AddProperty(&no_alpha, 1, AI_MATKEY_TEXFLAGS_DIFFUSE(0)); } else { - Q3Shader::ConvertShaderToMaterial(pcHelper,*shader); + Q3Shader::ConvertShaderToMaterial(pcHelper, *shader); } - pScene->mMaterials[iNumMaterials] = (aiMaterial*)pcHelper; + pScene->mMaterials[iNumMaterials] = (aiMaterial *)pcHelper; pcMesh->mMaterialIndex = iNumMaterials++; - // Ensure correct endianness + // Ensure correct endianness #ifdef AI_BUILD_BIG_ENDIAN - for (uint32_t i = 0; i < pcSurfaces->NUM_VERTICES;++i) { - AI_SWAP2( pcVertices[i].NORMAL ); - AI_SWAP2( pcVertices[i].X ); - AI_SWAP2( pcVertices[i].Y ); - AI_SWAP2( pcVertices[i].Z ); + for (uint32_t i = 0; i < pcSurfaces->NUM_VERTICES; ++i) { + AI_SWAP2(pcVertices[i].NORMAL); + AI_SWAP2(pcVertices[i].X); + AI_SWAP2(pcVertices[i].Y); + AI_SWAP2(pcVertices[i].Z); - AI_SWAP4( pcUVs[i].U ); - AI_SWAP4( pcUVs[i].V ); + AI_SWAP4(pcUVs[i].U); + AI_SWAP4(pcUVs[i].V); } - for (uint32_t i = 0; i < pcSurfaces->NUM_TRIANGLES;++i) { + for (uint32_t i = 0; i < pcSurfaces->NUM_TRIANGLES; ++i) { AI_SWAP4(pcTriangles[i].INDEXES[0]); AI_SWAP4(pcTriangles[i].INDEXES[1]); AI_SWAP4(pcTriangles[i].INDEXES[2]); @@ -986,56 +949,56 @@ void MD3Importer::InternReadFile( const std::string& pFile, aiScene* pScene, IOS // Fill mesh information pcMesh->mPrimitiveTypes = aiPrimitiveType_TRIANGLE; - pcMesh->mNumVertices = pcSurfaces->NUM_TRIANGLES*3; - pcMesh->mNumFaces = pcSurfaces->NUM_TRIANGLES; - pcMesh->mFaces = new aiFace[pcSurfaces->NUM_TRIANGLES]; - pcMesh->mNormals = new aiVector3D[pcMesh->mNumVertices]; - pcMesh->mVertices = new aiVector3D[pcMesh->mNumVertices]; - pcMesh->mTextureCoords[0] = new aiVector3D[pcMesh->mNumVertices]; + pcMesh->mNumVertices = pcSurfaces->NUM_TRIANGLES * 3; + pcMesh->mNumFaces = pcSurfaces->NUM_TRIANGLES; + pcMesh->mFaces = new aiFace[pcSurfaces->NUM_TRIANGLES]; + pcMesh->mNormals = new aiVector3D[pcMesh->mNumVertices]; + pcMesh->mVertices = new aiVector3D[pcMesh->mNumVertices]; + pcMesh->mTextureCoords[0] = new aiVector3D[pcMesh->mNumVertices]; pcMesh->mNumUVComponents[0] = 2; // Fill in all triangles unsigned int iCurrent = 0; - for (unsigned int i = 0; i < (unsigned int)pcSurfaces->NUM_TRIANGLES;++i) { + for (unsigned int i = 0; i < (unsigned int)pcSurfaces->NUM_TRIANGLES; ++i) { pcMesh->mFaces[i].mIndices = new unsigned int[3]; pcMesh->mFaces[i].mNumIndices = 3; //unsigned int iTemp = iCurrent; - for (unsigned int c = 0; c < 3;++c,++iCurrent) { + for (unsigned int c = 0; c < 3; ++c, ++iCurrent) { pcMesh->mFaces[i].mIndices[c] = iCurrent; // Read vertices - aiVector3D& vec = pcMesh->mVertices[iCurrent]; + aiVector3D &vec = pcMesh->mVertices[iCurrent]; uint32_t index = pcTriangles->INDEXES[c]; if (index >= pcSurfaces->NUM_VERTICES) { - throw DeadlyImportError( "MD3: Invalid vertex index"); + throw DeadlyImportError("MD3: Invalid vertex index"); } - vec.x = pcVertices[index].X*AI_MD3_XYZ_SCALE; - vec.y = pcVertices[index].Y*AI_MD3_XYZ_SCALE; - vec.z = pcVertices[index].Z*AI_MD3_XYZ_SCALE; + vec.x = pcVertices[index].X * AI_MD3_XYZ_SCALE; + vec.y = pcVertices[index].Y * AI_MD3_XYZ_SCALE; + vec.z = pcVertices[index].Z * AI_MD3_XYZ_SCALE; // Convert the normal vector to uncompressed float3 format - aiVector3D& nor = pcMesh->mNormals[iCurrent]; - LatLngNormalToVec3(pcVertices[index].NORMAL,(ai_real*)&nor); + aiVector3D &nor = pcMesh->mNormals[iCurrent]; + LatLngNormalToVec3(pcVertices[index].NORMAL, (ai_real *)&nor); // Read texture coordinates pcMesh->mTextureCoords[0][iCurrent].x = pcUVs[index].U; - pcMesh->mTextureCoords[0][iCurrent].y = 1.0f-pcUVs[index].V; + pcMesh->mTextureCoords[0][iCurrent].y = 1.0f - pcUVs[index].V; } // Flip face order if necessary if (!shader || shader->cull == Q3Shader::CULL_CW) { - std::swap(pcMesh->mFaces[i].mIndices[2],pcMesh->mFaces[i].mIndices[1]); + std::swap(pcMesh->mFaces[i].mIndices[2], pcMesh->mFaces[i].mIndices[1]); } ++pcTriangles; } // Go to the next surface - pcSurfaces = (BE_NCONST MD3::Surface*)(((unsigned char*)pcSurfaces) + pcSurfaces->OFS_END); + pcSurfaces = (BE_NCONST MD3::Surface *)(((unsigned char *)pcSurfaces) + pcSurfaces->OFS_END); } // For debugging purposes: check whether we found matches for all entries in the skins file if (!DefaultLogger::isNullLogger()) { - for (std::list< Q3Shader::SkinData::TextureEntry>::const_iterator it = skins.textures.begin();it != skins.textures.end(); ++it) { + for (std::list::const_iterator it = skins.textures.begin(); it != skins.textures.end(); ++it) { if (!(*it).resolved) { ASSIMP_LOG_ERROR_F("MD3: Failed to match skin ", (*it).first, " to surface ", (*it).second); } @@ -1043,7 +1006,7 @@ void MD3Importer::InternReadFile( const std::string& pFile, aiScene* pScene, IOS } if (!pScene->mNumMeshes) { - throw DeadlyImportError( "MD3: File contains no valid mesh"); + throw DeadlyImportError("MD3: File contains no valid mesh"); } pScene->mNumMaterials = iNumMaterials; @@ -1055,11 +1018,11 @@ void MD3Importer::InternReadFile( const std::string& pFile, aiScene* pScene, IOS // Attach tiny children for all tags if (pcHeader->NUM_TAGS) { pScene->mRootNode->mNumChildren = pcHeader->NUM_TAGS; - pScene->mRootNode->mChildren = new aiNode*[pcHeader->NUM_TAGS]; + pScene->mRootNode->mChildren = new aiNode *[pcHeader->NUM_TAGS]; for (unsigned int i = 0; i < pcHeader->NUM_TAGS; ++i, ++pcTags) { - aiNode* nd = pScene->mRootNode->mChildren[i] = new aiNode(); - nd->mName.Set((const char*)pcTags->NAME); + aiNode *nd = pScene->mRootNode->mChildren[i] = new aiNode(); + nd->mName.Set((const char *)pcTags->NAME); nd->mParent = pScene->mRootNode; AI_SWAP4(pcTags->origin.x); @@ -1072,8 +1035,8 @@ void MD3Importer::InternReadFile( const std::string& pFile, aiScene* pScene, IOS nd->mTransformation.c4 = pcTags->origin.z; // Copy rest of transformation (need to transpose to match row-order matrix) - for (unsigned int a = 0; a < 3;++a) { - for (unsigned int m = 0; m < 3;++m) { + for (unsigned int a = 0; a < 3; ++a) { + for (unsigned int m = 0; m < 3; ++m) { nd->mTransformation[m][a] = pcTags->orientation[a][m]; AI_SWAP4(nd->mTransformation[m][a]); } @@ -1081,16 +1044,15 @@ void MD3Importer::InternReadFile( const std::string& pFile, aiScene* pScene, IOS } } - for (unsigned int i = 0; i < pScene->mNumMeshes;++i) + for (unsigned int i = 0; i < pScene->mNumMeshes; ++i) pScene->mRootNode->mMeshes[i] = i; // Now rotate the whole scene 90 degrees around the x axis to convert to internal coordinate system pScene->mRootNode->mTransformation = aiMatrix4x4( - 1.f,0.f,0.f,0.f, - 0.f,0.f,1.f,0.f, - 0.f,-1.f,0.f,0.f, - 0.f,0.f,0.f,1.f - ); + 1.f, 0.f, 0.f, 0.f, + 0.f, 0.f, 1.f, 0.f, + 0.f, -1.f, 0.f, 0.f, + 0.f, 0.f, 0.f, 1.f); } #endif // !! ASSIMP_BUILD_NO_MD3_IMPORTER diff --git a/code/AssetLib/MD5/MD5Loader.cpp b/code/AssetLib/MD5/MD5Loader.cpp index d428873df..5428a9c74 100644 --- a/code/AssetLib/MD5/MD5Loader.cpp +++ b/code/AssetLib/MD5/MD5Loader.cpp @@ -5,8 +5,6 @@ Open Asset Import Library (assimp) Copyright (c) 2006-2020, assimp team - - All rights reserved. Redistribution and use of this software in source and binary forms, @@ -82,7 +80,15 @@ static const aiImporterDesc desc = { // ------------------------------------------------------------------------------------------------ // Constructor to be privately used by Importer MD5Importer::MD5Importer() : - mIOHandler(nullptr), mBuffer(), fileSize(), iLineNumber(), pScene(), bHadMD5Mesh(), bHadMD5Anim(), bHadMD5Camera(), configNoAutoLoad(false) { + mIOHandler(nullptr), + mBuffer(), + mFileSize(), + mLineNumber(), + mScene(), + mHadMD5Mesh(), + mHadMD5Anim(), + mHadMD5Camera(), + mCconfigNoAutoLoad(false) { // empty } @@ -106,6 +112,7 @@ bool MD5Importer::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool c const char *tokens[] = { "MD5Version" }; return SearchFileHeaderForToken(pIOHandler, pFile, tokens, 1); } + return false; } @@ -119,16 +126,15 @@ const aiImporterDesc *MD5Importer::GetInfo() const { // Setup import properties void MD5Importer::SetupProperties(const Importer *pImp) { // AI_CONFIG_IMPORT_MD5_NO_ANIM_AUTOLOAD - configNoAutoLoad = (0 != pImp->GetPropertyInteger(AI_CONFIG_IMPORT_MD5_NO_ANIM_AUTOLOAD, 0)); + mCconfigNoAutoLoad = (0 != pImp->GetPropertyInteger(AI_CONFIG_IMPORT_MD5_NO_ANIM_AUTOLOAD, 0)); } // ------------------------------------------------------------------------------------------------ // Imports the given file into the given scene structure. -void MD5Importer::InternReadFile(const std::string &pFile, - aiScene *_pScene, IOSystem *pIOHandler) { +void MD5Importer::InternReadFile(const std::string &pFile, aiScene *_pScene, IOSystem *pIOHandler) { mIOHandler = pIOHandler; - pScene = _pScene; - bHadMD5Mesh = bHadMD5Anim = bHadMD5Camera = false; + mScene = _pScene; + mHadMD5Mesh = mHadMD5Anim = mHadMD5Camera = false; // remove the file extension const std::string::size_type pos = pFile.find_last_of('.'); @@ -138,7 +144,7 @@ void MD5Importer::InternReadFile(const std::string &pFile, try { if (extension == "md5camera") { LoadMD5CameraFile(); - } else if (configNoAutoLoad || extension == "md5anim") { + } else if (mCconfigNoAutoLoad || extension == "md5anim") { // determine file extension and process just *one* file if (extension.length() == 0) { throw DeadlyImportError("Failure, need file extension to determine MD5 part type"); @@ -158,17 +164,17 @@ void MD5Importer::InternReadFile(const std::string &pFile, } // make sure we have at least one file - if (!bHadMD5Mesh && !bHadMD5Anim && !bHadMD5Camera) { + if (!mHadMD5Mesh && !mHadMD5Anim && !mHadMD5Camera) { throw DeadlyImportError("Failed to read valid contents out of this MD5* file"); } // Now rotate the whole scene 90 degrees around the x axis to match our internal coordinate system - pScene->mRootNode->mTransformation = aiMatrix4x4(1.f, 0.f, 0.f, 0.f, + mScene->mRootNode->mTransformation = aiMatrix4x4(1.f, 0.f, 0.f, 0.f, 0.f, 0.f, 1.f, 0.f, 0.f, -1.f, 0.f, 0.f, 0.f, 0.f, 0.f, 1.f); // the output scene wouldn't pass the validation without this flag - if (!bHadMD5Mesh) { - pScene->mFlags |= AI_SCENE_FLAGS_INCOMPLETE; + if (!mHadMD5Mesh) { + mScene->mFlags |= AI_SCENE_FLAGS_INCOMPLETE; } // clean the instance -- the BaseImporter instance may be reused later. @@ -181,17 +187,17 @@ void MD5Importer::LoadFileIntoMemory(IOStream *file) { // unload the previous buffer, if any UnloadFileFromMemory(); - ai_assert(NULL != file); - fileSize = (unsigned int)file->FileSize(); - ai_assert(fileSize); + ai_assert(nullptr != file); + mFileSize = (unsigned int)file->FileSize(); + ai_assert(mFileSize); // allocate storage and copy the contents of the file to a memory buffer - mBuffer = new char[fileSize + 1]; - file->Read((void *)mBuffer, 1, fileSize); - iLineNumber = 1; + mBuffer = new char[mFileSize + 1]; + file->Read((void *)mBuffer, 1, mFileSize); + mLineNumber = 1; // append a terminal 0 - mBuffer[fileSize] = '\0'; + mBuffer[mFileSize] = '\0'; // now remove all line comments from the file CommentRemover::RemoveLineComments("//", mBuffer, ' '); @@ -202,8 +208,8 @@ void MD5Importer::LoadFileIntoMemory(IOStream *file) { void MD5Importer::UnloadFileFromMemory() { // delete the file buffer delete[] mBuffer; - mBuffer = NULL; - fileSize = 0; + mBuffer = nullptr; + mFileSize = 0; } // ------------------------------------------------------------------------------------------------ @@ -243,7 +249,8 @@ void MD5Importer::MakeDataUnique(MD5::MeshDesc &meshSrc) { // ------------------------------------------------------------------------------------------------ // Recursive node graph construction from a MD5MESH void MD5Importer::AttachChilds_Mesh(int iParentID, aiNode *piParent, BoneList &bones) { - ai_assert(NULL != piParent && !piParent->mNumChildren); + ai_assert(nullptr != piParent); + ai_assert(!piParent->mNumChildren); // First find out how many children we'll have for (int i = 0; i < (int)bones.size(); ++i) { @@ -293,7 +300,8 @@ void MD5Importer::AttachChilds_Mesh(int iParentID, aiNode *piParent, BoneList &b // ------------------------------------------------------------------------------------------------ // Recursive node graph construction from a MD5ANIM void MD5Importer::AttachChilds_Anim(int iParentID, aiNode *piParent, AnimBoneList &bones, const aiNodeAnim **node_anims) { - ai_assert(NULL != piParent && !piParent->mNumChildren); + ai_assert(nullptr != piParent); + ai_assert(!piParent->mNumChildren); // First find out how many children we'll have for (int i = 0; i < (int)bones.size(); ++i) { @@ -332,37 +340,37 @@ void MD5Importer::AttachChilds_Anim(int iParentID, aiNode *piParent, AnimBoneLis // ------------------------------------------------------------------------------------------------ // Load a MD5MESH file void MD5Importer::LoadMD5MeshFile() { - std::string pFile = mFile + "md5mesh"; - std::unique_ptr file(mIOHandler->Open(pFile, "rb")); + std::string filename = mFile + "md5mesh"; + std::unique_ptr file(mIOHandler->Open(filename, "rb")); // Check whether we can read from the file if (file.get() == nullptr || !file->FileSize()) { - ASSIMP_LOG_WARN("Failed to access MD5MESH file: " + pFile); + ASSIMP_LOG_WARN("Failed to access MD5MESH file: " + filename); return; } - bHadMD5Mesh = true; + mHadMD5Mesh = true; LoadFileIntoMemory(file.get()); // now construct a parser and parse the file - MD5::MD5Parser parser(mBuffer, fileSize); + MD5::MD5Parser parser(mBuffer, mFileSize); // load the mesh information from it MD5::MD5MeshParser meshParser(parser.mSections); // create the bone hierarchy - first the root node and dummy nodes for all meshes - pScene->mRootNode = new aiNode(""); - pScene->mRootNode->mNumChildren = 2; - pScene->mRootNode->mChildren = new aiNode *[2]; + mScene->mRootNode = new aiNode(""); + mScene->mRootNode->mNumChildren = 2; + mScene->mRootNode->mChildren = new aiNode *[2]; // build the hierarchy from the MD5MESH file - aiNode *pcNode = pScene->mRootNode->mChildren[1] = new aiNode(); + aiNode *pcNode = mScene->mRootNode->mChildren[1] = new aiNode(); pcNode->mName.Set(""); - pcNode->mParent = pScene->mRootNode; + pcNode->mParent = mScene->mRootNode; AttachChilds_Mesh(-1, pcNode, meshParser.mJoints); - pcNode = pScene->mRootNode->mChildren[0] = new aiNode(); + pcNode = mScene->mRootNode->mChildren[0] = new aiNode(); pcNode->mName.Set(""); - pcNode->mParent = pScene->mRootNode; + pcNode->mParent = mScene->mRootNode; #if 0 if (pScene->mRootNode->mChildren[1]->mNumChildren) /* start at the right hierarchy level */ @@ -371,28 +379,31 @@ void MD5Importer::LoadMD5MeshFile() { // FIX: MD5 files exported from Blender can have empty meshes for (std::vector::const_iterator it = meshParser.mMeshes.begin(), end = meshParser.mMeshes.end(); it != end; ++it) { - if (!(*it).mFaces.empty() && !(*it).mVertices.empty()) - ++pScene->mNumMaterials; + if (!(*it).mFaces.empty() && !(*it).mVertices.empty()) { + ++mScene->mNumMaterials; + } } // generate all meshes - pScene->mNumMeshes = pScene->mNumMaterials; - pScene->mMeshes = new aiMesh *[pScene->mNumMeshes]; - pScene->mMaterials = new aiMaterial *[pScene->mNumMeshes]; + mScene->mNumMeshes = mScene->mNumMaterials; + mScene->mMeshes = new aiMesh *[mScene->mNumMeshes]; + mScene->mMaterials = new aiMaterial *[mScene->mNumMeshes]; // storage for node mesh indices - pcNode->mNumMeshes = pScene->mNumMeshes; + pcNode->mNumMeshes = mScene->mNumMeshes; pcNode->mMeshes = new unsigned int[pcNode->mNumMeshes]; - for (unsigned int m = 0; m < pcNode->mNumMeshes; ++m) + for (unsigned int m = 0; m < pcNode->mNumMeshes; ++m) { pcNode->mMeshes[m] = m; + } unsigned int n = 0; for (std::vector::iterator it = meshParser.mMeshes.begin(), end = meshParser.mMeshes.end(); it != end; ++it) { MD5::MeshDesc &meshSrc = *it; - if (meshSrc.mFaces.empty() || meshSrc.mVertices.empty()) + if (meshSrc.mFaces.empty() || meshSrc.mVertices.empty()) { continue; + } - aiMesh *mesh = pScene->mMeshes[n] = new aiMesh(); + aiMesh *mesh = mScene->mMeshes[n] = new aiMesh(); mesh->mPrimitiveTypes = aiPrimitiveType_TRIANGLE; // generate unique vertices in our internal verbose format @@ -422,17 +433,19 @@ void MD5Importer::LoadMD5MeshFile() { for (unsigned int jub = (*iter).mFirstWeight, w = jub; w < jub + (*iter).mNumWeights; ++w) { MD5::WeightDesc &weightDesc = meshSrc.mWeights[w]; /* FIX for some invalid exporters */ - if (!(weightDesc.mWeight < AI_MD5_WEIGHT_EPSILON && weightDesc.mWeight >= -AI_MD5_WEIGHT_EPSILON)) + if (!(weightDesc.mWeight < AI_MD5_WEIGHT_EPSILON && weightDesc.mWeight >= -AI_MD5_WEIGHT_EPSILON)) { ++piCount[weightDesc.mBone]; + } } } // check how many we will need - for (unsigned int p = 0; p < meshParser.mJoints.size(); ++p) + for (unsigned int p = 0; p < meshParser.mJoints.size(); ++p) { if (piCount[p]) mesh->mNumBones++; + } - if (mesh->mNumBones) // just for safety - { + // just for safety + if (mesh->mNumBones) { mesh->mBones = new aiBone *[mesh->mNumBones]; for (unsigned int q = 0, h = 0; q < meshParser.mJoints.size(); ++q) { if (!piCount[q]) continue; @@ -457,8 +470,9 @@ void MD5Importer::LoadMD5MeshFile() { // there are models which have weights which don't sum to 1 ... ai_real fSum = 0.0; - for (unsigned int jub = (*iter).mFirstWeight, w = jub; w < jub + (*iter).mNumWeights; ++w) + for (unsigned int jub = (*iter).mFirstWeight, w = jub; w < jub + (*iter).mNumWeights; ++w) { fSum += meshSrc.mWeights[w].mWeight; + } if (!fSum) { ASSIMP_LOG_ERROR("MD5MESH: The sum of all vertex bone weights is 0"); continue; @@ -466,11 +480,12 @@ void MD5Importer::LoadMD5MeshFile() { // process bone weights for (unsigned int jub = (*iter).mFirstWeight, w = jub; w < jub + (*iter).mNumWeights; ++w) { - if (w >= meshSrc.mWeights.size()) + if (w >= meshSrc.mWeights.size()) { throw DeadlyImportError("MD5MESH: Invalid weight index"); + } MD5::WeightDesc &weightDesc = meshSrc.mWeights[w]; - if (weightDesc.mWeight < AI_MD5_WEIGHT_EPSILON && weightDesc.mWeight >= -AI_MD5_WEIGHT_EPSILON) { + if (weightDesc.mWeight < AI_MD5_WEIGHT_EPSILON && weightDesc.mWeight >= -AI_MD5_WEIGHT_EPSILON) { continue; } @@ -504,12 +519,12 @@ void MD5Importer::LoadMD5MeshFile() { for (unsigned int c = 0; c < mesh->mNumFaces; ++c) { mesh->mFaces[c].mNumIndices = 3; mesh->mFaces[c].mIndices = meshSrc.mFaces[c].mIndices; - meshSrc.mFaces[c].mIndices = NULL; + meshSrc.mFaces[c].mIndices = nullptr; } // generate a material for the mesh aiMaterial *mat = new aiMaterial(); - pScene->mMaterials[n] = mat; + mScene->mMaterials[n] = mat; // insert the typical doom3 textures: // nnn_local.tga - normal map @@ -555,10 +570,11 @@ void MD5Importer::LoadMD5AnimFile() { ASSIMP_LOG_WARN("Failed to read MD5ANIM file: " + pFile); return; } + LoadFileIntoMemory(file.get()); // parse the basic file structure - MD5::MD5Parser parser(mBuffer, fileSize); + MD5::MD5Parser parser(mBuffer, mFileSize); // load the animation information from the parse tree MD5::MD5AnimParser animParser(parser.mSections); @@ -568,10 +584,10 @@ void MD5Importer::LoadMD5AnimFile() { animParser.mBaseFrames.size() != animParser.mAnimatedBones.size()) { ASSIMP_LOG_ERROR("MD5ANIM: No frames or animated bones loaded"); } else { - bHadMD5Anim = true; + mHadMD5Anim = true; - pScene->mAnimations = new aiAnimation *[pScene->mNumAnimations = 1]; - aiAnimation *anim = pScene->mAnimations[0] = new aiAnimation(); + mScene->mAnimations = new aiAnimation *[mScene->mNumAnimations = 1]; + aiAnimation *anim = mScene->mAnimations[0] = new aiAnimation(); anim->mNumChannels = (unsigned int)animParser.mAnimatedBones.size(); anim->mChannels = new aiNodeAnim *[anim->mNumChannels]; for (unsigned int i = 0; i < anim->mNumChannels; ++i) { @@ -637,15 +653,15 @@ void MD5Importer::LoadMD5AnimFile() { // If we didn't build the hierarchy yet (== we didn't load a MD5MESH), // construct it now from the data given in the MD5ANIM. - if (!pScene->mRootNode) { - pScene->mRootNode = new aiNode(); - pScene->mRootNode->mName.Set(""); + if (!mScene->mRootNode) { + mScene->mRootNode = new aiNode(); + mScene->mRootNode->mName.Set(""); - AttachChilds_Anim(-1, pScene->mRootNode, animParser.mAnimatedBones, (const aiNodeAnim **)anim->mChannels); + AttachChilds_Anim(-1, mScene->mRootNode, animParser.mAnimatedBones, (const aiNodeAnim **)anim->mChannels); // Call SkeletonMeshBuilder to construct a mesh to represent the shape - if (pScene->mRootNode->mNumChildren) { - SkeletonMeshBuilder skeleton_maker(pScene, pScene->mRootNode->mChildren[0]); + if (mScene->mRootNode->mNumChildren) { + SkeletonMeshBuilder skeleton_maker(mScene, mScene->mRootNode->mChildren[0]); } } } @@ -661,11 +677,11 @@ void MD5Importer::LoadMD5CameraFile() { if (!file.get() || !file->FileSize()) { throw DeadlyImportError("Failed to read MD5CAMERA file: " + pFile); } - bHadMD5Camera = true; + mHadMD5Camera = true; LoadFileIntoMemory(file.get()); // parse the basic file structure - MD5::MD5Parser parser(mBuffer, fileSize); + MD5::MD5Parser parser(mBuffer, mFileSize); // load the camera animation data from the parse tree MD5::MD5CameraParser cameraParser(parser.mSections); @@ -679,14 +695,14 @@ void MD5Importer::LoadMD5CameraFile() { // Construct output graph - a simple root with a dummy child. // The root node performs the coordinate system conversion - aiNode *root = pScene->mRootNode = new aiNode(""); + aiNode *root = mScene->mRootNode = new aiNode(""); root->mChildren = new aiNode *[root->mNumChildren = 1]; root->mChildren[0] = new aiNode(""); root->mChildren[0]->mParent = root; // ... but with one camera assigned to it - pScene->mCameras = new aiCamera *[pScene->mNumCameras = 1]; - aiCamera *cam = pScene->mCameras[0] = new aiCamera(); + mScene->mCameras = new aiCamera *[mScene->mNumCameras = 1]; + aiCamera *cam = mScene->mCameras[0] = new aiCamera(); cam->mName = ""; // FIXME: Fov is currently set to the first frame's value @@ -703,8 +719,8 @@ void MD5Importer::LoadMD5CameraFile() { cuts.push_back(static_cast(frames.size() - 1)); } - pScene->mNumAnimations = static_cast(cuts.size() - 1); - aiAnimation **tmp = pScene->mAnimations = new aiAnimation *[pScene->mNumAnimations]; + mScene->mNumAnimations = static_cast(cuts.size() - 1); + aiAnimation **tmp = mScene->mAnimations = new aiAnimation *[mScene->mNumAnimations]; for (std::vector::const_iterator it = cuts.begin(); it != cuts.end() - 1; ++it) { aiAnimation *anim = *tmp++ = new aiAnimation(); diff --git a/code/AssetLib/MD5/MD5Loader.h b/code/AssetLib/MD5/MD5Loader.h index cfdd9ed0e..f62a57e68 100644 --- a/code/AssetLib/MD5/MD5Loader.h +++ b/code/AssetLib/MD5/MD5Loader.h @@ -4,7 +4,6 @@ Open Asset Import Library (assimp) Copyright (c) 2006-2020, assimp team - All rights reserved. Redistribution and use of this software in source and binary forms, @@ -156,25 +155,25 @@ protected: char *mBuffer; /** Size of the file */ - unsigned int fileSize; + unsigned int mFileSize; /** Current line number. For debugging purposes */ - unsigned int iLineNumber; + unsigned int mLineNumber; /** Scene to be filled */ - aiScene *pScene; + aiScene *mScene; /** true if a MD5MESH file has already been parsed */ - bool bHadMD5Mesh; + bool mHadMD5Mesh; /** true if a MD5ANIM file has already been parsed */ - bool bHadMD5Anim; + bool mHadMD5Anim; /** true if a MD5CAMERA file has already been parsed */ - bool bHadMD5Camera; + bool mHadMD5Camera; /** configuration option: prevent anim autoload */ - bool configNoAutoLoad; + bool mCconfigNoAutoLoad; }; } // end of namespace Assimp diff --git a/code/AssetLib/MD5/MD5Parser.cpp b/code/AssetLib/MD5/MD5Parser.cpp index e2f697816..345f0e10c 100644 --- a/code/AssetLib/MD5/MD5Parser.cpp +++ b/code/AssetLib/MD5/MD5Parser.cpp @@ -45,25 +45,24 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * @brief Implementation of the MD5 parser class */ - // internal headers #include "AssetLib/MD5/MD5Loader.h" #include "Material/MaterialSystem.h" -#include #include #include -#include +#include #include +#include using namespace Assimp; using namespace Assimp::MD5; // ------------------------------------------------------------------------------------------------ // Parse the segment structure fo a MD5 file -MD5Parser::MD5Parser(char* _buffer, unsigned int _fileSize ) -{ - ai_assert(NULL != _buffer && 0 != _fileSize); +MD5Parser::MD5Parser(char *_buffer, unsigned int _fileSize) { + ai_assert(nullptr != _buffer); + ai_assert(0 != _fileSize); buffer = _buffer; fileSize = _fileSize; @@ -78,48 +77,45 @@ MD5Parser::MD5Parser(char* _buffer, unsigned int _fileSize ) bool running = true; while (running) { mSections.push_back(Section()); - Section& sec = mSections.back(); - if(!ParseSection(sec)) { + Section &sec = mSections.back(); + if (!ParseSection(sec)) { break; } } - if ( !DefaultLogger::isNullLogger()) { + if (!DefaultLogger::isNullLogger()) { char szBuffer[128]; // should be sufficiently large - ::ai_snprintf(szBuffer,128,"MD5Parser end. Parsed %i sections",(int)mSections.size()); + ::ai_snprintf(szBuffer, 128, "MD5Parser end. Parsed %i sections", (int)mSections.size()); ASSIMP_LOG_DEBUG(szBuffer); } } // ------------------------------------------------------------------------------------------------ // Report error to the log stream -/*static*/ AI_WONT_RETURN void MD5Parser::ReportError (const char* error, unsigned int line) -{ +/*static*/ AI_WONT_RETURN void MD5Parser::ReportError(const char *error, unsigned int line) { char szBuffer[1024]; - ::ai_snprintf(szBuffer, 1024, "[MD5] Line %u: %s",line,error); + ::ai_snprintf(szBuffer, 1024, "[MD5] Line %u: %s", line, error); throw DeadlyImportError(szBuffer); } // ------------------------------------------------------------------------------------------------ // Report warning to the log stream -/*static*/ void MD5Parser::ReportWarning (const char* warn, unsigned int line) -{ +/*static*/ void MD5Parser::ReportWarning(const char *warn, unsigned int line) { char szBuffer[1024]; - ::sprintf(szBuffer,"[MD5] Line %u: %s",line,warn); + ::sprintf(szBuffer, "[MD5] Line %u: %s", line, warn); ASSIMP_LOG_WARN(szBuffer); } // ------------------------------------------------------------------------------------------------ // Parse and validate the MD5 header -void MD5Parser::ParseHeader() -{ +void MD5Parser::ParseHeader() { // parse and validate the file version SkipSpaces(); - if (!TokenMatch(buffer,"MD5Version",10)) { + if (!TokenMatch(buffer, "MD5Version", 10)) { ReportError("Invalid MD5 file: MD5Version tag has not been found"); } SkipSpaces(); - unsigned int iVer = ::strtoul10(buffer,(const char**)&buffer); + unsigned int iVer = ::strtoul10(buffer, (const char **)&buffer); if (10 != iVer) { ReportError("MD5 version tag is unknown (10 is expected)"); } @@ -127,23 +123,24 @@ void MD5Parser::ParseHeader() // print the command line options to the console // FIX: can break the log length limit, so we need to be careful - char* sz = buffer; - while (!IsLineEnd( *buffer++)); - ASSIMP_LOG_INFO(std::string(sz,std::min((uintptr_t)MAX_LOG_MESSAGE_LENGTH, (uintptr_t)(buffer-sz)))); + char *sz = buffer; + while (!IsLineEnd(*buffer++)) + ; + ASSIMP_LOG_INFO(std::string(sz, std::min((uintptr_t)MAX_LOG_MESSAGE_LENGTH, (uintptr_t)(buffer - sz)))); SkipSpacesAndLineEnd(); } // ------------------------------------------------------------------------------------------------ // Recursive MD5 parsing function -bool MD5Parser::ParseSection(Section& out) -{ +bool MD5Parser::ParseSection(Section &out) { // store the current line number for use in error messages out.iLineNumber = lineNumber; // first parse the name of the section - char* sz = buffer; - while (!IsSpaceOrNewLine( *buffer))buffer++; - out.mName = std::string(sz,(uintptr_t)(buffer-sz)); + char *sz = buffer; + while (!IsSpaceOrNewLine(*buffer)) + buffer++; + out.mName = std::string(sz, (uintptr_t)(buffer - sz)); SkipSpaces(); bool running = true; @@ -152,8 +149,7 @@ bool MD5Parser::ParseSection(Section& out) // it is a normal section so read all lines buffer++; bool run = true; - while (run) - { + while (run) { if (!SkipSpacesAndLineEnd()) { return false; // seems this was the last section } @@ -163,25 +159,26 @@ bool MD5Parser::ParseSection(Section& out) } out.mElements.push_back(Element()); - Element& elem = out.mElements.back(); + Element &elem = out.mElements.back(); elem.iLineNumber = lineNumber; elem.szStart = buffer; // terminate the line with zero - while (!IsLineEnd( *buffer))buffer++; + while (!IsLineEnd(*buffer)) + buffer++; if (*buffer) { ++lineNumber; *buffer++ = '\0'; } } break; - } - else if (!IsSpaceOrNewLine(*buffer)) { + } else if (!IsSpaceOrNewLine(*buffer)) { // it is an element at global scope. Parse its value and go on sz = buffer; - while (!IsSpaceOrNewLine( *buffer++)); - out.mGlobalValue = std::string(sz,(uintptr_t)(buffer-sz)); + while (!IsSpaceOrNewLine(*buffer++)) + ; + out.mGlobalValue = std::string(sz, (uintptr_t)(buffer - sz)); continue; } break; @@ -193,161 +190,161 @@ bool MD5Parser::ParseSection(Section& out) // Some dirty macros just because they're so funny and easy to debug // skip all spaces ... handle EOL correctly -#define AI_MD5_SKIP_SPACES() if(!SkipSpaces(&sz)) \ - MD5Parser::ReportWarning("Unexpected end of line",elem.iLineNumber); +#define AI_MD5_SKIP_SPACES() \ + if (!SkipSpaces(&sz)) \ + MD5Parser::ReportWarning("Unexpected end of line", elem.iLineNumber); - // read a triple float in brackets: (1.0 1.0 1.0) -#define AI_MD5_READ_TRIPLE(vec) \ - AI_MD5_SKIP_SPACES(); \ - if ('(' != *sz++) \ - MD5Parser::ReportWarning("Unexpected token: ( was expected",elem.iLineNumber); \ - AI_MD5_SKIP_SPACES(); \ - sz = fast_atoreal_move(sz,(float&)vec.x); \ - AI_MD5_SKIP_SPACES(); \ - sz = fast_atoreal_move(sz,(float&)vec.y); \ - AI_MD5_SKIP_SPACES(); \ - sz = fast_atoreal_move(sz,(float&)vec.z); \ - AI_MD5_SKIP_SPACES(); \ - if (')' != *sz++) \ - MD5Parser::ReportWarning("Unexpected token: ) was expected",elem.iLineNumber); +// read a triple float in brackets: (1.0 1.0 1.0) +#define AI_MD5_READ_TRIPLE(vec) \ + AI_MD5_SKIP_SPACES(); \ + if ('(' != *sz++) \ + MD5Parser::ReportWarning("Unexpected token: ( was expected", elem.iLineNumber); \ + AI_MD5_SKIP_SPACES(); \ + sz = fast_atoreal_move(sz, (float &)vec.x); \ + AI_MD5_SKIP_SPACES(); \ + sz = fast_atoreal_move(sz, (float &)vec.y); \ + AI_MD5_SKIP_SPACES(); \ + sz = fast_atoreal_move(sz, (float &)vec.z); \ + AI_MD5_SKIP_SPACES(); \ + if (')' != *sz++) \ + MD5Parser::ReportWarning("Unexpected token: ) was expected", elem.iLineNumber); - // parse a string, enclosed in quotation marks or not -#define AI_MD5_PARSE_STRING(out) \ - bool bQuota = (*sz == '\"'); \ - const char* szStart = sz; \ - while (!IsSpaceOrNewLine(*sz))++sz; \ - const char* szEnd = sz; \ - if (bQuota) { \ - szStart++; \ - if ('\"' != *(szEnd-=1)) { \ +// parse a string, enclosed in quotation marks or not +#define AI_MD5_PARSE_STRING(out) \ + bool bQuota = (*sz == '\"'); \ + const char *szStart = sz; \ + while (!IsSpaceOrNewLine(*sz)) \ + ++sz; \ + const char *szEnd = sz; \ + if (bQuota) { \ + szStart++; \ + if ('\"' != *(szEnd -= 1)) { \ MD5Parser::ReportWarning("Expected closing quotation marks in string", \ - elem.iLineNumber); \ - continue; \ - } \ - } \ - out.length = (size_t)(szEnd - szStart); \ - ::memcpy(out.data,szStart,out.length); \ + elem.iLineNumber); \ + continue; \ + } \ + } \ + out.length = (size_t)(szEnd - szStart); \ + ::memcpy(out.data, szStart, out.length); \ out.data[out.length] = '\0'; - // parse a string, enclosed in quotation marks -#define AI_MD5_PARSE_STRING_IN_QUOTATION(out) \ - while('\"'!=*sz)++sz; \ - const char* szStart = ++sz; \ - while('\"'!=*sz)++sz; \ - const char* szEnd = (sz++); \ - out.length = (ai_uint32) (szEnd - szStart); \ - ::memcpy(out.data,szStart,out.length); \ +// parse a string, enclosed in quotation marks +#define AI_MD5_PARSE_STRING_IN_QUOTATION(out) \ + while ('\"' != *sz) \ + ++sz; \ + const char *szStart = ++sz; \ + while ('\"' != *sz) \ + ++sz; \ + const char *szEnd = (sz++); \ + out.length = (ai_uint32)(szEnd - szStart); \ + ::memcpy(out.data, szStart, out.length); \ out.data[out.length] = '\0'; // ------------------------------------------------------------------------------------------------ // .MD5MESH parsing function -MD5MeshParser::MD5MeshParser(SectionList& mSections) -{ +MD5MeshParser::MD5MeshParser(SectionList &mSections) { ASSIMP_LOG_DEBUG("MD5MeshParser begin"); // now parse all sections - for (SectionList::const_iterator iter = mSections.begin(), iterEnd = mSections.end();iter != iterEnd;++iter){ - if ( (*iter).mName == "numMeshes") { + for (SectionList::const_iterator iter = mSections.begin(), iterEnd = mSections.end(); iter != iterEnd; ++iter) { + if ((*iter).mName == "numMeshes") { mMeshes.reserve(::strtoul10((*iter).mGlobalValue.c_str())); - } - else if ( (*iter).mName == "numJoints") { + } else if ((*iter).mName == "numJoints") { mJoints.reserve(::strtoul10((*iter).mGlobalValue.c_str())); - } - else if ((*iter).mName == "joints") { + } else if ((*iter).mName == "joints") { // "origin" -1 ( -0.000000 0.016430 -0.006044 ) ( 0.707107 0.000000 0.707107 ) - for (const auto & elem : (*iter).mElements){ + for (const auto &elem : (*iter).mElements) { mJoints.push_back(BoneDesc()); - BoneDesc& desc = mJoints.back(); - - const char* sz = elem.szStart; - AI_MD5_PARSE_STRING_IN_QUOTATION(desc.mName); + BoneDesc &desc = mJoints.back(); + + const char *sz = elem.szStart; + AI_MD5_PARSE_STRING_IN_QUOTATION(desc.mName); AI_MD5_SKIP_SPACES(); // negative values, at least -1, is allowed here - desc.mParentIndex = (int)strtol10(sz,&sz); + desc.mParentIndex = (int)strtol10(sz, &sz); AI_MD5_READ_TRIPLE(desc.mPositionXYZ); AI_MD5_READ_TRIPLE(desc.mRotationQuat); // normalized quaternion, so w is not there } - } - else if ((*iter).mName == "mesh") { + } else if ((*iter).mName == "mesh") { mMeshes.push_back(MeshDesc()); - MeshDesc& desc = mMeshes.back(); + MeshDesc &desc = mMeshes.back(); - for (const auto & elem : (*iter).mElements){ - const char* sz = elem.szStart; + for (const auto &elem : (*iter).mElements) { + const char *sz = elem.szStart; // shader attribute - if (TokenMatch(sz,"shader",6)) { + if (TokenMatch(sz, "shader", 6)) { AI_MD5_SKIP_SPACES(); AI_MD5_PARSE_STRING_IN_QUOTATION(desc.mShader); } // numverts attribute - else if (TokenMatch(sz,"numverts",8)) { + else if (TokenMatch(sz, "numverts", 8)) { AI_MD5_SKIP_SPACES(); desc.mVertices.resize(strtoul10(sz)); } // numtris attribute - else if (TokenMatch(sz,"numtris",7)) { + else if (TokenMatch(sz, "numtris", 7)) { AI_MD5_SKIP_SPACES(); desc.mFaces.resize(strtoul10(sz)); } // numweights attribute - else if (TokenMatch(sz,"numweights",10)) { + else if (TokenMatch(sz, "numweights", 10)) { AI_MD5_SKIP_SPACES(); desc.mWeights.resize(strtoul10(sz)); } // vert attribute // "vert 0 ( 0.394531 0.513672 ) 0 1" - else if (TokenMatch(sz,"vert",4)) { + else if (TokenMatch(sz, "vert", 4)) { AI_MD5_SKIP_SPACES(); - const unsigned int idx = ::strtoul10(sz,&sz); + const unsigned int idx = ::strtoul10(sz, &sz); AI_MD5_SKIP_SPACES(); if (idx >= desc.mVertices.size()) - desc.mVertices.resize(idx+1); + desc.mVertices.resize(idx + 1); - VertexDesc& vert = desc.mVertices[idx]; + VertexDesc &vert = desc.mVertices[idx]; if ('(' != *sz++) - MD5Parser::ReportWarning("Unexpected token: ( was expected",elem.iLineNumber); + MD5Parser::ReportWarning("Unexpected token: ( was expected", elem.iLineNumber); AI_MD5_SKIP_SPACES(); - sz = fast_atoreal_move(sz,(float&)vert.mUV.x); + sz = fast_atoreal_move(sz, (float &)vert.mUV.x); AI_MD5_SKIP_SPACES(); - sz = fast_atoreal_move(sz,(float&)vert.mUV.y); + sz = fast_atoreal_move(sz, (float &)vert.mUV.y); AI_MD5_SKIP_SPACES(); if (')' != *sz++) - MD5Parser::ReportWarning("Unexpected token: ) was expected",elem.iLineNumber); + MD5Parser::ReportWarning("Unexpected token: ) was expected", elem.iLineNumber); AI_MD5_SKIP_SPACES(); - vert.mFirstWeight = ::strtoul10(sz,&sz); + vert.mFirstWeight = ::strtoul10(sz, &sz); AI_MD5_SKIP_SPACES(); - vert.mNumWeights = ::strtoul10(sz,&sz); + vert.mNumWeights = ::strtoul10(sz, &sz); } // tri attribute // "tri 0 15 13 12" - else if (TokenMatch(sz,"tri",3)) { + else if (TokenMatch(sz, "tri", 3)) { AI_MD5_SKIP_SPACES(); - const unsigned int idx = strtoul10(sz,&sz); + const unsigned int idx = strtoul10(sz, &sz); if (idx >= desc.mFaces.size()) - desc.mFaces.resize(idx+1); + desc.mFaces.resize(idx + 1); - aiFace& face = desc.mFaces[idx]; + aiFace &face = desc.mFaces[idx]; face.mIndices = new unsigned int[face.mNumIndices = 3]; - for (unsigned int i = 0; i < 3;++i) { + for (unsigned int i = 0; i < 3; ++i) { AI_MD5_SKIP_SPACES(); - face.mIndices[i] = strtoul10(sz,&sz); + face.mIndices[i] = strtoul10(sz, &sz); } } // weight attribute // "weight 362 5 0.500000 ( -3.553583 11.893474 9.719339 )" - else if (TokenMatch(sz,"weight",6)) { + else if (TokenMatch(sz, "weight", 6)) { AI_MD5_SKIP_SPACES(); - const unsigned int idx = strtoul10(sz,&sz); + const unsigned int idx = strtoul10(sz, &sz); AI_MD5_SKIP_SPACES(); if (idx >= desc.mWeights.size()) - desc.mWeights.resize(idx+1); + desc.mWeights.resize(idx + 1); - WeightDesc& weight = desc.mWeights[idx]; - weight.mBone = strtoul10(sz,&sz); + WeightDesc &weight = desc.mWeights[idx]; + weight.mBone = strtoul10(sz, &sz); AI_MD5_SKIP_SPACES(); - sz = fast_atoreal_move(sz,weight.mWeight); + sz = fast_atoreal_move(sz, weight.mWeight); AI_MD5_READ_TRIPLE(weight.vOffsetPosition); } } @@ -358,57 +355,54 @@ MD5MeshParser::MD5MeshParser(SectionList& mSections) // ------------------------------------------------------------------------------------------------ // .MD5ANIM parsing function -MD5AnimParser::MD5AnimParser(SectionList& mSections) -{ +MD5AnimParser::MD5AnimParser(SectionList &mSections) { ASSIMP_LOG_DEBUG("MD5AnimParser begin"); fFrameRate = 24.0f; mNumAnimatedComponents = UINT_MAX; - for (SectionList::const_iterator iter = mSections.begin(), iterEnd = mSections.end();iter != iterEnd;++iter) { - if ((*iter).mName == "hierarchy") { + for (SectionList::const_iterator iter = mSections.begin(), iterEnd = mSections.end(); iter != iterEnd; ++iter) { + if ((*iter).mName == "hierarchy") { // "sheath" 0 63 6 - for (const auto & elem : (*iter).mElements) { - mAnimatedBones.push_back ( AnimBoneDesc () ); - AnimBoneDesc& desc = mAnimatedBones.back(); + for (const auto &elem : (*iter).mElements) { + mAnimatedBones.push_back(AnimBoneDesc()); + AnimBoneDesc &desc = mAnimatedBones.back(); - const char* sz = elem.szStart; + const char *sz = elem.szStart; AI_MD5_PARSE_STRING_IN_QUOTATION(desc.mName); AI_MD5_SKIP_SPACES(); // parent index - negative values are allowed (at least -1) - desc.mParentIndex = ::strtol10(sz,&sz); + desc.mParentIndex = ::strtol10(sz, &sz); // flags (highest is 2^6-1) AI_MD5_SKIP_SPACES(); - if(63 < (desc.iFlags = ::strtoul10(sz,&sz))){ - MD5Parser::ReportWarning("Invalid flag combination in hierarchy section",elem.iLineNumber); + if (63 < (desc.iFlags = ::strtoul10(sz, &sz))) { + MD5Parser::ReportWarning("Invalid flag combination in hierarchy section", elem.iLineNumber); } AI_MD5_SKIP_SPACES(); // index of the first animation keyframe component for this joint - desc.iFirstKeyIndex = ::strtoul10(sz,&sz); + desc.iFirstKeyIndex = ::strtoul10(sz, &sz); } - } - else if((*iter).mName == "baseframe") { + } else if ((*iter).mName == "baseframe") { // ( -0.000000 0.016430 -0.006044 ) ( 0.707107 0.000242 0.707107 ) - for (const auto & elem : (*iter).mElements) { - const char* sz = elem.szStart; + for (const auto &elem : (*iter).mElements) { + const char *sz = elem.szStart; - mBaseFrames.push_back ( BaseFrameDesc () ); - BaseFrameDesc& desc = mBaseFrames.back(); + mBaseFrames.push_back(BaseFrameDesc()); + BaseFrameDesc &desc = mBaseFrames.back(); AI_MD5_READ_TRIPLE(desc.vPositionXYZ); AI_MD5_READ_TRIPLE(desc.vRotationQuat); } - } - else if((*iter).mName == "frame") { + } else if ((*iter).mName == "frame") { if (!(*iter).mGlobalValue.length()) { - MD5Parser::ReportWarning("A frame section must have a frame index",(*iter).iLineNumber); + MD5Parser::ReportWarning("A frame section must have a frame index", (*iter).iLineNumber); continue; } - mFrames.push_back ( FrameDesc () ); - FrameDesc& desc = mFrames.back(); + mFrames.push_back(FrameDesc()); + FrameDesc &desc = mFrames.back(); desc.iIndex = strtoul10((*iter).mGlobalValue.c_str()); // we do already know how much storage we will presumably need @@ -417,31 +411,28 @@ MD5AnimParser::MD5AnimParser(SectionList& mSections) } // now read all elements (continuous list of floats) - for (const auto & elem : (*iter).mElements){ - const char* sz = elem.szStart; - while (SkipSpacesAndLineEnd(&sz)) { - float f;sz = fast_atoreal_move(sz,f); + for (const auto &elem : (*iter).mElements) { + const char *sz = elem.szStart; + while (SkipSpacesAndLineEnd(&sz)) { + float f; + sz = fast_atoreal_move(sz, f); desc.mValues.push_back(f); } } - } - else if((*iter).mName == "numFrames") { + } else if ((*iter).mName == "numFrames") { mFrames.reserve(strtoul10((*iter).mGlobalValue.c_str())); - } - else if((*iter).mName == "numJoints") { + } else if ((*iter).mName == "numJoints") { const unsigned int num = strtoul10((*iter).mGlobalValue.c_str()); mAnimatedBones.reserve(num); // try to guess the number of animated components if that element is not given - if (UINT_MAX == mNumAnimatedComponents) { + if (UINT_MAX == mNumAnimatedComponents) { mNumAnimatedComponents = num * 6; } - } - else if((*iter).mName == "numAnimatedComponents") { - mAnimatedBones.reserve( strtoul10((*iter).mGlobalValue.c_str())); - } - else if((*iter).mName == "frameRate") { - fast_atoreal_move((*iter).mGlobalValue.c_str(),fFrameRate); + } else if ((*iter).mName == "numAnimatedComponents") { + mAnimatedBones.reserve(strtoul10((*iter).mGlobalValue.c_str())); + } else if ((*iter).mName == "frameRate") { + fast_atoreal_move((*iter).mGlobalValue.c_str(), fFrameRate); } } ASSIMP_LOG_DEBUG("MD5AnimParser end"); @@ -449,32 +440,27 @@ MD5AnimParser::MD5AnimParser(SectionList& mSections) // ------------------------------------------------------------------------------------------------ // .MD5CAMERA parsing function -MD5CameraParser::MD5CameraParser(SectionList& mSections) -{ +MD5CameraParser::MD5CameraParser(SectionList &mSections) { ASSIMP_LOG_DEBUG("MD5CameraParser begin"); fFrameRate = 24.0f; - for (SectionList::const_iterator iter = mSections.begin(), iterEnd = mSections.end();iter != iterEnd;++iter) { - if ((*iter).mName == "numFrames") { + for (SectionList::const_iterator iter = mSections.begin(), iterEnd = mSections.end(); iter != iterEnd; ++iter) { + if ((*iter).mName == "numFrames") { frames.reserve(strtoul10((*iter).mGlobalValue.c_str())); - } - else if ((*iter).mName == "frameRate") { - fFrameRate = fast_atof ((*iter).mGlobalValue.c_str()); - } - else if ((*iter).mName == "numCuts") { + } else if ((*iter).mName == "frameRate") { + fFrameRate = fast_atof((*iter).mGlobalValue.c_str()); + } else if ((*iter).mName == "numCuts") { cuts.reserve(strtoul10((*iter).mGlobalValue.c_str())); - } - else if ((*iter).mName == "cuts") { - for (const auto & elem : (*iter).mElements){ - cuts.push_back(strtoul10(elem.szStart)+1); + } else if ((*iter).mName == "cuts") { + for (const auto &elem : (*iter).mElements) { + cuts.push_back(strtoul10(elem.szStart) + 1); } - } - else if ((*iter).mName == "camera") { - for (const auto & elem : (*iter).mElements){ - const char* sz = elem.szStart; + } else if ((*iter).mName == "camera") { + for (const auto &elem : (*iter).mElements) { + const char *sz = elem.szStart; frames.push_back(CameraAnimFrameDesc()); - CameraAnimFrameDesc& cur = frames.back(); + CameraAnimFrameDesc &cur = frames.back(); AI_MD5_READ_TRIPLE(cur.vPositionXYZ); AI_MD5_READ_TRIPLE(cur.vRotationQuat); AI_MD5_SKIP_SPACES(); @@ -484,4 +470,3 @@ MD5CameraParser::MD5CameraParser(SectionList& mSections) } ASSIMP_LOG_DEBUG("MD5CameraParser end"); } - diff --git a/code/AssetLib/MDC/MDCLoader.cpp b/code/AssetLib/MDC/MDCLoader.cpp index 60146de81..5748fba0b 100644 --- a/code/AssetLib/MDC/MDCLoader.cpp +++ b/code/AssetLib/MDC/MDCLoader.cpp @@ -267,7 +267,7 @@ void MDCImporter::InternReadFile( // necessary that we don't crash if an exception occurs for (unsigned int i = 0; i < pScene->mNumMeshes; ++i) { - pScene->mMeshes[i] = NULL; + pScene->mMeshes[i] = nullptr; } // now read all surfaces @@ -347,8 +347,8 @@ void MDCImporter::InternReadFile( #endif - const MDC::CompressedVertex *pcCVerts = NULL; - int16_t *mdcCompVert = NULL; + const MDC::CompressedVertex *pcCVerts = nullptr; + int16_t *mdcCompVert = nullptr; // access compressed frames for large frame numbers, but never for the first if (this->configFrameID && pcSurface->ulNumCompFrames > 0) { @@ -359,7 +359,7 @@ void MDCImporter::InternReadFile( pcSurface->ulOffsetCompVerts) + *mdcCompVert * pcSurface->ulNumVertices; } else - mdcCompVert = NULL; + mdcCompVert = nullptr; } // copy all faces diff --git a/code/AssetLib/MDL/HalfLife/HL1MDLLoader.h b/code/AssetLib/MDL/HalfLife/HL1MDLLoader.h index c4293259c..2891ddb1e 100644 --- a/code/AssetLib/MDL/HalfLife/HL1MDLLoader.h +++ b/code/AssetLib/MDL/HalfLife/HL1MDLLoader.h @@ -222,12 +222,14 @@ void HL1MDLLoader::load_file_into_buffer(const std::string &file_path, unsigned std::unique_ptr file(io_->Open(file_path)); - if (file.get() == NULL) + if (file.get() == nullptr) { throw DeadlyImportError("Failed to open MDL file " + DefaultIOSystem::fileName(file_path) + "."); + } const size_t file_size = file->FileSize(); - if (file_size < sizeof(MDLFileHeader)) + if (file_size < sizeof(MDLFileHeader)) { throw DeadlyImportError("MDL file is too small."); + } buffer = new unsigned char[1 + file_size]; file->Read((void *)buffer, 1, file_size); diff --git a/code/AssetLib/MDL/MDLLoader.cpp b/code/AssetLib/MDL/MDLLoader.cpp index 463be1f1b..e917e3b5e 100644 --- a/code/AssetLib/MDL/MDLLoader.cpp +++ b/code/AssetLib/MDL/MDLLoader.cpp @@ -278,7 +278,7 @@ void MDLImporter::SizeCheck(const void *szPos) { // ------------------------------------------------------------------------------------------------ // Just for debugging purposes void MDLImporter::SizeCheck(const void *szPos, const char *szFile, unsigned int iLine) { - ai_assert(NULL != szFile); + ai_assert(nullptr != szFile); if (!szPos || (const unsigned char *)szPos > mBuffer + iFileSize) { // remove a directory if there is one const char *szFilePtr = ::strrchr(szFile, '\\'); @@ -304,7 +304,7 @@ void MDLImporter::SizeCheck(const void *szPos, const char *szFile, unsigned int // ------------------------------------------------------------------------------------------------ // Validate a quake file header void MDLImporter::ValidateHeader_Quake1(const MDL::Header *pcHeader) { - // some values may not be NULL + // some values may not be nullptr if (!pcHeader->num_frames) throw DeadlyImportError("[Quake 1 MDL] There are no frames in the file"); @@ -359,7 +359,7 @@ void FlipQuakeHeader(BE_NCONST MDL::Header *pcHeader) { // ------------------------------------------------------------------------------------------------ // Read a Quake 1 file void MDLImporter::InternReadFile_Quake1() { - ai_assert(NULL != pScene); + ai_assert(nullptr != pScene); BE_NCONST MDL::Header *pcHeader = (BE_NCONST MDL::Header *)this->mBuffer; @@ -548,7 +548,7 @@ void MDLImporter::SetupMaterialProperties_3DGS_MDL5_Quake1() { delete pScene->mTextures[0]; delete[] pScene->mTextures; - pScene->mTextures = NULL; + pScene->mTextures = nullptr; pScene->mNumTextures = 0; } else { clr.b = clr.a = clr.g = clr.r = 1.0f; @@ -572,7 +572,7 @@ void MDLImporter::SetupMaterialProperties_3DGS_MDL5_Quake1() { // ------------------------------------------------------------------------------------------------ // Read a MDL 3,4,5 file void MDLImporter::InternReadFile_3DGS_MDL345() { - ai_assert(NULL != pScene); + ai_assert(nullptr != pScene); // the header of MDL 3/4/5 is nearly identical to the original Quake1 header BE_NCONST MDL::Header *pcHeader = (BE_NCONST MDL::Header *)this->mBuffer; @@ -791,7 +791,7 @@ void MDLImporter::ImportUVCoordinate_3DGS_MDL345( aiVector3D &vOut, const MDL::TexCoord_MDL3 *pcSrc, unsigned int iIndex) { - ai_assert(NULL != pcSrc); + ai_assert(nullptr != pcSrc); const MDL::Header *const pcHeader = (const MDL::Header *)this->mBuffer; // validate UV indices @@ -860,7 +860,7 @@ void MDLImporter::CalculateUVCoordinates_MDL5() { // ------------------------------------------------------------------------------------------------ // Validate the header of a MDL7 file void MDLImporter::ValidateHeader_3DGS_MDL7(const MDL::Header_MDL7 *pcHeader) { - ai_assert(NULL != pcHeader); + ai_assert(nullptr != pcHeader); // There are some fixed sizes ... if (sizeof(MDL::ColorValue_MDL7) != pcHeader->colorvalue_stc_size) { @@ -887,7 +887,7 @@ void MDLImporter::ValidateHeader_3DGS_MDL7(const MDL::Header_MDL7 *pcHeader) { void MDLImporter::CalcAbsBoneMatrices_3DGS_MDL7(MDL::IntBone_MDL7 **apcOutBones) { const MDL::Header_MDL7 *pcHeader = (const MDL::Header_MDL7 *)this->mBuffer; const MDL::Bone_MDL7 *pcBones = (const MDL::Bone_MDL7 *)(pcHeader + 1); - ai_assert(NULL != apcOutBones); + ai_assert(nullptr != apcOutBones); // first find the bone that has NO parent, calculate the // animation matrix for it, then go on and search for the next parent @@ -979,7 +979,7 @@ MDL::IntBone_MDL7 **MDLImporter::LoadBones_3DGS_MDL7() { AI_MDL7_BONE_STRUCT_SIZE__NAME_IS_32_CHARS != pcHeader->bone_stc_size && AI_MDL7_BONE_STRUCT_SIZE__NAME_IS_NOT_THERE != pcHeader->bone_stc_size) { ASSIMP_LOG_WARN("Unknown size of bone data structure"); - return NULL; + return nullptr; } MDL::IntBone_MDL7 **apcBonesOut = new MDL::IntBone_MDL7 *[pcHeader->bones_num]; @@ -990,7 +990,7 @@ MDL::IntBone_MDL7 **MDLImporter::LoadBones_3DGS_MDL7() { CalcAbsBoneMatrices_3DGS_MDL7(apcBonesOut); return apcBonesOut; } - return NULL; + return nullptr; } // ------------------------------------------------------------------------------------------------ @@ -1014,7 +1014,7 @@ void MDLImporter::ReadFaces_3DGS_MDL7(const MDL::IntGroupInfo_MDL7 &groupInfo, unsigned int iIndex = pcGroupTris->v_index[c]; if (iIndex > (unsigned int)groupInfo.pcGroup->numverts) { // (we might need to read this section a second time - to process frame vertices correctly) - pcGroupTris->v_index[c] = (uint16_t) (iIndex = groupInfo.pcGroup->numverts - 1 ); + pcGroupTris->v_index[c] = (uint16_t)(iIndex = groupInfo.pcGroup->numverts - 1); ASSIMP_LOG_WARN("Index overflow in MDL7 vertex list"); } @@ -1337,7 +1337,7 @@ void MDLImporter::SortByMaterials_3DGS_MDL7( // ------------------------------------------------------------------------------------------------ // Read a MDL7 file void MDLImporter::InternReadFile_3DGS_MDL7() { - ai_assert(NULL != pScene); + ai_assert(nullptr != pScene); MDL::IntSharedData_MDL7 sharedData; @@ -1368,7 +1368,7 @@ void MDLImporter::InternReadFile_3DGS_MDL7() { // load all bones (they are shared by all groups, so // we'll need to add them to all groups/meshes later) - // apcBonesOut is a list of all bones or NULL if they could not been loaded + // apcBonesOut is a list of all bones or nullptr if they could not been loaded szCurrent += pcHeader->bones_num * pcHeader->bone_stc_size; sharedData.apcOutBones = this->LoadBones_3DGS_MDL7(); @@ -1558,9 +1558,9 @@ void MDLImporter::InternReadFile_3DGS_MDL7() { if (1 == pScene->mRootNode->mNumChildren && !sharedData.apcOutBones) { aiNode *pcOldRoot = this->pScene->mRootNode; pScene->mRootNode = pcOldRoot->mChildren[0]; - pcOldRoot->mChildren[0] = NULL; + pcOldRoot->mChildren[0] = nullptr; delete pcOldRoot; - pScene->mRootNode->mParent = NULL; + pScene->mRootNode->mParent = nullptr; } else pScene->mRootNode->mName.Set(""); @@ -1665,7 +1665,8 @@ void MDLImporter::ParseBoneTrafoKeys_3DGS_MDL7( // Attach bones to the output nodegraph void MDLImporter::AddBonesToNodeGraph_3DGS_MDL7(const MDL::IntBone_MDL7 **apcBones, aiNode *pcParent, uint16_t iParentIndex) { - ai_assert(NULL != apcBones && NULL != pcParent); + ai_assert(nullptr != apcBones); + ai_assert(nullptr != pcParent); // get a pointer to the header ... const MDL::Header_MDL7 *const pcHeader = (const MDL::Header_MDL7 *)this->mBuffer; @@ -1696,7 +1697,7 @@ void MDLImporter::AddBonesToNodeGraph_3DGS_MDL7(const MDL::IntBone_MDL7 **apcBon // Build output animations void MDLImporter::BuildOutputAnims_3DGS_MDL7( const MDL::IntBone_MDL7 **apcBonesOut) { - ai_assert(NULL != apcBonesOut); + ai_assert(nullptr != apcBonesOut); const MDL::Header_MDL7 *const pcHeader = (const MDL::Header_MDL7 *)mBuffer; // one animation ... @@ -1755,8 +1756,8 @@ void MDLImporter::BuildOutputAnims_3DGS_MDL7( void MDLImporter::AddAnimationBoneTrafoKey_3DGS_MDL7(unsigned int iTrafo, const MDL::BoneTransform_MDL7 *pcBoneTransforms, MDL::IntBone_MDL7 **apcBonesOut) { - ai_assert(NULL != pcBoneTransforms); - ai_assert(NULL != apcBonesOut); + ai_assert(nullptr != pcBoneTransforms); + ai_assert(nullptr != apcBonesOut); // first .. get the transformation matrix aiMatrix4x4 mTransform; @@ -1920,7 +1921,9 @@ void MDLImporter::JoinSkins_3DGS_MDL7( aiMaterial *pcMat1, aiMaterial *pcMat2, aiMaterial *pcMatOut) { - ai_assert(NULL != pcMat1 && NULL != pcMat2 && NULL != pcMatOut); + ai_assert(nullptr != pcMat1); + ai_assert(nullptr != pcMat2); + ai_assert(nullptr != pcMatOut); // first create a full copy of the first skin property set // and assign it to the output material diff --git a/code/AssetLib/MDL/MDLLoader.h b/code/AssetLib/MDL/MDLLoader.h index c747559c8..9c1b403c8 100644 --- a/code/AssetLib/MDL/MDLLoader.h +++ b/code/AssetLib/MDL/MDLLoader.h @@ -320,7 +320,7 @@ protected: /** Load the bone list of a MDL7 file * \return If the bones could be loaded successfully, a valid * array containing pointers to a temporary bone - * representation. NULL if the bones could not be loaded. + * representation. nullptr if the bones could not be loaded. */ MDL::IntBone_MDL7** LoadBones_3DGS_MDL7(); diff --git a/code/AssetLib/MDL/MDLMaterialLoader.cpp b/code/AssetLib/MDL/MDLMaterialLoader.cpp index 1f46c1edf..83939e98b 100644 --- a/code/AssetLib/MDL/MDLMaterialLoader.cpp +++ b/code/AssetLib/MDL/MDLMaterialLoader.cpp @@ -364,7 +364,7 @@ void MDLImporter::ParseTextureColorData(const unsigned char *szData, void MDLImporter::CreateTexture_3DGS_MDL5(const unsigned char *szData, unsigned int iType, unsigned int *piSkip) { - ai_assert(NULL != piSkip); + ai_assert(nullptr != piSkip); bool bNoRead = *piSkip == UINT_MAX; // allocate a new texture object @@ -428,7 +428,7 @@ void MDLImporter::CreateTexture_3DGS_MDL5(const unsigned char *szData, delete[] pc; } } else { - pcNew->pcData = NULL; + pcNew->pcData = nullptr; delete pcNew; } return; diff --git a/code/AssetLib/MMD/MMDImporter.cpp b/code/AssetLib/MMD/MMDImporter.cpp index 7c382bd09..0814f4813 100644 --- a/code/AssetLib/MMD/MMDImporter.cpp +++ b/code/AssetLib/MMD/MMDImporter.cpp @@ -134,7 +134,7 @@ void MMDImporter::InternReadFile(const std::string &file, aiScene *pScene, // ------------------------------------------------------------------------------------------------ void MMDImporter::CreateDataFromImport(const pmx::PmxModel *pModel, aiScene *pScene) { - if (pModel == NULL) { + if (pModel == nullptr) { return; } diff --git a/code/AssetLib/MMD/MMDPmdParser.h b/code/AssetLib/MMD/MMDPmdParser.h index dad9ed4bc..375126ec4 100644 --- a/code/AssetLib/MMD/MMDPmdParser.h +++ b/code/AssetLib/MMD/MMDPmdParser.h @@ -131,7 +131,7 @@ namespace pmd stream->read((char*) &index_count, sizeof(uint32_t)); stream->read((char*) &buffer, sizeof(char) * 20); char* pstar = strchr(buffer, '*'); - if (NULL == pstar) + if (nullptr == pstar) { texture_filename = std::string(buffer); sphere_filename.clear(); diff --git a/code/AssetLib/MS3D/MS3DLoader.cpp b/code/AssetLib/MS3D/MS3DLoader.cpp index 9f0149c2b..b5b6673f3 100644 --- a/code/AssetLib/MS3D/MS3DLoader.cpp +++ b/code/AssetLib/MS3D/MS3DLoader.cpp @@ -657,7 +657,7 @@ void MS3DImporter::InternReadFile( const std::string& pFile, } // fixup to pass the validation if not a single animation channel is non-trivial if (!anim->mNumChannels) { - anim->mChannels = NULL; + anim->mChannels = nullptr; } } } diff --git a/code/AssetLib/NFF/NFFLoader.cpp b/code/AssetLib/NFF/NFFLoader.cpp index edb64a34f..8d85b5acf 100644 --- a/code/AssetLib/NFF/NFFLoader.cpp +++ b/code/AssetLib/NFF/NFFLoader.cpp @@ -154,7 +154,7 @@ void NFFImporter::LoadNFF2MaterialTable(std::vector &output, return; } - ShadingInfo *curShader = NULL; + ShadingInfo *curShader = nullptr; // No read the file line per line char line[4096]; @@ -238,9 +238,9 @@ void NFFImporter::InternReadFile(const std::string &pFile, bool hasCam = false; - MeshInfo *currentMeshWithNormals = NULL; - MeshInfo *currentMesh = NULL; - MeshInfo *currentMeshWithUVCoords = NULL; + MeshInfo *currentMeshWithNormals = nullptr; + MeshInfo *currentMesh = nullptr; + MeshInfo *currentMeshWithUVCoords = nullptr; ShadingInfo s; // current material info @@ -542,7 +542,7 @@ void NFFImporter::InternReadFile(const std::string &pFile, // search the list of all shaders we have for this object whether // there is an identical one. In this case, we append our mesh // data to it. - MeshInfo *mesh = NULL; + MeshInfo *mesh = nullptr; for (std::vector::iterator it = meshes.begin() + objStart, end = meshes.end(); it != end; ++it) { if ((*it).shader == shader && (*it).matIndex == matIdx) { @@ -603,11 +603,11 @@ void NFFImporter::InternReadFile(const std::string &pFile, while (GetNextLine(buffer, line)) { sz = line; if ('p' == line[0] || TokenMatch(sz, "tpp", 3)) { - MeshInfo *out = NULL; + MeshInfo *out = nullptr; // 'tpp' - texture polygon patch primitive if ('t' == line[0]) { - currentMeshWithUVCoords = NULL; + currentMeshWithUVCoords = nullptr; for (auto &mesh : meshesWithUVCoords) { if (mesh.shader == s) { currentMeshWithUVCoords = &mesh; @@ -624,7 +624,7 @@ void NFFImporter::InternReadFile(const std::string &pFile, } // 'pp' - polygon patch primitive else if ('p' == line[1]) { - currentMeshWithNormals = NULL; + currentMeshWithNormals = nullptr; for (auto &mesh : meshesWithNormals) { if (mesh.shader == s) { currentMeshWithNormals = &mesh; @@ -642,7 +642,7 @@ void NFFImporter::InternReadFile(const std::string &pFile, } // 'p' - polygon primitive else { - currentMesh = NULL; + currentMesh = nullptr; for (auto &mesh : meshes) { if (mesh.shader == s) { currentMesh = &mesh; @@ -969,8 +969,8 @@ void NFFImporter::InternReadFile(const std::string &pFile, root->mNumChildren = numNamed + (hasCam ? 1 : 0) + (unsigned int)lights.size(); root->mNumMeshes = pScene->mNumMeshes - numNamed; - aiNode **ppcChildren = NULL; - unsigned int *pMeshes = NULL; + aiNode **ppcChildren = nullptr; + unsigned int *pMeshes = nullptr; if (root->mNumMeshes) pMeshes = root->mMeshes = new unsigned int[root->mNumMeshes]; if (root->mNumChildren) @@ -1037,7 +1037,7 @@ void NFFImporter::InternReadFile(const std::string &pFile, mesh->mNumFaces = (unsigned int)src.faces.size(); // Generate sub nodes for named meshes - if (src.name[0] && NULL != ppcChildren) { + if (src.name[0] && nullptr != ppcChildren) { aiNode *const node = *ppcChildren = new aiNode(); node->mParent = root; node->mNumMeshes = 1; diff --git a/code/AssetLib/Obj/ObjExporter.cpp b/code/AssetLib/Obj/ObjExporter.cpp index 350436959..882f3a917 100644 --- a/code/AssetLib/Obj/ObjExporter.cpp +++ b/code/AssetLib/Obj/ObjExporter.cpp @@ -70,14 +70,14 @@ void ExportSceneObj(const char* pFile,IOSystem* pIOSystem, const aiScene* pScene // we're still here - export successfully completed. Write both the main OBJ file and the material script { std::unique_ptr outfile (pIOSystem->Open(pFile,"wt")); - if(outfile == NULL) { + if (outfile == nullptr) { throw DeadlyExportError("could not open output .obj file: " + std::string(pFile)); } outfile->Write( exporter.mOutput.str().c_str(), static_cast(exporter.mOutput.tellp()),1); } { std::unique_ptr outfile (pIOSystem->Open(exporter.GetMaterialLibFileName(),"wt")); - if(outfile == NULL) { + if (outfile == nullptr) { throw DeadlyExportError("could not open output .mtl file: " + std::string(exporter.GetMaterialLibFileName())); } outfile->Write( exporter.mOutputMat.str().c_str(), static_cast(exporter.mOutputMat.tellp()),1); @@ -97,7 +97,7 @@ void ExportSceneObjNoMtl(const char* pFile,IOSystem* pIOSystem, const aiScene* p // we're still here - export successfully completed. Write both the main OBJ file and the material script { std::unique_ptr outfile (pIOSystem->Open(pFile,"wt")); - if(outfile == NULL) { + if (outfile == nullptr) { throw DeadlyExportError("could not open output .obj file: " + std::string(pFile)); } outfile->Write( exporter.mOutput.str().c_str(), static_cast(exporter.mOutput.tellp()),1); diff --git a/code/AssetLib/Obj/ObjFileData.h b/code/AssetLib/Obj/ObjFileData.h index 2974a4c23..5982be44d 100644 --- a/code/AssetLib/Obj/ObjFileData.h +++ b/code/AssetLib/Obj/ObjFileData.h @@ -41,12 +41,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #pragma once #ifndef OBJ_FILEDATA_H_INC -# define OBJ_FILEDATA_H_INC +#define OBJ_FILEDATA_H_INC -# include -# include -# include -# include +#include +#include +#include +#include namespace Assimp { namespace ObjFile { @@ -215,7 +215,11 @@ struct Mesh { /// Constructor explicit Mesh(const std::string &name) : - m_name(name), m_pMaterial(NULL), m_uiNumIndices(0), m_uiMaterialIndex(NoMaterial), m_hasNormals(false) { + m_name(name), + m_pMaterial(nullptr), + m_uiNumIndices(0), + m_uiMaterialIndex(NoMaterial), + m_hasNormals(false) { memset(m_uiUVCoordinates, 0, sizeof(unsigned int) * AI_MAX_NUMBER_OF_TEXTURECOORDS); } @@ -275,13 +279,13 @@ struct Model { //! \brief The default class constructor Model() : m_ModelName(""), - m_pCurrent(NULL), - m_pCurrentMaterial(NULL), - m_pDefaultMaterial(NULL), - m_pGroupFaceIDs(NULL), + m_pCurrent(nullptr), + m_pCurrentMaterial(nullptr), + m_pDefaultMaterial(nullptr), + m_pGroupFaceIDs(nullptr), m_strActiveGroup(""), m_TextureCoordDim(0), - m_pCurrentMesh(NULL) { + m_pCurrentMesh(nullptr) { // empty } diff --git a/code/AssetLib/Obj/ObjFileImporter.cpp b/code/AssetLib/Obj/ObjFileImporter.cpp index 462245e44..b6e1f9061 100644 --- a/code/AssetLib/Obj/ObjFileImporter.cpp +++ b/code/AssetLib/Obj/ObjFileImporter.cpp @@ -252,9 +252,9 @@ void ObjFileImporter::CreateDataFromImport(const ObjFile::Model *pModel, aiScene aiNode *ObjFileImporter::createNodes(const ObjFile::Model *pModel, const ObjFile::Object *pObject, aiNode *pParent, aiScene *pScene, std::vector &MeshArray) { - ai_assert(NULL != pModel); - if (NULL == pObject) { - return NULL; + ai_assert(nullptr != pModel); + if (nullptr == pObject) { + return nullptr; } // Store older mesh size to be able to computes mesh offsets for new mesh instances @@ -264,7 +264,7 @@ aiNode *ObjFileImporter::createNodes(const ObjFile::Model *pModel, const ObjFile pNode->mName = pObject->m_strObjName; // If we have a parent node, store it - ai_assert(NULL != pParent); + ai_assert(nullptr != pParent); appendChildToParentNode(pParent, pNode); for (size_t i = 0; i < pObject->m_Meshes.size(); ++i) { @@ -308,20 +308,20 @@ aiNode *ObjFileImporter::createNodes(const ObjFile::Model *pModel, const ObjFile // Create topology data aiMesh *ObjFileImporter::createTopology(const ObjFile::Model *pModel, const ObjFile::Object *pData, unsigned int meshIndex) { // Checking preconditions - ai_assert(NULL != pModel); + ai_assert(nullptr != pModel); - if (NULL == pData) { - return NULL; + if (nullptr == pData) { + return nullptr; } // Create faces ObjFile::Mesh *pObjMesh = pModel->m_Meshes[meshIndex]; if (!pObjMesh) { - return NULL; + return nullptr; } if (pObjMesh->m_Faces.empty()) { - return NULL; + return nullptr; } std::unique_ptr pMesh(new aiMesh); @@ -331,7 +331,7 @@ aiMesh *ObjFileImporter::createTopology(const ObjFile::Model *pModel, const ObjF for (size_t index = 0; index < pObjMesh->m_Faces.size(); index++) { ObjFile::Face *const inp = pObjMesh->m_Faces[index]; - ai_assert(NULL != inp); + ai_assert(nullptr != inp); if (inp->m_PrimitiveType == aiPrimitiveType_LINE) { pMesh->mNumFaces += static_cast(inp->m_vertices.size() - 1); @@ -400,7 +400,7 @@ void ObjFileImporter::createVertexArray(const ObjFile::Model *pModel, aiMesh *pMesh, unsigned int numIndices) { // Checking preconditions - ai_assert(NULL != pCurrentObject); + ai_assert(nullptr != pCurrentObject); // Break, if no faces are stored in object if (pCurrentObject->m_Meshes.empty()) @@ -408,7 +408,7 @@ void ObjFileImporter::createVertexArray(const ObjFile::Model *pModel, // Get current mesh ObjFile::Mesh *pObjMesh = pModel->m_Meshes[uiMeshIndex]; - if (NULL == pObjMesh || pObjMesh->m_uiNumIndices < 1) { + if (nullptr == pObjMesh || pObjMesh->m_uiNumIndices < 1) { return; } @@ -561,7 +561,7 @@ void ObjFileImporter::addTextureMappingModeProperty(aiMaterial *mat, aiTextureTy // ------------------------------------------------------------------------------------------------ // Creates the material void ObjFileImporter::createMaterials(const ObjFile::Model *pModel, aiScene *pScene) { - if (NULL == pScene) { + if (nullptr == pScene) { return; } @@ -717,8 +717,8 @@ void ObjFileImporter::createMaterials(const ObjFile::Model *pModel, aiScene *pSc // Appends this node to the parent node void ObjFileImporter::appendChildToParentNode(aiNode *pParent, aiNode *pChild) { // Checking preconditions - ai_assert(NULL != pParent); - ai_assert(NULL != pChild); + ai_assert(nullptr != pParent); + ai_assert(nullptr != pChild); // Assign parent to child pChild->mParent = pParent; diff --git a/code/AssetLib/Obj/ObjFileMtlImporter.cpp b/code/AssetLib/Obj/ObjFileMtlImporter.cpp index 8b529758e..6464a55e0 100644 --- a/code/AssetLib/Obj/ObjFileMtlImporter.cpp +++ b/code/AssetLib/Obj/ObjFileMtlImporter.cpp @@ -200,7 +200,7 @@ void ObjFileMtlImporter::load() { // ------------------------------------------------------------------- // Loads a color definition void ObjFileMtlImporter::getColorRGBA(aiColor3D *pColor) { - ai_assert(NULL != pColor); + ai_assert(nullptr != pColor); ai_real r(0.0), g(0.0), b(0.0); m_DataIt = getFloat(m_DataIt, m_DataItEnd, r); @@ -274,7 +274,7 @@ void ObjFileMtlImporter::createMaterial() { // ------------------------------------------------------------------- // Gets a texture name from data. void ObjFileMtlImporter::getTexture() { - aiString *out(NULL); + aiString *out(nullptr); int clampIndex = -1; const char *pPtr(&(*m_DataIt)); @@ -332,7 +332,7 @@ void ObjFileMtlImporter::getTexture() { std::string texture; m_DataIt = getName(m_DataIt, m_DataItEnd, texture); - if (NULL != out) { + if (nullptr != out) { out->Set(texture); } } diff --git a/code/AssetLib/Obj/ObjFileParser.cpp b/code/AssetLib/Obj/ObjFileParser.cpp index a825b96ca..a8039ae23 100644 --- a/code/AssetLib/Obj/ObjFileParser.cpp +++ b/code/AssetLib/Obj/ObjFileParser.cpp @@ -253,7 +253,6 @@ static bool isDataDefinitionEnd(const char *tmp) { if (*tmp == '\\') { tmp++; if (IsLineEnd(*tmp)) { - tmp++; return true; } } @@ -495,19 +494,19 @@ void ObjFileParser::getFace(aiPrimitiveType type) { } // Set active material, if one set - if (NULL != m_pModel->m_pCurrentMaterial) { + if (nullptr != m_pModel->m_pCurrentMaterial) { face->m_pMaterial = m_pModel->m_pCurrentMaterial; } else { face->m_pMaterial = m_pModel->m_pDefaultMaterial; } // Create a default object, if nothing is there - if (NULL == m_pModel->m_pCurrent) { + if (nullptr == m_pModel->m_pCurrent) { createObject(DefaultObjName); } // Assign face to mesh - if (NULL == m_pModel->m_pCurrentMesh) { + if (nullptr == m_pModel->m_pCurrentMesh) { createMesh(DefaultObjName); } @@ -754,7 +753,7 @@ void ObjFileParser::getObjectName() { std::string strObjectName(pStart, &(*m_DataIt)); if (!strObjectName.empty()) { // Reset current object - m_pModel->m_pCurrent = NULL; + m_pModel->m_pCurrent = nullptr; // Search for actual object for (std::vector::const_iterator it = m_pModel->m_Objects.begin(); @@ -767,7 +766,7 @@ void ObjFileParser::getObjectName() { } // Allocate a new object, if current one was not found before - if (NULL == m_pModel->m_pCurrent) { + if (nullptr == m_pModel->m_pCurrent) { createObject(strObjectName); } } @@ -776,7 +775,7 @@ void ObjFileParser::getObjectName() { // ------------------------------------------------------------------- // Creates a new object instance void ObjFileParser::createObject(const std::string &objName) { - ai_assert(NULL != m_pModel); + ai_assert(nullptr != m_pModel); m_pModel->m_pCurrent = new ObjFile::Object; m_pModel->m_pCurrent->m_strObjName = objName; @@ -793,11 +792,12 @@ void ObjFileParser::createObject(const std::string &objName) { // ------------------------------------------------------------------- // Creates a new mesh void ObjFileParser::createMesh(const std::string &meshName) { - ai_assert(NULL != m_pModel); + ai_assert(nullptr != m_pModel); + m_pModel->m_pCurrentMesh = new ObjFile::Mesh(meshName); m_pModel->m_Meshes.push_back(m_pModel->m_pCurrentMesh); unsigned int meshId = static_cast(m_pModel->m_Meshes.size() - 1); - if (NULL != m_pModel->m_pCurrent) { + if (nullptr != m_pModel->m_pCurrent) { m_pModel->m_pCurrent->m_Meshes.push_back(meshId); } else { ASSIMP_LOG_ERROR("OBJ: No object detected to attach a new mesh instance."); diff --git a/code/AssetLib/Ogre/OgreStructs.cpp b/code/AssetLib/Ogre/OgreStructs.cpp index 69cfae1cd..4a4f9479e 100644 --- a/code/AssetLib/Ogre/OgreStructs.cpp +++ b/code/AssetLib/Ogre/OgreStructs.cpp @@ -43,199 +43,183 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef ASSIMP_BUILD_NO_OGRE_IMPORTER #include "OgreStructs.h" +#include #include #include #include -#include - -namespace Assimp -{ -namespace Ogre -{ +namespace Assimp { +namespace Ogre { // VertexElement VertexElement::VertexElement() : - index(0), - source(0), - offset(0), - type(VET_FLOAT1), - semantic(VES_POSITION) -{ + index(0), + source(0), + offset(0), + type(VET_FLOAT1), + semantic(VES_POSITION) { } -size_t VertexElement::Size() const -{ +size_t VertexElement::Size() const { return TypeSize(type); } -size_t VertexElement::ComponentCount() const -{ +size_t VertexElement::ComponentCount() const { return ComponentCount(type); } -size_t VertexElement::ComponentCount(Type type) -{ - switch(type) - { - case VET_COLOUR: - case VET_COLOUR_ABGR: - case VET_COLOUR_ARGB: - case VET_FLOAT1: - case VET_DOUBLE1: - case VET_SHORT1: - case VET_USHORT1: - case VET_INT1: - case VET_UINT1: - return 1; - case VET_FLOAT2: - case VET_DOUBLE2: - case VET_SHORT2: - case VET_USHORT2: - case VET_INT2: - case VET_UINT2: - return 2; - case VET_FLOAT3: - case VET_DOUBLE3: - case VET_SHORT3: - case VET_USHORT3: - case VET_INT3: - case VET_UINT3: - return 3; - case VET_FLOAT4: - case VET_DOUBLE4: - case VET_SHORT4: - case VET_USHORT4: - case VET_INT4: - case VET_UINT4: - case VET_UBYTE4: - return 4; +size_t VertexElement::ComponentCount(Type type) { + switch (type) { + case VET_COLOUR: + case VET_COLOUR_ABGR: + case VET_COLOUR_ARGB: + case VET_FLOAT1: + case VET_DOUBLE1: + case VET_SHORT1: + case VET_USHORT1: + case VET_INT1: + case VET_UINT1: + return 1; + case VET_FLOAT2: + case VET_DOUBLE2: + case VET_SHORT2: + case VET_USHORT2: + case VET_INT2: + case VET_UINT2: + return 2; + case VET_FLOAT3: + case VET_DOUBLE3: + case VET_SHORT3: + case VET_USHORT3: + case VET_INT3: + case VET_UINT3: + return 3; + case VET_FLOAT4: + case VET_DOUBLE4: + case VET_SHORT4: + case VET_USHORT4: + case VET_INT4: + case VET_UINT4: + case VET_UBYTE4: + return 4; } return 0; } -size_t VertexElement::TypeSize(Type type) -{ - switch(type) - { - case VET_COLOUR: - case VET_COLOUR_ABGR: - case VET_COLOUR_ARGB: - return sizeof(unsigned int); - case VET_FLOAT1: - return sizeof(float); - case VET_FLOAT2: - return sizeof(float)*2; - case VET_FLOAT3: - return sizeof(float)*3; - case VET_FLOAT4: - return sizeof(float)*4; - case VET_DOUBLE1: - return sizeof(double); - case VET_DOUBLE2: - return sizeof(double)*2; - case VET_DOUBLE3: - return sizeof(double)*3; - case VET_DOUBLE4: - return sizeof(double)*4; - case VET_SHORT1: - return sizeof(short); - case VET_SHORT2: - return sizeof(short)*2; - case VET_SHORT3: - return sizeof(short)*3; - case VET_SHORT4: - return sizeof(short)*4; - case VET_USHORT1: - return sizeof(unsigned short); - case VET_USHORT2: - return sizeof(unsigned short)*2; - case VET_USHORT3: - return sizeof(unsigned short)*3; - case VET_USHORT4: - return sizeof(unsigned short)*4; - case VET_INT1: - return sizeof(int); - case VET_INT2: - return sizeof(int)*2; - case VET_INT3: - return sizeof(int)*3; - case VET_INT4: - return sizeof(int)*4; - case VET_UINT1: - return sizeof(unsigned int); - case VET_UINT2: - return sizeof(unsigned int)*2; - case VET_UINT3: - return sizeof(unsigned int)*3; - case VET_UINT4: - return sizeof(unsigned int)*4; - case VET_UBYTE4: - return sizeof(unsigned char)*4; +size_t VertexElement::TypeSize(Type type) { + switch (type) { + case VET_COLOUR: + case VET_COLOUR_ABGR: + case VET_COLOUR_ARGB: + return sizeof(unsigned int); + case VET_FLOAT1: + return sizeof(float); + case VET_FLOAT2: + return sizeof(float) * 2; + case VET_FLOAT3: + return sizeof(float) * 3; + case VET_FLOAT4: + return sizeof(float) * 4; + case VET_DOUBLE1: + return sizeof(double); + case VET_DOUBLE2: + return sizeof(double) * 2; + case VET_DOUBLE3: + return sizeof(double) * 3; + case VET_DOUBLE4: + return sizeof(double) * 4; + case VET_SHORT1: + return sizeof(short); + case VET_SHORT2: + return sizeof(short) * 2; + case VET_SHORT3: + return sizeof(short) * 3; + case VET_SHORT4: + return sizeof(short) * 4; + case VET_USHORT1: + return sizeof(unsigned short); + case VET_USHORT2: + return sizeof(unsigned short) * 2; + case VET_USHORT3: + return sizeof(unsigned short) * 3; + case VET_USHORT4: + return sizeof(unsigned short) * 4; + case VET_INT1: + return sizeof(int); + case VET_INT2: + return sizeof(int) * 2; + case VET_INT3: + return sizeof(int) * 3; + case VET_INT4: + return sizeof(int) * 4; + case VET_UINT1: + return sizeof(unsigned int); + case VET_UINT2: + return sizeof(unsigned int) * 2; + case VET_UINT3: + return sizeof(unsigned int) * 3; + case VET_UINT4: + return sizeof(unsigned int) * 4; + case VET_UBYTE4: + return sizeof(unsigned char) * 4; } return 0; } -std::string VertexElement::TypeToString() -{ +std::string VertexElement::TypeToString() { return TypeToString(type); } -std::string VertexElement::TypeToString(Type type) -{ - switch(type) - { - case VET_COLOUR: return "COLOUR"; - case VET_COLOUR_ABGR: return "COLOUR_ABGR"; - case VET_COLOUR_ARGB: return "COLOUR_ARGB"; - case VET_FLOAT1: return "FLOAT1"; - case VET_FLOAT2: return "FLOAT2"; - case VET_FLOAT3: return "FLOAT3"; - case VET_FLOAT4: return "FLOAT4"; - case VET_DOUBLE1: return "DOUBLE1"; - case VET_DOUBLE2: return "DOUBLE2"; - case VET_DOUBLE3: return "DOUBLE3"; - case VET_DOUBLE4: return "DOUBLE4"; - case VET_SHORT1: return "SHORT1"; - case VET_SHORT2: return "SHORT2"; - case VET_SHORT3: return "SHORT3"; - case VET_SHORT4: return "SHORT4"; - case VET_USHORT1: return "USHORT1"; - case VET_USHORT2: return "USHORT2"; - case VET_USHORT3: return "USHORT3"; - case VET_USHORT4: return "USHORT4"; - case VET_INT1: return "INT1"; - case VET_INT2: return "INT2"; - case VET_INT3: return "INT3"; - case VET_INT4: return "INT4"; - case VET_UINT1: return "UINT1"; - case VET_UINT2: return "UINT2"; - case VET_UINT3: return "UINT3"; - case VET_UINT4: return "UINT4"; - case VET_UBYTE4: return "UBYTE4"; +std::string VertexElement::TypeToString(Type type) { + switch (type) { + case VET_COLOUR: return "COLOUR"; + case VET_COLOUR_ABGR: return "COLOUR_ABGR"; + case VET_COLOUR_ARGB: return "COLOUR_ARGB"; + case VET_FLOAT1: return "FLOAT1"; + case VET_FLOAT2: return "FLOAT2"; + case VET_FLOAT3: return "FLOAT3"; + case VET_FLOAT4: return "FLOAT4"; + case VET_DOUBLE1: return "DOUBLE1"; + case VET_DOUBLE2: return "DOUBLE2"; + case VET_DOUBLE3: return "DOUBLE3"; + case VET_DOUBLE4: return "DOUBLE4"; + case VET_SHORT1: return "SHORT1"; + case VET_SHORT2: return "SHORT2"; + case VET_SHORT3: return "SHORT3"; + case VET_SHORT4: return "SHORT4"; + case VET_USHORT1: return "USHORT1"; + case VET_USHORT2: return "USHORT2"; + case VET_USHORT3: return "USHORT3"; + case VET_USHORT4: return "USHORT4"; + case VET_INT1: return "INT1"; + case VET_INT2: return "INT2"; + case VET_INT3: return "INT3"; + case VET_INT4: return "INT4"; + case VET_UINT1: return "UINT1"; + case VET_UINT2: return "UINT2"; + case VET_UINT3: return "UINT3"; + case VET_UINT4: return "UINT4"; + case VET_UBYTE4: return "UBYTE4"; } return "Uknown_VertexElement::Type"; } -std::string VertexElement::SemanticToString() -{ +std::string VertexElement::SemanticToString() { return SemanticToString(semantic); } -std::string VertexElement::SemanticToString(Semantic semantic) -{ - switch(semantic) - { - case VES_POSITION: return "POSITION"; - case VES_BLEND_WEIGHTS: return "BLEND_WEIGHTS"; - case VES_BLEND_INDICES: return "BLEND_INDICES"; - case VES_NORMAL: return "NORMAL"; - case VES_DIFFUSE: return "DIFFUSE"; - case VES_SPECULAR: return "SPECULAR"; - case VES_TEXTURE_COORDINATES: return "TEXTURE_COORDINATES"; - case VES_BINORMAL: return "BINORMAL"; - case VES_TANGENT: return "TANGENT"; +std::string VertexElement::SemanticToString(Semantic semantic) { + switch (semantic) { + case VES_POSITION: return "POSITION"; + case VES_BLEND_WEIGHTS: return "BLEND_WEIGHTS"; + case VES_BLEND_INDICES: return "BLEND_INDICES"; + case VES_NORMAL: return "NORMAL"; + case VES_DIFFUSE: return "DIFFUSE"; + case VES_SPECULAR: return "SPECULAR"; + case VES_TEXTURE_COORDINATES: return "TEXTURE_COORDINATES"; + case VES_BINORMAL: return "BINORMAL"; + case VES_TANGENT: return "TANGENT"; } return "Uknown_VertexElement::Semantic"; } @@ -243,27 +227,21 @@ std::string VertexElement::SemanticToString(Semantic semantic) // IVertexData IVertexData::IVertexData() : - count(0) -{ + count(0) { } -bool IVertexData::HasBoneAssignments() const -{ +bool IVertexData::HasBoneAssignments() const { return !boneAssignments.empty(); } -void IVertexData::AddVertexMapping(uint32_t oldIndex, uint32_t newIndex) -{ +void IVertexData::AddVertexMapping(uint32_t oldIndex, uint32_t newIndex) { BoneAssignmentsForVertex(oldIndex, newIndex, boneAssignmentsMap[newIndex]); vertexIndexMapping[oldIndex].push_back(newIndex); } -void IVertexData::BoneAssignmentsForVertex(uint32_t currentIndex, uint32_t newIndex, VertexBoneAssignmentList &dest) const -{ - for (const auto &boneAssign : boneAssignments) - { - if (boneAssign.vertexIndex == currentIndex) - { +void IVertexData::BoneAssignmentsForVertex(uint32_t currentIndex, uint32_t newIndex, VertexBoneAssignmentList &dest) const { + for (const auto &boneAssign : boneAssignments) { + if (boneAssign.vertexIndex == currentIndex) { VertexBoneAssignment a = boneAssign; a.vertexIndex = newIndex; dest.push_back(a); @@ -271,15 +249,12 @@ void IVertexData::BoneAssignmentsForVertex(uint32_t currentIndex, uint32_t newIn } } -AssimpVertexBoneWeightList IVertexData::AssimpBoneWeights(size_t vertices) -{ +AssimpVertexBoneWeightList IVertexData::AssimpBoneWeights(size_t vertices) { AssimpVertexBoneWeightList weights; - for(size_t vi=0; vi(vi)]; - for (VertexBoneAssignmentList::const_iterator iter=vertexWeights.begin(), end=vertexWeights.end(); - iter!=end; ++iter) - { + for (VertexBoneAssignmentList::const_iterator iter = vertexWeights.begin(), end = vertexWeights.end(); + iter != end; ++iter) { std::vector &boneWeights = weights[iter->boneIndex]; boneWeights.push_back(aiVertexWeight(static_cast(vi), iter->weight)); } @@ -287,11 +262,9 @@ AssimpVertexBoneWeightList IVertexData::AssimpBoneWeights(size_t vertices) return weights; } -std::set IVertexData::ReferencedBonesByWeights() const -{ +std::set IVertexData::ReferencedBonesByWeights() const { std::set referenced; - for (const auto &boneAssign : boneAssignments) - { + for (const auto &boneAssign : boneAssignments) { referenced.insert(boneAssign.boneIndex); } return referenced; @@ -299,44 +272,36 @@ std::set IVertexData::ReferencedBonesByWeights() const // VertexData -VertexData::VertexData() -{ +VertexData::VertexData() { } -VertexData::~VertexData() -{ +VertexData::~VertexData() { Reset(); } -void VertexData::Reset() -{ +void VertexData::Reset() { // Releases shared ptr memory streams. vertexBindings.clear(); vertexElements.clear(); } -uint32_t VertexData::VertexSize(uint16_t source) const -{ +uint32_t VertexData::VertexSize(uint16_t source) const { uint32_t size = 0; - for(const auto &element : vertexElements) - { + for (const auto &element : vertexElements) { if (element.source == source) size += static_cast(element.Size()); } return size; } -MemoryStream *VertexData::VertexBuffer(uint16_t source) -{ +MemoryStream *VertexData::VertexBuffer(uint16_t source) { if (vertexBindings.find(source) != vertexBindings.end()) return vertexBindings[source].get(); return 0; } -VertexElement *VertexData::GetVertexElement(VertexElement::Semantic semantic, uint16_t index) -{ - for(auto & element : vertexElements) - { +VertexElement *VertexData::GetVertexElement(VertexElement::Semantic semantic, uint16_t index) { + for (auto &element : vertexElements) { if (element.semantic == semantic && element.index == index) return &element; } @@ -345,125 +310,108 @@ VertexElement *VertexData::GetVertexElement(VertexElement::Semantic semantic, ui // VertexDataXml -VertexDataXml::VertexDataXml() -{ +VertexDataXml::VertexDataXml() { } -bool VertexDataXml::HasPositions() const -{ +bool VertexDataXml::HasPositions() const { return !positions.empty(); } -bool VertexDataXml::HasNormals() const -{ +bool VertexDataXml::HasNormals() const { return !normals.empty(); } -bool VertexDataXml::HasTangents() const -{ +bool VertexDataXml::HasTangents() const { return !tangents.empty(); } -bool VertexDataXml::HasUvs() const -{ +bool VertexDataXml::HasUvs() const { return !uvs.empty(); } -size_t VertexDataXml::NumUvs() const -{ +size_t VertexDataXml::NumUvs() const { return uvs.size(); } // IndexData IndexData::IndexData() : - count(0), - faceCount(0), - is32bit(false) -{ + count(0), + faceCount(0), + is32bit(false) { } -IndexData::~IndexData() -{ +IndexData::~IndexData() { Reset(); } -void IndexData::Reset() -{ +void IndexData::Reset() { // Release shared ptr memory stream. buffer.reset(); } -size_t IndexData::IndexSize() const -{ +size_t IndexData::IndexSize() const { return (is32bit ? sizeof(uint32_t) : sizeof(uint16_t)); } -size_t IndexData::FaceSize() const -{ +size_t IndexData::FaceSize() const { return IndexSize() * 3; } // Mesh -Mesh::Mesh() - : hasSkeletalAnimations(false) - , skeleton(NULL) - , sharedVertexData(NULL) - , subMeshes() - , animations() - , poses() -{ +Mesh::Mesh() : + hasSkeletalAnimations(false), + skeleton(nullptr), + sharedVertexData(nullptr), + subMeshes(), + animations(), + poses() { } -Mesh::~Mesh() -{ +Mesh::~Mesh() { Reset(); } -void Mesh::Reset() -{ +void Mesh::Reset() { OGRE_SAFE_DELETE(skeleton) OGRE_SAFE_DELETE(sharedVertexData) - for(auto &mesh : subMeshes) { + for (auto &mesh : subMeshes) { OGRE_SAFE_DELETE(mesh) } subMeshes.clear(); - for(auto &anim : animations) { + for (auto &anim : animations) { OGRE_SAFE_DELETE(anim) } animations.clear(); - for(auto &pose : poses) { + for (auto &pose : poses) { OGRE_SAFE_DELETE(pose) } poses.clear(); } -size_t Mesh::NumSubMeshes() const -{ +size_t Mesh::NumSubMeshes() const { return subMeshes.size(); } -SubMesh *Mesh::GetSubMesh( size_t index ) const -{ - for ( size_t i = 0; i < subMeshes.size(); ++i ) { - if ( subMeshes[ i ]->index == index ) { - return subMeshes[ i ]; +SubMesh *Mesh::GetSubMesh(size_t index) const { + for (size_t i = 0; i < subMeshes.size(); ++i) { + if (subMeshes[i]->index == index) { + return subMeshes[i]; } } return 0; } -void Mesh::ConvertToAssimpScene(aiScene* dest) -{ - if ( nullptr == dest ) { +void Mesh::ConvertToAssimpScene(aiScene *dest) { + if (nullptr == dest) { return; } // Setup dest->mNumMeshes = static_cast(NumSubMeshes()); - dest->mMeshes = new aiMesh*[dest->mNumMeshes]; + dest->mMeshes = new aiMesh *[dest->mNumMeshes]; // Create root node dest->mRootNode = new aiNode(); @@ -471,35 +419,30 @@ void Mesh::ConvertToAssimpScene(aiScene* dest) dest->mRootNode->mMeshes = new unsigned int[dest->mRootNode->mNumMeshes]; // Export meshes - for(size_t i=0; imNumMeshes; ++i) { + for (size_t i = 0; i < dest->mNumMeshes; ++i) { dest->mMeshes[i] = subMeshes[i]->ConvertToAssimpMesh(this); dest->mRootNode->mMeshes[i] = static_cast(i); } // Export skeleton - if (skeleton) - { + if (skeleton) { // Bones - if (!skeleton->bones.empty()) - { + if (!skeleton->bones.empty()) { BoneList rootBones = skeleton->RootBones(); dest->mRootNode->mNumChildren = static_cast(rootBones.size()); - dest->mRootNode->mChildren = new aiNode*[dest->mRootNode->mNumChildren]; + dest->mRootNode->mChildren = new aiNode *[dest->mRootNode->mNumChildren]; - for(size_t i=0, len=rootBones.size(); imRootNode->mChildren[i] = rootBones[i]->ConvertToAssimpNode(skeleton, dest->mRootNode); } } // Animations - if (!skeleton->animations.empty()) - { + if (!skeleton->animations.empty()) { dest->mNumAnimations = static_cast(skeleton->animations.size()); - dest->mAnimations = new aiAnimation*[dest->mNumAnimations]; + dest->mAnimations = new aiAnimation *[dest->mNumAnimations]; - for(size_t i=0, len=skeleton->animations.size(); ianimations.size(); i < len; ++i) { dest->mAnimations[i] = skeleton->animations[i]->ConvertToAssimpAnimation(); } } @@ -509,34 +452,29 @@ void Mesh::ConvertToAssimpScene(aiScene* dest) // ISubMesh ISubMesh::ISubMesh() : - index(0), - materialIndex(-1), - usesSharedVertexData(false), - operationType(OT_POINT_LIST) -{ + index(0), + materialIndex(-1), + usesSharedVertexData(false), + operationType(OT_POINT_LIST) { } // SubMesh SubMesh::SubMesh() : - vertexData(0), - indexData(new IndexData()) -{ + vertexData(0), + indexData(new IndexData()) { } -SubMesh::~SubMesh() -{ +SubMesh::~SubMesh() { Reset(); } -void SubMesh::Reset() -{ +void SubMesh::Reset(){ OGRE_SAFE_DELETE(vertexData) - OGRE_SAFE_DELETE(indexData) + OGRE_SAFE_DELETE(indexData) } -aiMesh *SubMesh::ConvertToAssimpMesh(Mesh *parent) -{ +aiMesh *SubMesh::ConvertToAssimpMesh(Mesh *parent) { if (operationType != OT_TRIANGLE_LIST) { throw DeadlyImportError(Formatter::format() << "Only mesh operation type OT_TRIANGLE_LIST is supported. Found " << operationType); } @@ -555,9 +493,9 @@ aiMesh *SubMesh::ConvertToAssimpMesh(Mesh *parent) VertexData *src = (!usesSharedVertexData ? vertexData : parent->sharedVertexData); VertexElement *positionsElement = src->GetVertexElement(VertexElement::VES_POSITION); - VertexElement *normalsElement = src->GetVertexElement(VertexElement::VES_NORMAL); - VertexElement *uv1Element = src->GetVertexElement(VertexElement::VES_TEXTURE_COORDINATES, 0); - VertexElement *uv2Element = src->GetVertexElement(VertexElement::VES_TEXTURE_COORDINATES, 1); + VertexElement *normalsElement = src->GetVertexElement(VertexElement::VES_NORMAL); + VertexElement *uv1Element = src->GetVertexElement(VertexElement::VES_TEXTURE_COORDINATES, 0); + VertexElement *uv2Element = src->GetVertexElement(VertexElement::VES_TEXTURE_COORDINATES, 1); // Sanity checks if (!positionsElement) { @@ -578,22 +516,22 @@ aiMesh *SubMesh::ConvertToAssimpMesh(Mesh *parent) dest->mVertices = new aiVector3D[dest->mNumVertices]; // Source streams - MemoryStream *positions = src->VertexBuffer(positionsElement->source); - MemoryStream *normals = (normalsElement ? src->VertexBuffer(normalsElement->source) : 0); - MemoryStream *uv1 = (uv1Element ? src->VertexBuffer(uv1Element->source) : 0); - MemoryStream *uv2 = (uv2Element ? src->VertexBuffer(uv2Element->source) : 0); + MemoryStream *positions = src->VertexBuffer(positionsElement->source); + MemoryStream *normals = (normalsElement ? src->VertexBuffer(normalsElement->source) : 0); + MemoryStream *uv1 = (uv1Element ? src->VertexBuffer(uv1Element->source) : 0); + MemoryStream *uv2 = (uv2Element ? src->VertexBuffer(uv2Element->source) : 0); // Element size - const size_t sizePosition = positionsElement->Size(); - const size_t sizeNormal = (normalsElement ? normalsElement->Size() : 0); - const size_t sizeUv1 = (uv1Element ? uv1Element->Size() : 0); - const size_t sizeUv2 = (uv2Element ? uv2Element->Size() : 0); + const size_t sizePosition = positionsElement->Size(); + const size_t sizeNormal = (normalsElement ? normalsElement->Size() : 0); + const size_t sizeUv1 = (uv1Element ? uv1Element->Size() : 0); + const size_t sizeUv2 = (uv2Element ? uv2Element->Size() : 0); // Vertex width - const size_t vWidthPosition = src->VertexSize(positionsElement->source); - const size_t vWidthNormal = (normalsElement ? src->VertexSize(normalsElement->source) : 0); - const size_t vWidthUv1 = (uv1Element ? src->VertexSize(uv1Element->source) : 0); - const size_t vWidthUv2 = (uv2Element ? src->VertexSize(uv2Element->source) : 0); + const size_t vWidthPosition = src->VertexSize(positionsElement->source); + const size_t vWidthNormal = (normalsElement ? src->VertexSize(normalsElement->source) : 0); + const size_t vWidthUv1 = (uv1Element ? src->VertexSize(uv1Element->source) : 0); + const size_t vWidthUv2 = (uv2Element ? src->VertexSize(uv2Element->source) : 0); bool boneAssignments = src->HasBoneAssignments(); @@ -602,28 +540,20 @@ aiMesh *SubMesh::ConvertToAssimpMesh(Mesh *parent) dest->mNormals = new aiVector3D[dest->mNumVertices]; // Prepare UVs, ignoring incompatible UVs. - if (uv1) - { - if (uv1Element->type == VertexElement::VET_FLOAT2 || uv1Element->type == VertexElement::VET_FLOAT3) - { + if (uv1) { + if (uv1Element->type == VertexElement::VET_FLOAT2 || uv1Element->type == VertexElement::VET_FLOAT3) { dest->mNumUVComponents[0] = static_cast(uv1Element->ComponentCount()); dest->mTextureCoords[0] = new aiVector3D[dest->mNumVertices]; - } - else - { + } else { ASSIMP_LOG_WARN(Formatter::format() << "Ogre imported UV0 type " << uv1Element->TypeToString() << " is not compatible with Assimp. Ignoring UV."); uv1 = 0; } } - if (uv2) - { - if (uv2Element->type == VertexElement::VET_FLOAT2 || uv2Element->type == VertexElement::VET_FLOAT3) - { + if (uv2) { + if (uv2Element->type == VertexElement::VET_FLOAT2 || uv2Element->type == VertexElement::VET_FLOAT3) { dest->mNumUVComponents[1] = static_cast(uv2Element->ComponentCount()); dest->mTextureCoords[1] = new aiVector3D[dest->mNumVertices]; - } - else - { + } else { ASSIMP_LOG_WARN(Formatter::format() << "Ogre imported UV0 type " << uv2Element->TypeToString() << " is not compatible with Assimp. Ignoring UV."); uv2 = 0; } @@ -633,24 +563,19 @@ aiMesh *SubMesh::ConvertToAssimpMesh(Mesh *parent) aiVector3D *uv2Dest = (uv2 ? dest->mTextureCoords[1] : 0); MemoryStream *faces = indexData->buffer.get(); - for (size_t fi=0, isize=indexData->IndexSize(), fsize=indexData->FaceSize(); - fimNumFaces; ++fi) - { + for (size_t fi = 0, isize = indexData->IndexSize(), fsize = indexData->FaceSize(); + fi < dest->mNumFaces; ++fi) { // Source Ogre face aiFace ogreFace; ogreFace.mNumIndices = 3; ogreFace.mIndices = new unsigned int[3]; faces->Seek(fi * fsize, aiOrigin_SET); - if (indexData->is32bit) - { + if (indexData->is32bit) { faces->Read(&ogreFace.mIndices[0], isize, 3); - } - else - { + } else { uint16_t iout = 0; - for (size_t ii=0; ii<3; ++ii) - { + for (size_t ii = 0; ii < 3; ++ii) { faces->Read(&iout, isize, 1); ogreFace.mIndices[ii] = static_cast(iout); } @@ -662,8 +587,7 @@ aiMesh *SubMesh::ConvertToAssimpMesh(Mesh *parent) face.mIndices = new unsigned int[3]; const size_t pos = fi * 3; - for (size_t v=0; v<3; ++v) - { + for (size_t v = 0; v < 3; ++v) { const size_t newIndex = pos + v; // Write face index @@ -678,21 +602,18 @@ aiMesh *SubMesh::ConvertToAssimpMesh(Mesh *parent) positions->Read(&dest->mVertices[newIndex], sizePosition, 1); // Normal - if (normals) - { + if (normals) { normals->Seek((vWidthNormal * ogreVertexIndex) + normalsElement->offset, aiOrigin_SET); normals->Read(&dest->mNormals[newIndex], sizeNormal, 1); } // UV0 - if (uv1 && uv1Dest) - { + if (uv1 && uv1Dest) { uv1->Seek((vWidthUv1 * ogreVertexIndex) + uv1Element->offset, aiOrigin_SET); uv1->Read(&uv1Dest[newIndex], sizeUv1, 1); uv1Dest[newIndex].y = (uv1Dest[newIndex].y * -1) + 1; // Flip UV from Ogre to Assimp form } // UV1 - if (uv2 && uv2Dest) - { + if (uv2 && uv2Dest) { uv2->Seek((vWidthUv2 * ogreVertexIndex) + uv2Element->offset, aiOrigin_SET); uv2->Read(&uv2Dest[newIndex], sizeUv2, 1); uv2Dest[newIndex].y = (uv2Dest[newIndex].y * -1) + 1; // Flip UV from Ogre to Assimp form @@ -701,17 +622,15 @@ aiMesh *SubMesh::ConvertToAssimpMesh(Mesh *parent) } // Bones and bone weights - if (parent->skeleton && boneAssignments) - { + if (parent->skeleton && boneAssignments) { AssimpVertexBoneWeightList weights = src->AssimpBoneWeights(dest->mNumVertices); std::set referencedBones = src->ReferencedBonesByWeights(); dest->mNumBones = static_cast(referencedBones.size()); - dest->mBones = new aiBone*[dest->mNumBones]; + dest->mBones = new aiBone *[dest->mNumBones]; size_t assimpBoneIndex = 0; - for(std::set::const_iterator rbIter=referencedBones.begin(), rbEnd=referencedBones.end(); rbIter != rbEnd; ++rbIter, ++assimpBoneIndex) - { + for (std::set::const_iterator rbIter = referencedBones.begin(), rbEnd = referencedBones.end(); rbIter != rbEnd; ++rbIter, ++assimpBoneIndex) { Bone *bone = parent->skeleton->BoneById((*rbIter)); dest->mBones[assimpBoneIndex] = bone->ConvertToAssimpBone(parent->skeleton, weights[bone->id]); } @@ -723,45 +642,39 @@ aiMesh *SubMesh::ConvertToAssimpMesh(Mesh *parent) // MeshXml MeshXml::MeshXml() : - skeleton(0), - sharedVertexData(0) -{ + skeleton(0), + sharedVertexData(0) { } -MeshXml::~MeshXml() -{ +MeshXml::~MeshXml() { Reset(); } -void MeshXml::Reset() -{ +void MeshXml::Reset() { OGRE_SAFE_DELETE(skeleton) OGRE_SAFE_DELETE(sharedVertexData) - for(auto &mesh : subMeshes) { + for (auto &mesh : subMeshes) { OGRE_SAFE_DELETE(mesh) } subMeshes.clear(); } -size_t MeshXml::NumSubMeshes() const -{ +size_t MeshXml::NumSubMeshes() const { return subMeshes.size(); } -SubMeshXml *MeshXml::GetSubMesh(uint16_t index) const -{ - for(size_t i=0; iindex == index) return subMeshes[i]; return 0; } -void MeshXml::ConvertToAssimpScene(aiScene* dest) -{ +void MeshXml::ConvertToAssimpScene(aiScene *dest) { // Setup dest->mNumMeshes = static_cast(NumSubMeshes()); - dest->mMeshes = new aiMesh*[dest->mNumMeshes]; + dest->mMeshes = new aiMesh *[dest->mNumMeshes]; // Create root node dest->mRootNode = new aiNode(); @@ -769,36 +682,30 @@ void MeshXml::ConvertToAssimpScene(aiScene* dest) dest->mRootNode->mMeshes = new unsigned int[dest->mRootNode->mNumMeshes]; // Export meshes - for(size_t i=0; imNumMeshes; ++i) - { + for (size_t i = 0; i < dest->mNumMeshes; ++i) { dest->mMeshes[i] = subMeshes[i]->ConvertToAssimpMesh(this); dest->mRootNode->mMeshes[i] = static_cast(i); } // Export skeleton - if (skeleton) - { + if (skeleton) { // Bones - if (!skeleton->bones.empty()) - { + if (!skeleton->bones.empty()) { BoneList rootBones = skeleton->RootBones(); dest->mRootNode->mNumChildren = static_cast(rootBones.size()); - dest->mRootNode->mChildren = new aiNode*[dest->mRootNode->mNumChildren]; + dest->mRootNode->mChildren = new aiNode *[dest->mRootNode->mNumChildren]; - for(size_t i=0, len=rootBones.size(); imRootNode->mChildren[i] = rootBones[i]->ConvertToAssimpNode(skeleton, dest->mRootNode); } } // Animations - if (!skeleton->animations.empty()) - { + if (!skeleton->animations.empty()) { dest->mNumAnimations = static_cast(skeleton->animations.size()); - dest->mAnimations = new aiAnimation*[dest->mNumAnimations]; + dest->mAnimations = new aiAnimation *[dest->mNumAnimations]; - for(size_t i=0, len=skeleton->animations.size(); ianimations.size(); i < len; ++i) { dest->mAnimations[i] = skeleton->animations[i]->ConvertToAssimpAnimation(); } } @@ -808,24 +715,20 @@ void MeshXml::ConvertToAssimpScene(aiScene* dest) // SubMeshXml SubMeshXml::SubMeshXml() : - indexData(new IndexDataXml()), - vertexData(0) -{ + indexData(new IndexDataXml()), + vertexData(0) { } -SubMeshXml::~SubMeshXml() -{ +SubMeshXml::~SubMeshXml() { Reset(); } -void SubMeshXml::Reset() -{ +void SubMeshXml::Reset(){ OGRE_SAFE_DELETE(indexData) - OGRE_SAFE_DELETE(vertexData) + OGRE_SAFE_DELETE(vertexData) } -aiMesh *SubMeshXml::ConvertToAssimpMesh(MeshXml *parent) -{ +aiMesh *SubMeshXml::ConvertToAssimpMesh(MeshXml *parent) { aiMesh *dest = new aiMesh(); dest->mPrimitiveTypes = aiPrimitiveType_TRIANGLE; @@ -855,14 +758,12 @@ aiMesh *SubMeshXml::ConvertToAssimpMesh(MeshXml *parent) dest->mNormals = new aiVector3D[dest->mNumVertices]; // Prepare UVs - for(size_t uvi=0; uvimNumUVComponents[uvi] = 2; dest->mTextureCoords[uvi] = new aiVector3D[dest->mNumVertices]; } - for (size_t fi=0; fimNumFaces; ++fi) - { + for (size_t fi = 0; fi < dest->mNumFaces; ++fi) { // Source Ogre face aiFace &ogreFace = indexData->faces[fi]; @@ -872,8 +773,7 @@ aiMesh *SubMeshXml::ConvertToAssimpMesh(MeshXml *parent) face.mIndices = new unsigned int[3]; const size_t pos = fi * 3; - for (size_t v=0; v<3; ++v) - { + for (size_t v = 0; v < 3; ++v) { const size_t newIndex = pos + v; // Write face index @@ -891,8 +791,7 @@ aiMesh *SubMeshXml::ConvertToAssimpMesh(MeshXml *parent) dest->mNormals[newIndex] = src->normals[ogreVertexIndex]; // UVs - for(size_t uvi=0; uvimTextureCoords[uvi]; std::vector &uvSrc = src->uvs[uvi]; uvDest[newIndex] = uvSrc[ogreVertexIndex]; @@ -901,17 +800,15 @@ aiMesh *SubMeshXml::ConvertToAssimpMesh(MeshXml *parent) } // Bones and bone weights - if (parent->skeleton && boneAssignments) - { + if (parent->skeleton && boneAssignments) { AssimpVertexBoneWeightList weights = src->AssimpBoneWeights(dest->mNumVertices); std::set referencedBones = src->ReferencedBonesByWeights(); dest->mNumBones = static_cast(referencedBones.size()); - dest->mBones = new aiBone*[dest->mNumBones]; + dest->mBones = new aiBone *[dest->mNumBones]; size_t assimpBoneIndex = 0; - for(std::set::const_iterator rbIter=referencedBones.begin(), rbEnd=referencedBones.end(); rbIter != rbEnd; ++rbIter, ++assimpBoneIndex) - { + for (std::set::const_iterator rbIter = referencedBones.begin(), rbEnd = referencedBones.end(); rbIter != rbEnd; ++rbIter, ++assimpBoneIndex) { Bone *bone = parent->skeleton->BoneById((*rbIter)); dest->mBones[assimpBoneIndex] = bone->ConvertToAssimpBone(parent->skeleton, weights[bone->id]); } @@ -923,48 +820,46 @@ aiMesh *SubMeshXml::ConvertToAssimpMesh(MeshXml *parent) // Animation Animation::Animation(Skeleton *parent) : - parentMesh(NULL), - parentSkeleton(parent), - length(0.0f), - baseTime(-1.0f) -{ + parentMesh(nullptr), + parentSkeleton(parent), + length(0.0f), + baseTime(-1.0f) { + // empty } Animation::Animation(Mesh *parent) : - parentMesh(parent), - parentSkeleton(0), - length(0.0f), - baseTime(-1.0f) -{ + parentMesh(parent), + parentSkeleton(0), + length(0.0f), + baseTime(-1.0f) { + // empty } -VertexData *Animation::AssociatedVertexData(VertexAnimationTrack *track) const -{ - if (!parentMesh) - return 0; +VertexData *Animation::AssociatedVertexData(VertexAnimationTrack *track) const { + if (nullptr == parentMesh) { + return nullptr; + } bool sharedGeom = (track->target == 0); - if (sharedGeom) + if (sharedGeom) { return parentMesh->sharedVertexData; - else - return parentMesh->GetSubMesh(track->target-1)->vertexData; + } + + return parentMesh->GetSubMesh(track->target - 1)->vertexData; } -aiAnimation *Animation::ConvertToAssimpAnimation() -{ +aiAnimation *Animation::ConvertToAssimpAnimation() { aiAnimation *anim = new aiAnimation(); anim->mName = name; anim->mDuration = static_cast(length); anim->mTicksPerSecond = 1.0; // Tracks - if (!tracks.empty()) - { + if (!tracks.empty()) { anim->mNumChannels = static_cast(tracks.size()); - anim->mChannels = new aiNodeAnim*[anim->mNumChannels]; + anim->mChannels = new aiNodeAnim *[anim->mNumChannels]; - for(size_t i=0, len=tracks.size(); imChannels[i] = tracks[i].ConvertToAssimpAnimationNode(parentSkeleton); } } @@ -974,65 +869,54 @@ aiAnimation *Animation::ConvertToAssimpAnimation() // Skeleton Skeleton::Skeleton() : - bones(), - animations(), - blendMode(ANIMBLEND_AVERAGE) -{ + bones(), + animations(), + blendMode(ANIMBLEND_AVERAGE) { } -Skeleton::~Skeleton() -{ +Skeleton::~Skeleton() { Reset(); } -void Skeleton::Reset() -{ - for(auto &bone : bones) { +void Skeleton::Reset() { + for (auto &bone : bones) { OGRE_SAFE_DELETE(bone) } bones.clear(); - for(auto &anim : animations) { + for (auto &anim : animations) { OGRE_SAFE_DELETE(anim) } animations.clear(); } -BoneList Skeleton::RootBones() const -{ +BoneList Skeleton::RootBones() const { BoneList rootBones; - for(BoneList::const_iterator iter = bones.begin(); iter != bones.end(); ++iter) - { + for (BoneList::const_iterator iter = bones.begin(); iter != bones.end(); ++iter) { if (!(*iter)->IsParented()) rootBones.push_back((*iter)); } return rootBones; } -size_t Skeleton::NumRootBones() const -{ +size_t Skeleton::NumRootBones() const { size_t num = 0; - for(BoneList::const_iterator iter = bones.begin(); iter != bones.end(); ++iter) - { + for (BoneList::const_iterator iter = bones.begin(); iter != bones.end(); ++iter) { if (!(*iter)->IsParented()) num++; } return num; } -Bone *Skeleton::BoneByName(const std::string &name) const -{ - for(BoneList::const_iterator iter = bones.begin(); iter != bones.end(); ++iter) - { +Bone *Skeleton::BoneByName(const std::string &name) const { + for (BoneList::const_iterator iter = bones.begin(); iter != bones.end(); ++iter) { if ((*iter)->name == name) return (*iter); } return 0; } -Bone *Skeleton::BoneById(uint16_t id) const -{ - for(BoneList::const_iterator iter = bones.begin(); iter != bones.end(); ++iter) - { +Bone *Skeleton::BoneById(uint16_t id) const { + for (BoneList::const_iterator iter = bones.begin(); iter != bones.end(); ++iter) { if ((*iter)->id == id) return (*iter); } @@ -1042,25 +926,21 @@ Bone *Skeleton::BoneById(uint16_t id) const // Bone Bone::Bone() : - id(0), - parent(0), - parentId(-1), - scale(1.0f, 1.0f, 1.0f) -{ + id(0), + parent(0), + parentId(-1), + scale(1.0f, 1.0f, 1.0f) { } -bool Bone::IsParented() const -{ +bool Bone::IsParented() const { return (parentId != -1 && parent != 0); } -uint16_t Bone::ParentId() const -{ +uint16_t Bone::ParentId() const { return static_cast(parentId); } -void Bone::AddChild(Bone *bone) -{ +void Bone::AddChild(Bone *bone) { if (!bone) return; if (bone->IsParented()) @@ -1071,8 +951,7 @@ void Bone::AddChild(Bone *bone) children.push_back(bone->id); } -void Bone::CalculateWorldMatrixAndDefaultPose(Skeleton *skeleton) -{ +void Bone::CalculateWorldMatrixAndDefaultPose(Skeleton *skeleton) { if (!IsParented()) worldMatrix = aiMatrix4x4(scale, rotation, position).Inverse(); else @@ -1081,8 +960,7 @@ void Bone::CalculateWorldMatrixAndDefaultPose(Skeleton *skeleton) defaultPose = aiMatrix4x4(scale, rotation, position); // Recursively for all children now that the parent matrix has been calculated. - for (auto boneId : children) - { + for (auto boneId : children) { Bone *child = skeleton->BoneById(boneId); if (!child) { throw DeadlyImportError(Formatter::format() << "CalculateWorldMatrixAndDefaultPose: Failed to find child bone " << boneId << " for parent " << id << " " << name); @@ -1091,21 +969,18 @@ void Bone::CalculateWorldMatrixAndDefaultPose(Skeleton *skeleton) } } -aiNode *Bone::ConvertToAssimpNode(Skeleton *skeleton, aiNode *parentNode) -{ +aiNode *Bone::ConvertToAssimpNode(Skeleton *skeleton, aiNode *parentNode) { // Bone node - aiNode* node = new aiNode(name); + aiNode *node = new aiNode(name); node->mParent = parentNode; node->mTransformation = defaultPose; // Children - if (!children.empty()) - { + if (!children.empty()) { node->mNumChildren = static_cast(children.size()); - node->mChildren = new aiNode*[node->mNumChildren]; + node->mChildren = new aiNode *[node->mNumChildren]; - for(size_t i=0, len=children.size(); iBoneById(children[i]); if (!child) { throw DeadlyImportError(Formatter::format() << "ConvertToAssimpNode: Failed to find child bone " << children[i] << " for parent " << id << " " << name); @@ -1116,14 +991,12 @@ aiNode *Bone::ConvertToAssimpNode(Skeleton *skeleton, aiNode *parentNode) return node; } -aiBone *Bone::ConvertToAssimpBone(Skeleton * /*parent*/, const std::vector &boneWeights) -{ +aiBone *Bone::ConvertToAssimpBone(Skeleton * /*parent*/, const std::vector &boneWeights) { aiBone *bone = new aiBone(); bone->mName = name; bone->mOffsetMatrix = worldMatrix; - if (!boneWeights.empty()) - { + if (!boneWeights.empty()) { bone->mNumWeights = static_cast(boneWeights.size()); bone->mWeights = new aiVertexWeight[boneWeights.size()]; memcpy(bone->mWeights, &boneWeights[0], boneWeights.size() * sizeof(aiVertexWeight)); @@ -1135,13 +1008,11 @@ aiBone *Bone::ConvertToAssimpBone(Skeleton * /*parent*/, const std::vectormScalingKeys = new aiVectorKey[numKeyframes]; nodeAnim->mNumPositionKeys = static_cast(numKeyframes); nodeAnim->mNumRotationKeys = static_cast(numKeyframes); - nodeAnim->mNumScalingKeys = static_cast(numKeyframes); + nodeAnim->mNumScalingKeys = static_cast(numKeyframes); - for(size_t kfi=0; kfidefaultPose * kfSource.Transform(); finalTransform.Decompose(scale, rot, pos); @@ -1190,17 +1062,15 @@ aiNodeAnim *VertexAnimationTrack::ConvertToAssimpAnimationNode(Skeleton *skeleto // TransformKeyFrame TransformKeyFrame::TransformKeyFrame() : - timePos(0.0f), - scale(1.0f, 1.0f, 1.0f) -{ + timePos(0.0f), + scale(1.0f, 1.0f, 1.0f) { } -aiMatrix4x4 TransformKeyFrame::Transform() -{ +aiMatrix4x4 TransformKeyFrame::Transform() { return aiMatrix4x4(scale, rotation, position); } -} // Ogre -} // Assimp +} // namespace Ogre +} // namespace Assimp #endif // ASSIMP_BUILD_NO_OGRE_IMPORTER diff --git a/code/AssetLib/Ply/PlyExporter.cpp b/code/AssetLib/Ply/PlyExporter.cpp index 28ff0c602..d82c55ca9 100644 --- a/code/AssetLib/Ply/PlyExporter.cpp +++ b/code/AssetLib/Ply/PlyExporter.cpp @@ -77,7 +77,7 @@ void ExportScenePly(const char* pFile,IOSystem* pIOSystem, const aiScene* pScene // we're still here - export successfully completed. Write the file. std::unique_ptr outfile (pIOSystem->Open(pFile,"wt")); - if(outfile == NULL) { + if (outfile == nullptr) { throw DeadlyExportError("could not open output .ply file: " + std::string(pFile)); } @@ -91,7 +91,7 @@ void ExportScenePlyBinary(const char* pFile, IOSystem* pIOSystem, const aiScene* // we're still here - export successfully completed. Write the file. std::unique_ptr outfile(pIOSystem->Open(pFile, "wb")); - if (outfile == NULL) { + if (outfile == nullptr) { throw DeadlyExportError("could not open output .ply file: " + std::string(pFile)); } diff --git a/code/AssetLib/Ply/PlyLoader.cpp b/code/AssetLib/Ply/PlyLoader.cpp index 8f41bd1a0..b8dbf2598 100644 --- a/code/AssetLib/Ply/PlyLoader.cpp +++ b/code/AssetLib/Ply/PlyLoader.cpp @@ -693,7 +693,7 @@ void PLYImporter::GetMaterialColor(const std::vector &avL unsigned int aiPositions[4], PLY::EDataType aiTypes[4], aiColor4D *clrOut) { - ai_assert(NULL != clrOut); + ai_assert(nullptr != clrOut); if (0xFFFFFFFF == aiPositions[0]) clrOut->r = 0.0f; @@ -736,7 +736,7 @@ void PLYImporter::GetMaterialColor(const std::vector &avL // ------------------------------------------------------------------------------------------------ // Extract a material from the PLY DOM void PLYImporter::LoadMaterial(std::vector *pvOut, std::string &defaultTexture, const bool pointsOnly) { - ai_assert(NULL != pvOut); + ai_assert(nullptr != pvOut); // diffuse[4], specular[4], ambient[4] // rgba order @@ -752,7 +752,7 @@ void PLYImporter::LoadMaterial(std::vector *pvOut, std::string &de { EDT_Char, EDT_Char, EDT_Char, EDT_Char }, { EDT_Char, EDT_Char, EDT_Char, EDT_Char } }; - PLY::ElementInstanceList *pcList = NULL; + PLY::ElementInstanceList *pcList = nullptr; unsigned int iPhong = 0xFFFFFFFF; PLY::EDataType ePhong = EDT_Char; @@ -835,7 +835,7 @@ void PLYImporter::LoadMaterial(std::vector *pvOut, std::string &de } } // check whether we have a valid source for the material data - if (NULL != pcList) { + if (nullptr != pcList) { for (std::vector::const_iterator i = pcList->alInstances.begin(); i != pcList->alInstances.end(); ++i) { aiColor4D clrOut; aiMaterial *pcHelper = new aiMaterial(); diff --git a/code/AssetLib/Ply/PlyParser.cpp b/code/AssetLib/Ply/PlyParser.cpp index 1b885fb9c..6fd7044f1 100644 --- a/code/AssetLib/Ply/PlyParser.cpp +++ b/code/AssetLib/Ply/PlyParser.cpp @@ -42,285 +42,201 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. /** @file Implementation of the PLY parser class */ - #ifndef ASSIMP_BUILD_NO_PLY_IMPORTER +#include "PlyLoader.h" +#include #include #include -#include -#include "PlyLoader.h" using namespace Assimp; // ------------------------------------------------------------------------------------------------ PLY::EDataType PLY::Property::ParseDataType(std::vector &buffer) { - ai_assert(!buffer.empty()); + ai_assert(!buffer.empty()); - PLY::EDataType eOut = PLY::EDT_INVALID; + PLY::EDataType eOut = PLY::EDT_INVALID; - if (PLY::DOM::TokenMatch(buffer, "char", 4) || - PLY::DOM::TokenMatch(buffer, "int8", 4)) - { - eOut = PLY::EDT_Char; - } - else if (PLY::DOM::TokenMatch(buffer, "uchar", 5) || - PLY::DOM::TokenMatch(buffer, "uint8", 5)) - { - eOut = PLY::EDT_UChar; - } - else if (PLY::DOM::TokenMatch(buffer, "short", 5) || - PLY::DOM::TokenMatch(buffer, "int16", 5)) - { - eOut = PLY::EDT_Short; - } - else if (PLY::DOM::TokenMatch(buffer, "ushort", 6) || - PLY::DOM::TokenMatch(buffer, "uint16", 6)) - { - eOut = PLY::EDT_UShort; - } - else if (PLY::DOM::TokenMatch(buffer, "int32", 5) || PLY::DOM::TokenMatch(buffer, "int", 3)) - { - eOut = PLY::EDT_Int; - } - else if (PLY::DOM::TokenMatch(buffer, "uint32", 6) || PLY::DOM::TokenMatch(buffer, "uint", 4)) - { - eOut = PLY::EDT_UInt; - } - else if (PLY::DOM::TokenMatch(buffer, "float", 5) || PLY::DOM::TokenMatch(buffer, "float32", 7)) - { - eOut = PLY::EDT_Float; - } - else if (PLY::DOM::TokenMatch(buffer, "double64", 8) || PLY::DOM::TokenMatch(buffer, "double", 6) || - PLY::DOM::TokenMatch(buffer, "float64", 7)) - { - eOut = PLY::EDT_Double; - } - if (PLY::EDT_INVALID == eOut) - { - ASSIMP_LOG_INFO("Found unknown data type in PLY file. This is OK"); - } + if (PLY::DOM::TokenMatch(buffer, "char", 4) || + PLY::DOM::TokenMatch(buffer, "int8", 4)) { + eOut = PLY::EDT_Char; + } else if (PLY::DOM::TokenMatch(buffer, "uchar", 5) || + PLY::DOM::TokenMatch(buffer, "uint8", 5)) { + eOut = PLY::EDT_UChar; + } else if (PLY::DOM::TokenMatch(buffer, "short", 5) || + PLY::DOM::TokenMatch(buffer, "int16", 5)) { + eOut = PLY::EDT_Short; + } else if (PLY::DOM::TokenMatch(buffer, "ushort", 6) || + PLY::DOM::TokenMatch(buffer, "uint16", 6)) { + eOut = PLY::EDT_UShort; + } else if (PLY::DOM::TokenMatch(buffer, "int32", 5) || PLY::DOM::TokenMatch(buffer, "int", 3)) { + eOut = PLY::EDT_Int; + } else if (PLY::DOM::TokenMatch(buffer, "uint32", 6) || PLY::DOM::TokenMatch(buffer, "uint", 4)) { + eOut = PLY::EDT_UInt; + } else if (PLY::DOM::TokenMatch(buffer, "float", 5) || PLY::DOM::TokenMatch(buffer, "float32", 7)) { + eOut = PLY::EDT_Float; + } else if (PLY::DOM::TokenMatch(buffer, "double64", 8) || PLY::DOM::TokenMatch(buffer, "double", 6) || + PLY::DOM::TokenMatch(buffer, "float64", 7)) { + eOut = PLY::EDT_Double; + } + if (PLY::EDT_INVALID == eOut) { + ASSIMP_LOG_INFO("Found unknown data type in PLY file. This is OK"); + } - return eOut; + return eOut; } // ------------------------------------------------------------------------------------------------ PLY::ESemantic PLY::Property::ParseSemantic(std::vector &buffer) { - ai_assert(!buffer.empty()); + ai_assert(!buffer.empty()); - PLY::ESemantic eOut = PLY::EST_INVALID; - if (PLY::DOM::TokenMatch(buffer, "red", 3)) { - eOut = PLY::EST_Red; - } - else if (PLY::DOM::TokenMatch(buffer, "green", 5)) { - eOut = PLY::EST_Green; - } - else if (PLY::DOM::TokenMatch(buffer, "blue", 4)) { - eOut = PLY::EST_Blue; - } - else if (PLY::DOM::TokenMatch(buffer, "alpha", 5)) { - eOut = PLY::EST_Alpha; - } - else if (PLY::DOM::TokenMatch(buffer, "vertex_index", 12) || PLY::DOM::TokenMatch(buffer, "vertex_indices", 14)) { - eOut = PLY::EST_VertexIndex; - } - else if (PLY::DOM::TokenMatch(buffer, "texcoord", 8)) // Manage uv coords on faces - { - eOut = PLY::EST_TextureCoordinates; - } - else if (PLY::DOM::TokenMatch(buffer, "material_index", 14)) - { - eOut = PLY::EST_MaterialIndex; - } - else if (PLY::DOM::TokenMatch(buffer, "ambient_red", 11)) - { - eOut = PLY::EST_AmbientRed; - } - else if (PLY::DOM::TokenMatch(buffer, "ambient_green", 13)) - { - eOut = PLY::EST_AmbientGreen; - } - else if (PLY::DOM::TokenMatch(buffer, "ambient_blue", 12)) - { - eOut = PLY::EST_AmbientBlue; - } - else if (PLY::DOM::TokenMatch(buffer, "ambient_alpha", 13)) - { - eOut = PLY::EST_AmbientAlpha; - } - else if (PLY::DOM::TokenMatch(buffer, "diffuse_red", 11)) - { - eOut = PLY::EST_DiffuseRed; - } - else if (PLY::DOM::TokenMatch(buffer, "diffuse_green", 13)) - { - eOut = PLY::EST_DiffuseGreen; - } - else if (PLY::DOM::TokenMatch(buffer, "diffuse_blue", 12)) - { - eOut = PLY::EST_DiffuseBlue; - } - else if (PLY::DOM::TokenMatch(buffer, "diffuse_alpha", 13)) - { - eOut = PLY::EST_DiffuseAlpha; - } - else if (PLY::DOM::TokenMatch(buffer, "specular_red", 12)) - { - eOut = PLY::EST_SpecularRed; - } - else if (PLY::DOM::TokenMatch(buffer, "specular_green", 14)) - { - eOut = PLY::EST_SpecularGreen; - } - else if (PLY::DOM::TokenMatch(buffer, "specular_blue", 13)) - { - eOut = PLY::EST_SpecularBlue; - } - else if (PLY::DOM::TokenMatch(buffer, "specular_alpha", 14)) - { - eOut = PLY::EST_SpecularAlpha; - } - else if (PLY::DOM::TokenMatch(buffer, "opacity", 7)) - { - eOut = PLY::EST_Opacity; - } - else if (PLY::DOM::TokenMatch(buffer, "specular_power", 14)) - { - eOut = PLY::EST_PhongPower; - } - else if (PLY::DOM::TokenMatch(buffer, "r", 1)) - { - eOut = PLY::EST_Red; - } - else if (PLY::DOM::TokenMatch(buffer, "g", 1)) - { - eOut = PLY::EST_Green; - } - else if (PLY::DOM::TokenMatch(buffer, "b", 1)) - { - eOut = PLY::EST_Blue; - } + PLY::ESemantic eOut = PLY::EST_INVALID; + if (PLY::DOM::TokenMatch(buffer, "red", 3)) { + eOut = PLY::EST_Red; + } else if (PLY::DOM::TokenMatch(buffer, "green", 5)) { + eOut = PLY::EST_Green; + } else if (PLY::DOM::TokenMatch(buffer, "blue", 4)) { + eOut = PLY::EST_Blue; + } else if (PLY::DOM::TokenMatch(buffer, "alpha", 5)) { + eOut = PLY::EST_Alpha; + } else if (PLY::DOM::TokenMatch(buffer, "vertex_index", 12) || PLY::DOM::TokenMatch(buffer, "vertex_indices", 14)) { + eOut = PLY::EST_VertexIndex; + } else if (PLY::DOM::TokenMatch(buffer, "texcoord", 8)) // Manage uv coords on faces + { + eOut = PLY::EST_TextureCoordinates; + } else if (PLY::DOM::TokenMatch(buffer, "material_index", 14)) { + eOut = PLY::EST_MaterialIndex; + } else if (PLY::DOM::TokenMatch(buffer, "ambient_red", 11)) { + eOut = PLY::EST_AmbientRed; + } else if (PLY::DOM::TokenMatch(buffer, "ambient_green", 13)) { + eOut = PLY::EST_AmbientGreen; + } else if (PLY::DOM::TokenMatch(buffer, "ambient_blue", 12)) { + eOut = PLY::EST_AmbientBlue; + } else if (PLY::DOM::TokenMatch(buffer, "ambient_alpha", 13)) { + eOut = PLY::EST_AmbientAlpha; + } else if (PLY::DOM::TokenMatch(buffer, "diffuse_red", 11)) { + eOut = PLY::EST_DiffuseRed; + } else if (PLY::DOM::TokenMatch(buffer, "diffuse_green", 13)) { + eOut = PLY::EST_DiffuseGreen; + } else if (PLY::DOM::TokenMatch(buffer, "diffuse_blue", 12)) { + eOut = PLY::EST_DiffuseBlue; + } else if (PLY::DOM::TokenMatch(buffer, "diffuse_alpha", 13)) { + eOut = PLY::EST_DiffuseAlpha; + } else if (PLY::DOM::TokenMatch(buffer, "specular_red", 12)) { + eOut = PLY::EST_SpecularRed; + } else if (PLY::DOM::TokenMatch(buffer, "specular_green", 14)) { + eOut = PLY::EST_SpecularGreen; + } else if (PLY::DOM::TokenMatch(buffer, "specular_blue", 13)) { + eOut = PLY::EST_SpecularBlue; + } else if (PLY::DOM::TokenMatch(buffer, "specular_alpha", 14)) { + eOut = PLY::EST_SpecularAlpha; + } else if (PLY::DOM::TokenMatch(buffer, "opacity", 7)) { + eOut = PLY::EST_Opacity; + } else if (PLY::DOM::TokenMatch(buffer, "specular_power", 14)) { + eOut = PLY::EST_PhongPower; + } else if (PLY::DOM::TokenMatch(buffer, "r", 1)) { + eOut = PLY::EST_Red; + } else if (PLY::DOM::TokenMatch(buffer, "g", 1)) { + eOut = PLY::EST_Green; + } else if (PLY::DOM::TokenMatch(buffer, "b", 1)) { + eOut = PLY::EST_Blue; + } - // NOTE: Blender3D exports texture coordinates as s,t tuples - else if (PLY::DOM::TokenMatch(buffer, "u", 1) || PLY::DOM::TokenMatch(buffer, "s", 1) || PLY::DOM::TokenMatch(buffer, "tx", 2) || PLY::DOM::TokenMatch(buffer, "texture_u", 9)) - { - eOut = PLY::EST_UTextureCoord; - } - else if (PLY::DOM::TokenMatch(buffer, "v", 1) || PLY::DOM::TokenMatch(buffer, "t", 1) || PLY::DOM::TokenMatch(buffer, "ty", 2) || PLY::DOM::TokenMatch(buffer, "texture_v", 9)) - { - eOut = PLY::EST_VTextureCoord; - } - else if (PLY::DOM::TokenMatch(buffer, "x", 1)) - { - eOut = PLY::EST_XCoord; - } - else if (PLY::DOM::TokenMatch(buffer, "y", 1)) { - eOut = PLY::EST_YCoord; - } - else if (PLY::DOM::TokenMatch(buffer, "z", 1)) { - eOut = PLY::EST_ZCoord; - } - else if (PLY::DOM::TokenMatch(buffer, "nx", 2)) { - eOut = PLY::EST_XNormal; - } - else if (PLY::DOM::TokenMatch(buffer, "ny", 2)) { - eOut = PLY::EST_YNormal; - } - else if (PLY::DOM::TokenMatch(buffer, "nz", 2)) { - eOut = PLY::EST_ZNormal; - } - else { - ASSIMP_LOG_INFO("Found unknown property semantic in file. This is ok"); - PLY::DOM::SkipLine(buffer); - } - return eOut; + // NOTE: Blender3D exports texture coordinates as s,t tuples + else if (PLY::DOM::TokenMatch(buffer, "u", 1) || PLY::DOM::TokenMatch(buffer, "s", 1) || PLY::DOM::TokenMatch(buffer, "tx", 2) || PLY::DOM::TokenMatch(buffer, "texture_u", 9)) { + eOut = PLY::EST_UTextureCoord; + } else if (PLY::DOM::TokenMatch(buffer, "v", 1) || PLY::DOM::TokenMatch(buffer, "t", 1) || PLY::DOM::TokenMatch(buffer, "ty", 2) || PLY::DOM::TokenMatch(buffer, "texture_v", 9)) { + eOut = PLY::EST_VTextureCoord; + } else if (PLY::DOM::TokenMatch(buffer, "x", 1)) { + eOut = PLY::EST_XCoord; + } else if (PLY::DOM::TokenMatch(buffer, "y", 1)) { + eOut = PLY::EST_YCoord; + } else if (PLY::DOM::TokenMatch(buffer, "z", 1)) { + eOut = PLY::EST_ZCoord; + } else if (PLY::DOM::TokenMatch(buffer, "nx", 2)) { + eOut = PLY::EST_XNormal; + } else if (PLY::DOM::TokenMatch(buffer, "ny", 2)) { + eOut = PLY::EST_YNormal; + } else if (PLY::DOM::TokenMatch(buffer, "nz", 2)) { + eOut = PLY::EST_ZNormal; + } else { + ASSIMP_LOG_INFO("Found unknown property semantic in file. This is ok"); + PLY::DOM::SkipLine(buffer); + } + return eOut; } // ------------------------------------------------------------------------------------------------ -bool PLY::Property::ParseProperty(std::vector &buffer, PLY::Property* pOut) -{ - ai_assert(!buffer.empty()); +bool PLY::Property::ParseProperty(std::vector &buffer, PLY::Property *pOut) { + ai_assert(!buffer.empty()); - // Forms supported: - // "property float x" - // "property list uchar int vertex_index" + // Forms supported: + // "property float x" + // "property list uchar int vertex_index" - // skip leading spaces - if (!PLY::DOM::SkipSpaces(buffer)) { - return false; - } - - // skip the "property" string at the beginning - if (!PLY::DOM::TokenMatch(buffer, "property", 8)) - { - // seems not to be a valid property entry - return false; - } - // get next word - if (!PLY::DOM::SkipSpaces(buffer)) { - return false; - } - if (PLY::DOM::TokenMatch(buffer, "list", 4)) - { - pOut->bIsList = true; - - // seems to be a list. - if (EDT_INVALID == (pOut->eFirstType = PLY::Property::ParseDataType(buffer))) - { - // unable to parse list size data type - PLY::DOM::SkipLine(buffer); - return false; + // skip leading spaces + if (!PLY::DOM::SkipSpaces(buffer)) { + return false; } - if (!PLY::DOM::SkipSpaces(buffer))return false; - if (EDT_INVALID == (pOut->eType = PLY::Property::ParseDataType(buffer))) - { - // unable to parse list data type - PLY::DOM::SkipLine(buffer); - return false; + + // skip the "property" string at the beginning + if (!PLY::DOM::TokenMatch(buffer, "property", 8)) { + // seems not to be a valid property entry + return false; } - } - else - { - if (EDT_INVALID == (pOut->eType = PLY::Property::ParseDataType(buffer))) - { - // unable to parse data type. Skip the property - PLY::DOM::SkipLine(buffer); - return false; + // get next word + if (!PLY::DOM::SkipSpaces(buffer)) { + return false; } - } + if (PLY::DOM::TokenMatch(buffer, "list", 4)) { + pOut->bIsList = true; - if (!PLY::DOM::SkipSpaces(buffer)) - return false; + // seems to be a list. + if (EDT_INVALID == (pOut->eFirstType = PLY::Property::ParseDataType(buffer))) { + // unable to parse list size data type + PLY::DOM::SkipLine(buffer); + return false; + } + if (!PLY::DOM::SkipSpaces(buffer)) return false; + if (EDT_INVALID == (pOut->eType = PLY::Property::ParseDataType(buffer))) { + // unable to parse list data type + PLY::DOM::SkipLine(buffer); + return false; + } + } else { + if (EDT_INVALID == (pOut->eType = PLY::Property::ParseDataType(buffer))) { + // unable to parse data type. Skip the property + PLY::DOM::SkipLine(buffer); + return false; + } + } - pOut->Semantic = PLY::Property::ParseSemantic(buffer); + if (!PLY::DOM::SkipSpaces(buffer)) + return false; - if (PLY::EST_INVALID == pOut->Semantic) - { - ASSIMP_LOG_INFO("Found unknown semantic in PLY file. This is OK"); - std::string(&buffer[0], &buffer[0] + strlen(&buffer[0])); - } + pOut->Semantic = PLY::Property::ParseSemantic(buffer); - PLY::DOM::SkipSpacesAndLineEnd(buffer); - return true; + if (PLY::EST_INVALID == pOut->Semantic) { + ASSIMP_LOG_INFO("Found unknown semantic in PLY file. This is OK"); + std::string(&buffer[0], &buffer[0] + strlen(&buffer[0])); + } + + PLY::DOM::SkipSpacesAndLineEnd(buffer); + return true; } // ------------------------------------------------------------------------------------------------ -PLY::EElementSemantic PLY::Element::ParseSemantic(std::vector &buffer) -{ - ai_assert(!buffer.empty()); +PLY::EElementSemantic PLY::Element::ParseSemantic(std::vector &buffer) { + ai_assert(!buffer.empty()); - PLY::EElementSemantic eOut = PLY::EEST_INVALID; - if (PLY::DOM::TokenMatch(buffer, "vertex", 6)) - { - eOut = PLY::EEST_Vertex; - } - else if (PLY::DOM::TokenMatch(buffer, "face", 4)) - { - eOut = PLY::EEST_Face; - } - else if (PLY::DOM::TokenMatch(buffer, "tristrips", 9)) - { - eOut = PLY::EEST_TriStrip; - } + PLY::EElementSemantic eOut = PLY::EEST_INVALID; + if (PLY::DOM::TokenMatch(buffer, "vertex", 6)) { + eOut = PLY::EEST_Vertex; + } else if (PLY::DOM::TokenMatch(buffer, "face", 4)) { + eOut = PLY::EEST_Face; + } else if (PLY::DOM::TokenMatch(buffer, "tristrips", 9)) { + eOut = PLY::EEST_TriStrip; + } #if 0 // TODO: maybe implement this? else if (PLY::DOM::TokenMatch(buffer,"range_grid",10)) @@ -328,815 +244,715 @@ PLY::EElementSemantic PLY::Element::ParseSemantic(std::vector &buffer) eOut = PLY::EEST_Face; } #endif - else if (PLY::DOM::TokenMatch(buffer, "edge", 4)) - { - eOut = PLY::EEST_Edge; - } - else if (PLY::DOM::TokenMatch(buffer, "material", 8)) - { - eOut = PLY::EEST_Material; - } - else if (PLY::DOM::TokenMatch(buffer, "TextureFile", 11)) - { - eOut = PLY::EEST_TextureFile; - } + else if (PLY::DOM::TokenMatch(buffer, "edge", 4)) { + eOut = PLY::EEST_Edge; + } else if (PLY::DOM::TokenMatch(buffer, "material", 8)) { + eOut = PLY::EEST_Material; + } else if (PLY::DOM::TokenMatch(buffer, "TextureFile", 11)) { + eOut = PLY::EEST_TextureFile; + } - return eOut; + return eOut; } // ------------------------------------------------------------------------------------------------ -bool PLY::Element::ParseElement(IOStreamBuffer &streamBuffer, std::vector &buffer, PLY::Element* pOut) -{ - ai_assert(NULL != pOut); - // Example format: "element vertex 8" +bool PLY::Element::ParseElement(IOStreamBuffer &streamBuffer, std::vector &buffer, PLY::Element *pOut) { + ai_assert(nullptr != pOut); + // Example format: "element vertex 8" - // skip leading spaces - if (!PLY::DOM::SkipSpaces(buffer)) - { - return false; - } + // skip leading spaces + if (!PLY::DOM::SkipSpaces(buffer)) { + return false; + } - // skip the "element" string at the beginning - if (!PLY::DOM::TokenMatch(buffer, "element", 7) && !PLY::DOM::TokenMatch(buffer, "comment", 7)) - { - // seems not to be a valid property entry - return false; - } - // get next word - if (!PLY::DOM::SkipSpaces(buffer)) - return false; + // skip the "element" string at the beginning + if (!PLY::DOM::TokenMatch(buffer, "element", 7) && !PLY::DOM::TokenMatch(buffer, "comment", 7)) { + // seems not to be a valid property entry + return false; + } + // get next word + if (!PLY::DOM::SkipSpaces(buffer)) + return false; - // parse the semantic of the element - pOut->eSemantic = PLY::Element::ParseSemantic(buffer); - if (PLY::EEST_INVALID == pOut->eSemantic) - { - // if the exact semantic can't be determined, just store - // the original string identifier - pOut->szName = std::string(&buffer[0], &buffer[0] + strlen(&buffer[0])); - } + // parse the semantic of the element + pOut->eSemantic = PLY::Element::ParseSemantic(buffer); + if (PLY::EEST_INVALID == pOut->eSemantic) { + // if the exact semantic can't be determined, just store + // the original string identifier + pOut->szName = std::string(&buffer[0], &buffer[0] + strlen(&buffer[0])); + } - if (!PLY::DOM::SkipSpaces(buffer)) - return false; + if (!PLY::DOM::SkipSpaces(buffer)) + return false; - if (PLY::EEST_TextureFile == pOut->eSemantic) - { - char* endPos = &buffer[0] + (strlen(&buffer[0]) - 1); - pOut->szName = std::string(&buffer[0], endPos); + if (PLY::EEST_TextureFile == pOut->eSemantic) { + char *endPos = &buffer[0] + (strlen(&buffer[0]) - 1); + pOut->szName = std::string(&buffer[0], endPos); + + // go to the next line + PLY::DOM::SkipSpacesAndLineEnd(buffer); + + return true; + } + + //parse the number of occurrences of this element + const char *pCur = (char *)&buffer[0]; + pOut->NumOccur = strtoul10(pCur, &pCur); // go to the next line PLY::DOM::SkipSpacesAndLineEnd(buffer); - return true; - } + // now parse all properties of the element + while (true) { + streamBuffer.getNextLine(buffer); + pCur = (char *)&buffer[0]; - //parse the number of occurrences of this element - const char* pCur = (char*)&buffer[0]; - pOut->NumOccur = strtoul10(pCur, &pCur); + // skip all comments + PLY::DOM::SkipComments(buffer); - // go to the next line - PLY::DOM::SkipSpacesAndLineEnd(buffer); + PLY::Property prop; + if (!PLY::Property::ParseProperty(buffer, &prop)) + break; - // now parse all properties of the element - while (true) - { - streamBuffer.getNextLine(buffer); - pCur = (char*)&buffer[0]; - - // skip all comments - PLY::DOM::SkipComments(buffer); - - PLY::Property prop; - if (!PLY::Property::ParseProperty(buffer, &prop)) - break; - - pOut->alProperties.push_back(prop); - } - - return true; -} - -// ------------------------------------------------------------------------------------------------ -bool PLY::DOM::SkipSpaces(std::vector &buffer) -{ - const char* pCur = buffer.empty() ? NULL : (char*)&buffer[0]; - bool ret = false; - if (pCur) - { - const char* szCur = pCur; - ret = Assimp::SkipSpaces(pCur, &pCur); - - uintptr_t iDiff = (uintptr_t)pCur - (uintptr_t)szCur; - buffer.erase(buffer.begin(), buffer.begin() + iDiff); - return ret; - } - - return ret; -} - -bool PLY::DOM::SkipLine(std::vector &buffer) -{ - const char* pCur = buffer.empty() ? NULL : (char*)&buffer[0]; - bool ret = false; - if (pCur) - { - const char* szCur = pCur; - ret = Assimp::SkipLine(pCur, &pCur); - - uintptr_t iDiff = (uintptr_t)pCur - (uintptr_t)szCur; - buffer.erase(buffer.begin(), buffer.begin() + iDiff); - return ret; - } - - return ret; -} - -bool PLY::DOM::TokenMatch(std::vector &buffer, const char* token, unsigned int len) -{ - const char* pCur = buffer.empty() ? NULL : (char*)&buffer[0]; - bool ret = false; - if (pCur) - { - const char* szCur = pCur; - ret = Assimp::TokenMatch(pCur, token, len); - - uintptr_t iDiff = (uintptr_t)pCur - (uintptr_t)szCur; - buffer.erase(buffer.begin(), buffer.begin() + iDiff); - return ret; - } - - return ret; -} - -bool PLY::DOM::SkipSpacesAndLineEnd(std::vector &buffer) -{ - const char* pCur = buffer.empty() ? NULL : (char*)&buffer[0]; - bool ret = false; - if (pCur) - { - const char* szCur = pCur; - ret = Assimp::SkipSpacesAndLineEnd(pCur, &pCur); - - uintptr_t iDiff = (uintptr_t)pCur - (uintptr_t)szCur; - buffer.erase(buffer.begin(), buffer.begin() + iDiff); - return ret; - } - - return ret; -} - -bool PLY::DOM::SkipComments(std::vector &buffer) -{ - ai_assert(!buffer.empty()); - - std::vector nbuffer = buffer; - // skip spaces - if (!SkipSpaces(nbuffer)) { - return false; - } - - if (TokenMatch(nbuffer, "comment", 7)) - { - if (!SkipSpaces(nbuffer)) - SkipLine(nbuffer); - - if (!TokenMatch(nbuffer, "TextureFile", 11)) - { - SkipLine(nbuffer); - buffer = nbuffer; - return true; + pOut->alProperties.push_back(prop); } return true; - } +} - return false; +// ------------------------------------------------------------------------------------------------ +bool PLY::DOM::SkipSpaces(std::vector &buffer) { + const char *pCur = buffer.empty() ? nullptr : (char *)&buffer[0]; + bool ret = false; + if (pCur) { + const char *szCur = pCur; + ret = Assimp::SkipSpaces(pCur, &pCur); + + uintptr_t iDiff = (uintptr_t)pCur - (uintptr_t)szCur; + buffer.erase(buffer.begin(), buffer.begin() + iDiff); + return ret; + } + + return ret; +} + +bool PLY::DOM::SkipLine(std::vector &buffer) { + const char *pCur = buffer.empty() ? nullptr : (char *)&buffer[0]; + bool ret = false; + if (pCur) { + const char *szCur = pCur; + ret = Assimp::SkipLine(pCur, &pCur); + + uintptr_t iDiff = (uintptr_t)pCur - (uintptr_t)szCur; + buffer.erase(buffer.begin(), buffer.begin() + iDiff); + return ret; + } + + return ret; +} + +bool PLY::DOM::TokenMatch(std::vector &buffer, const char *token, unsigned int len) { + const char *pCur = buffer.empty() ? nullptr : (char *)&buffer[0]; + bool ret = false; + if (pCur) { + const char *szCur = pCur; + ret = Assimp::TokenMatch(pCur, token, len); + + uintptr_t iDiff = (uintptr_t)pCur - (uintptr_t)szCur; + buffer.erase(buffer.begin(), buffer.begin() + iDiff); + return ret; + } + + return ret; +} + +bool PLY::DOM::SkipSpacesAndLineEnd(std::vector &buffer) { + const char *pCur = buffer.empty() ? nullptr : (char *)&buffer[0]; + bool ret = false; + if (pCur) { + const char *szCur = pCur; + ret = Assimp::SkipSpacesAndLineEnd(pCur, &pCur); + + uintptr_t iDiff = (uintptr_t)pCur - (uintptr_t)szCur; + buffer.erase(buffer.begin(), buffer.begin() + iDiff); + return ret; + } + + return ret; +} + +bool PLY::DOM::SkipComments(std::vector &buffer) { + ai_assert(!buffer.empty()); + + std::vector nbuffer = buffer; + // skip spaces + if (!SkipSpaces(nbuffer)) { + return false; + } + + if (TokenMatch(nbuffer, "comment", 7)) { + if (!SkipSpaces(nbuffer)) + SkipLine(nbuffer); + + if (!TokenMatch(nbuffer, "TextureFile", 11)) { + SkipLine(nbuffer); + buffer = nbuffer; + return true; + } + + return true; + } + + return false; } // ------------------------------------------------------------------------------------------------ bool PLY::DOM::ParseHeader(IOStreamBuffer &streamBuffer, std::vector &buffer, bool isBinary) { ASSIMP_LOG_VERBOSE_DEBUG("PLY::DOM::ParseHeader() begin"); - // parse all elements - while (!buffer.empty()) - { - // skip all comments - PLY::DOM::SkipComments(buffer); + // parse all elements + while (!buffer.empty()) { + // skip all comments + PLY::DOM::SkipComments(buffer); - PLY::Element out; - if (PLY::Element::ParseElement(streamBuffer, buffer, &out)) - { - // add the element to the list of elements - alElements.push_back(out); + PLY::Element out; + if (PLY::Element::ParseElement(streamBuffer, buffer, &out)) { + // add the element to the list of elements + alElements.push_back(out); + } else if (TokenMatch(buffer, "end_header", 10)) { + // we have reached the end of the header + break; + } else { + // ignore unknown header elements + streamBuffer.getNextLine(buffer); + } } - else if (TokenMatch(buffer, "end_header", 10)) - { - // we have reached the end of the header - break; - } - else - { - // ignore unknown header elements - streamBuffer.getNextLine(buffer); - } - } - if (!isBinary) // it would occur an error, if binary data start with values as space or line end. - SkipSpacesAndLineEnd(buffer); + if (!isBinary) // it would occur an error, if binary data start with values as space or line end. + SkipSpacesAndLineEnd(buffer); - ASSIMP_LOG_VERBOSE_DEBUG("PLY::DOM::ParseHeader() succeeded"); - return true; + ASSIMP_LOG_VERBOSE_DEBUG("PLY::DOM::ParseHeader() succeeded"); + return true; } // ------------------------------------------------------------------------------------------------ -bool PLY::DOM::ParseElementInstanceLists(IOStreamBuffer &streamBuffer, std::vector &buffer, PLYImporter* loader) -{ +bool PLY::DOM::ParseElementInstanceLists(IOStreamBuffer &streamBuffer, std::vector &buffer, PLYImporter *loader) { ASSIMP_LOG_VERBOSE_DEBUG("PLY::DOM::ParseElementInstanceLists() begin"); - alElementData.resize(alElements.size()); + alElementData.resize(alElements.size()); - std::vector::const_iterator i = alElements.begin(); - std::vector::iterator a = alElementData.begin(); + std::vector::const_iterator i = alElements.begin(); + std::vector::iterator a = alElementData.begin(); - // parse all element instances - //construct vertices and faces - for (; i != alElements.end(); ++i, ++a) - { - if ((*i).eSemantic == EEST_Vertex || (*i).eSemantic == EEST_Face || (*i).eSemantic == EEST_TriStrip) - { - PLY::ElementInstanceList::ParseInstanceList(streamBuffer, buffer, &(*i), NULL, loader); + // parse all element instances + //construct vertices and faces + for (; i != alElements.end(); ++i, ++a) { + if ((*i).eSemantic == EEST_Vertex || (*i).eSemantic == EEST_Face || (*i).eSemantic == EEST_TriStrip) { + PLY::ElementInstanceList::ParseInstanceList(streamBuffer, buffer, &(*i), nullptr, loader); + } else { + (*a).alInstances.resize((*i).NumOccur); + PLY::ElementInstanceList::ParseInstanceList(streamBuffer, buffer, &(*i), &(*a), nullptr); + } } - else - { - (*a).alInstances.resize((*i).NumOccur); - PLY::ElementInstanceList::ParseInstanceList(streamBuffer, buffer, &(*i), &(*a), NULL); - } - } - ASSIMP_LOG_VERBOSE_DEBUG("PLY::DOM::ParseElementInstanceLists() succeeded"); - return true; + ASSIMP_LOG_VERBOSE_DEBUG("PLY::DOM::ParseElementInstanceLists() succeeded"); + return true; } // ------------------------------------------------------------------------------------------------ bool PLY::DOM::ParseElementInstanceListsBinary(IOStreamBuffer &streamBuffer, std::vector &buffer, - const char* &pCur, - unsigned int &bufferSize, - PLYImporter* loader, - bool p_bBE) -{ + const char *&pCur, + unsigned int &bufferSize, + PLYImporter *loader, + bool p_bBE) { ASSIMP_LOG_VERBOSE_DEBUG("PLY::DOM::ParseElementInstanceListsBinary() begin"); - alElementData.resize(alElements.size()); + alElementData.resize(alElements.size()); - std::vector::const_iterator i = alElements.begin(); - std::vector::iterator a = alElementData.begin(); + std::vector::const_iterator i = alElements.begin(); + std::vector::iterator a = alElementData.begin(); - // parse all element instances - for (; i != alElements.end(); ++i, ++a) - { - if ((*i).eSemantic == EEST_Vertex || (*i).eSemantic == EEST_Face || (*i).eSemantic == EEST_TriStrip) - { - PLY::ElementInstanceList::ParseInstanceListBinary(streamBuffer, buffer, pCur, bufferSize, &(*i), NULL, loader, p_bBE); + // parse all element instances + for (; i != alElements.end(); ++i, ++a) { + if ((*i).eSemantic == EEST_Vertex || (*i).eSemantic == EEST_Face || (*i).eSemantic == EEST_TriStrip) { + PLY::ElementInstanceList::ParseInstanceListBinary(streamBuffer, buffer, pCur, bufferSize, &(*i), nullptr, loader, p_bBE); + } else { + (*a).alInstances.resize((*i).NumOccur); + PLY::ElementInstanceList::ParseInstanceListBinary(streamBuffer, buffer, pCur, bufferSize, &(*i), &(*a), nullptr, p_bBE); + } } - else - { - (*a).alInstances.resize((*i).NumOccur); - PLY::ElementInstanceList::ParseInstanceListBinary(streamBuffer, buffer, pCur, bufferSize, &(*i), &(*a), NULL, p_bBE); - } - } - ASSIMP_LOG_VERBOSE_DEBUG("PLY::DOM::ParseElementInstanceListsBinary() succeeded"); - return true; + ASSIMP_LOG_VERBOSE_DEBUG("PLY::DOM::ParseElementInstanceListsBinary() succeeded"); + return true; } // ------------------------------------------------------------------------------------------------ -bool PLY::DOM::ParseInstanceBinary(IOStreamBuffer &streamBuffer, DOM* p_pcOut, PLYImporter* loader, bool p_bBE) -{ - ai_assert(NULL != p_pcOut); - ai_assert(NULL != loader); +bool PLY::DOM::ParseInstanceBinary(IOStreamBuffer &streamBuffer, DOM *p_pcOut, PLYImporter *loader, bool p_bBE) { + ai_assert(nullptr != p_pcOut); + ai_assert(nullptr != loader); - std::vector buffer; - streamBuffer.getNextLine(buffer); + std::vector buffer; + streamBuffer.getNextLine(buffer); - ASSIMP_LOG_VERBOSE_DEBUG("PLY::DOM::ParseInstanceBinary() begin"); + ASSIMP_LOG_VERBOSE_DEBUG("PLY::DOM::ParseInstanceBinary() begin"); - if (!p_pcOut->ParseHeader(streamBuffer, buffer, true)) - { - ASSIMP_LOG_VERBOSE_DEBUG("PLY::DOM::ParseInstanceBinary() failure"); - return false; - } + if (!p_pcOut->ParseHeader(streamBuffer, buffer, true)) { + ASSIMP_LOG_VERBOSE_DEBUG("PLY::DOM::ParseInstanceBinary() failure"); + return false; + } - streamBuffer.getNextBlock(buffer); - unsigned int bufferSize = static_cast(buffer.size()); - const char* pCur = (char*)&buffer[0]; - if (!p_pcOut->ParseElementInstanceListsBinary(streamBuffer, buffer, pCur, bufferSize, loader, p_bBE)) - { - ASSIMP_LOG_VERBOSE_DEBUG("PLY::DOM::ParseInstanceBinary() failure"); - return false; - } - ASSIMP_LOG_VERBOSE_DEBUG("PLY::DOM::ParseInstanceBinary() succeeded"); - return true; + streamBuffer.getNextBlock(buffer); + unsigned int bufferSize = static_cast(buffer.size()); + const char *pCur = (char *)&buffer[0]; + if (!p_pcOut->ParseElementInstanceListsBinary(streamBuffer, buffer, pCur, bufferSize, loader, p_bBE)) { + ASSIMP_LOG_VERBOSE_DEBUG("PLY::DOM::ParseInstanceBinary() failure"); + return false; + } + ASSIMP_LOG_VERBOSE_DEBUG("PLY::DOM::ParseInstanceBinary() succeeded"); + return true; } // ------------------------------------------------------------------------------------------------ -bool PLY::DOM::ParseInstance(IOStreamBuffer &streamBuffer, DOM* p_pcOut, PLYImporter* loader) -{ - ai_assert(NULL != p_pcOut); - ai_assert(NULL != loader); +bool PLY::DOM::ParseInstance(IOStreamBuffer &streamBuffer, DOM *p_pcOut, PLYImporter *loader) { + ai_assert(nullptr != p_pcOut); + ai_assert(nullptr != loader); - std::vector buffer; - streamBuffer.getNextLine(buffer); + std::vector buffer; + streamBuffer.getNextLine(buffer); - ASSIMP_LOG_VERBOSE_DEBUG("PLY::DOM::ParseInstance() begin"); + ASSIMP_LOG_VERBOSE_DEBUG("PLY::DOM::ParseInstance() begin"); - if (!p_pcOut->ParseHeader(streamBuffer, buffer, false)) - { - ASSIMP_LOG_VERBOSE_DEBUG("PLY::DOM::ParseInstance() failure"); - return false; - } + if (!p_pcOut->ParseHeader(streamBuffer, buffer, false)) { + ASSIMP_LOG_VERBOSE_DEBUG("PLY::DOM::ParseInstance() failure"); + return false; + } - //get next line after header - streamBuffer.getNextLine(buffer); - if (!p_pcOut->ParseElementInstanceLists(streamBuffer, buffer, loader)) - { - ASSIMP_LOG_VERBOSE_DEBUG("PLY::DOM::ParseInstance() failure"); - return false; - } - ASSIMP_LOG_VERBOSE_DEBUG("PLY::DOM::ParseInstance() succeeded"); - return true; + //get next line after header + streamBuffer.getNextLine(buffer); + if (!p_pcOut->ParseElementInstanceLists(streamBuffer, buffer, loader)) { + ASSIMP_LOG_VERBOSE_DEBUG("PLY::DOM::ParseInstance() failure"); + return false; + } + ASSIMP_LOG_VERBOSE_DEBUG("PLY::DOM::ParseInstance() succeeded"); + return true; } // ------------------------------------------------------------------------------------------------ bool PLY::ElementInstanceList::ParseInstanceList( - IOStreamBuffer &streamBuffer, - std::vector &buffer, - const PLY::Element* pcElement, - PLY::ElementInstanceList* p_pcOut, - PLYImporter* loader) -{ - ai_assert(NULL != pcElement); + IOStreamBuffer &streamBuffer, + std::vector &buffer, + const PLY::Element *pcElement, + PLY::ElementInstanceList *p_pcOut, + PLYImporter *loader) { + ai_assert(nullptr != pcElement); - // parse all elements - if (EEST_INVALID == pcElement->eSemantic || pcElement->alProperties.empty()) - { - // if the element has an unknown semantic we can skip all lines - // However, there could be comments - for (unsigned int i = 0; i < pcElement->NumOccur; ++i) - { - PLY::DOM::SkipComments(buffer); - PLY::DOM::SkipLine(buffer); - streamBuffer.getNextLine(buffer); + // parse all elements + if (EEST_INVALID == pcElement->eSemantic || pcElement->alProperties.empty()) { + // if the element has an unknown semantic we can skip all lines + // However, there could be comments + for (unsigned int i = 0; i < pcElement->NumOccur; ++i) { + PLY::DOM::SkipComments(buffer); + PLY::DOM::SkipLine(buffer); + streamBuffer.getNextLine(buffer); + } + } else { + const char *pCur = (const char *)&buffer[0]; + // be sure to have enough storage + for (unsigned int i = 0; i < pcElement->NumOccur; ++i) { + if (p_pcOut) + PLY::ElementInstance::ParseInstance(pCur, pcElement, &p_pcOut->alInstances[i]); + else { + ElementInstance elt; + PLY::ElementInstance::ParseInstance(pCur, pcElement, &elt); + + // Create vertex or face + if (pcElement->eSemantic == EEST_Vertex) { + //call loader instance from here + loader->LoadVertex(pcElement, &elt, i); + } else if (pcElement->eSemantic == EEST_Face) { + //call loader instance from here + loader->LoadFace(pcElement, &elt, i); + } else if (pcElement->eSemantic == EEST_TriStrip) { + //call loader instance from here + loader->LoadFace(pcElement, &elt, i); + } + } + + streamBuffer.getNextLine(buffer); + pCur = (buffer.empty()) ? nullptr : (const char *)&buffer[0]; + } } - } - else - { - const char* pCur = (const char*)&buffer[0]; - // be sure to have enough storage - for (unsigned int i = 0; i < pcElement->NumOccur; ++i) - { - if (p_pcOut) - PLY::ElementInstance::ParseInstance(pCur, pcElement, &p_pcOut->alInstances[i]); - else - { - ElementInstance elt; - PLY::ElementInstance::ParseInstance(pCur, pcElement, &elt); - - // Create vertex or face - if (pcElement->eSemantic == EEST_Vertex) - { - //call loader instance from here - loader->LoadVertex(pcElement, &elt, i); - } - else if (pcElement->eSemantic == EEST_Face) - { - //call loader instance from here - loader->LoadFace(pcElement, &elt, i); - } - else if (pcElement->eSemantic == EEST_TriStrip) - { - //call loader instance from here - loader->LoadFace(pcElement, &elt, i); - } - } - - streamBuffer.getNextLine(buffer); - pCur = (buffer.empty()) ? NULL : (const char*)&buffer[0]; - } - } - return true; + return true; } // ------------------------------------------------------------------------------------------------ bool PLY::ElementInstanceList::ParseInstanceListBinary( - IOStreamBuffer &streamBuffer, - std::vector &buffer, - const char* &pCur, - unsigned int &bufferSize, - const PLY::Element* pcElement, - PLY::ElementInstanceList* p_pcOut, - PLYImporter* loader, - bool p_bBE /* = false */) -{ - ai_assert(NULL != pcElement); + IOStreamBuffer &streamBuffer, + std::vector &buffer, + const char *&pCur, + unsigned int &bufferSize, + const PLY::Element *pcElement, + PLY::ElementInstanceList *p_pcOut, + PLYImporter *loader, + bool p_bBE /* = false */) { + ai_assert(nullptr != pcElement); - // we can add special handling code for unknown element semantics since - // we can't skip it as a whole block (we don't know its exact size - // due to the fact that lists could be contained in the property list - // of the unknown element) - for (unsigned int i = 0; i < pcElement->NumOccur; ++i) - { - if (p_pcOut) - PLY::ElementInstance::ParseInstanceBinary(streamBuffer, buffer, pCur, bufferSize, pcElement, &p_pcOut->alInstances[i], p_bBE); - else - { - ElementInstance elt; - PLY::ElementInstance::ParseInstanceBinary(streamBuffer, buffer, pCur, bufferSize, pcElement, &elt, p_bBE); + // we can add special handling code for unknown element semantics since + // we can't skip it as a whole block (we don't know its exact size + // due to the fact that lists could be contained in the property list + // of the unknown element) + for (unsigned int i = 0; i < pcElement->NumOccur; ++i) { + if (p_pcOut) + PLY::ElementInstance::ParseInstanceBinary(streamBuffer, buffer, pCur, bufferSize, pcElement, &p_pcOut->alInstances[i], p_bBE); + else { + ElementInstance elt; + PLY::ElementInstance::ParseInstanceBinary(streamBuffer, buffer, pCur, bufferSize, pcElement, &elt, p_bBE); - // Create vertex or face - if (pcElement->eSemantic == EEST_Vertex) - { - //call loader instance from here - loader->LoadVertex(pcElement, &elt, i); - } - else if (pcElement->eSemantic == EEST_Face) - { - //call loader instance from here - loader->LoadFace(pcElement, &elt, i); - } - else if (pcElement->eSemantic == EEST_TriStrip) - { - //call loader instance from here - loader->LoadFace(pcElement, &elt, i); - } + // Create vertex or face + if (pcElement->eSemantic == EEST_Vertex) { + //call loader instance from here + loader->LoadVertex(pcElement, &elt, i); + } else if (pcElement->eSemantic == EEST_Face) { + //call loader instance from here + loader->LoadFace(pcElement, &elt, i); + } else if (pcElement->eSemantic == EEST_TriStrip) { + //call loader instance from here + loader->LoadFace(pcElement, &elt, i); + } + } } - } - return true; + return true; } // ------------------------------------------------------------------------------------------------ -bool PLY::ElementInstance::ParseInstance(const char* &pCur, - const PLY::Element* pcElement, - PLY::ElementInstance* p_pcOut) -{ - ai_assert(NULL != pcElement); - ai_assert(NULL != p_pcOut); +bool PLY::ElementInstance::ParseInstance(const char *&pCur, + const PLY::Element *pcElement, + PLY::ElementInstance *p_pcOut) { + ai_assert(nullptr != pcElement); + ai_assert(nullptr != p_pcOut); - // allocate enough storage - p_pcOut->alProperties.resize(pcElement->alProperties.size()); + // allocate enough storage + p_pcOut->alProperties.resize(pcElement->alProperties.size()); - std::vector::iterator i = p_pcOut->alProperties.begin(); - std::vector::const_iterator a = pcElement->alProperties.begin(); - for (; i != p_pcOut->alProperties.end(); ++i, ++a) - { - if (!(PLY::PropertyInstance::ParseInstance(pCur, &(*a), &(*i)))) - { - ASSIMP_LOG_WARN("Unable to parse property instance. " - "Skipping this element instance"); + std::vector::iterator i = p_pcOut->alProperties.begin(); + std::vector::const_iterator a = pcElement->alProperties.begin(); + for (; i != p_pcOut->alProperties.end(); ++i, ++a) { + if (!(PLY::PropertyInstance::ParseInstance(pCur, &(*a), &(*i)))) { + ASSIMP_LOG_WARN("Unable to parse property instance. " + "Skipping this element instance"); - PLY::PropertyInstance::ValueUnion v = PLY::PropertyInstance::DefaultValue((*a).eType); - (*i).avList.push_back(v); + PLY::PropertyInstance::ValueUnion v = PLY::PropertyInstance::DefaultValue((*a).eType); + (*i).avList.push_back(v); + } } - } - return true; + return true; } // ------------------------------------------------------------------------------------------------ bool PLY::ElementInstance::ParseInstanceBinary( - IOStreamBuffer &streamBuffer, - std::vector &buffer, - const char* &pCur, - unsigned int &bufferSize, - const PLY::Element* pcElement, - PLY::ElementInstance* p_pcOut, - bool p_bBE /* = false */) -{ - ai_assert(NULL != pcElement); - ai_assert(NULL != p_pcOut); + IOStreamBuffer &streamBuffer, + std::vector &buffer, + const char *&pCur, + unsigned int &bufferSize, + const PLY::Element *pcElement, + PLY::ElementInstance *p_pcOut, + bool p_bBE /* = false */) { + ai_assert(nullptr != pcElement); + ai_assert(nullptr != p_pcOut); - // allocate enough storage - p_pcOut->alProperties.resize(pcElement->alProperties.size()); + // allocate enough storage + p_pcOut->alProperties.resize(pcElement->alProperties.size()); - std::vector::iterator i = p_pcOut->alProperties.begin(); - std::vector::const_iterator a = pcElement->alProperties.begin(); - for (; i != p_pcOut->alProperties.end(); ++i, ++a) - { - if (!(PLY::PropertyInstance::ParseInstanceBinary(streamBuffer, buffer, pCur, bufferSize, &(*a), &(*i), p_bBE))) - { - ASSIMP_LOG_WARN("Unable to parse binary property instance. " - "Skipping this element instance"); + std::vector::iterator i = p_pcOut->alProperties.begin(); + std::vector::const_iterator a = pcElement->alProperties.begin(); + for (; i != p_pcOut->alProperties.end(); ++i, ++a) { + if (!(PLY::PropertyInstance::ParseInstanceBinary(streamBuffer, buffer, pCur, bufferSize, &(*a), &(*i), p_bBE))) { + ASSIMP_LOG_WARN("Unable to parse binary property instance. " + "Skipping this element instance"); - (*i).avList.push_back(PLY::PropertyInstance::DefaultValue((*a).eType)); + (*i).avList.push_back(PLY::PropertyInstance::DefaultValue((*a).eType)); + } } - } - return true; + return true; } // ------------------------------------------------------------------------------------------------ -bool PLY::PropertyInstance::ParseInstance(const char* &pCur, - const PLY::Property* prop, PLY::PropertyInstance* p_pcOut) -{ - ai_assert(NULL != prop); - ai_assert(NULL != p_pcOut); +bool PLY::PropertyInstance::ParseInstance(const char *&pCur, + const PLY::Property *prop, PLY::PropertyInstance *p_pcOut) { + ai_assert(nullptr != prop); + ai_assert(nullptr != p_pcOut); - // skip spaces at the beginning - if (!SkipSpaces(&pCur)) - { - return false; - } - - if (prop->bIsList) - { - // parse the number of elements in the list - PLY::PropertyInstance::ValueUnion v; - PLY::PropertyInstance::ParseValue(pCur, prop->eFirstType, &v); - - // convert to unsigned int - unsigned int iNum = PLY::PropertyInstance::ConvertTo(v, prop->eFirstType); - - // parse all list elements - p_pcOut->avList.resize(iNum); - for (unsigned int i = 0; i < iNum; ++i) - { - if (!SkipSpaces(&pCur)) + // skip spaces at the beginning + if (!SkipSpaces(&pCur)) { return false; - - PLY::PropertyInstance::ParseValue(pCur, prop->eType, &p_pcOut->avList[i]); } - } - else - { - // parse the property - PLY::PropertyInstance::ValueUnion v; - PLY::PropertyInstance::ParseValue(pCur, prop->eType, &v); - p_pcOut->avList.push_back(v); - } - SkipSpacesAndLineEnd(&pCur); - return true; + if (prop->bIsList) { + // parse the number of elements in the list + PLY::PropertyInstance::ValueUnion v; + PLY::PropertyInstance::ParseValue(pCur, prop->eFirstType, &v); + + // convert to unsigned int + unsigned int iNum = PLY::PropertyInstance::ConvertTo(v, prop->eFirstType); + + // parse all list elements + p_pcOut->avList.resize(iNum); + for (unsigned int i = 0; i < iNum; ++i) { + if (!SkipSpaces(&pCur)) + return false; + + PLY::PropertyInstance::ParseValue(pCur, prop->eType, &p_pcOut->avList[i]); + } + } else { + // parse the property + PLY::PropertyInstance::ValueUnion v; + + PLY::PropertyInstance::ParseValue(pCur, prop->eType, &v); + p_pcOut->avList.push_back(v); + } + SkipSpacesAndLineEnd(&pCur); + return true; } // ------------------------------------------------------------------------------------------------ bool PLY::PropertyInstance::ParseInstanceBinary(IOStreamBuffer &streamBuffer, std::vector &buffer, - const char* &pCur, - unsigned int &bufferSize, - const PLY::Property* prop, - PLY::PropertyInstance* p_pcOut, - bool p_bBE) -{ - ai_assert(NULL != prop); - ai_assert(NULL != p_pcOut); + const char *&pCur, + unsigned int &bufferSize, + const PLY::Property *prop, + PLY::PropertyInstance *p_pcOut, + bool p_bBE) { + ai_assert(nullptr != prop); + ai_assert(nullptr != p_pcOut); - // parse all elements - if (prop->bIsList) - { - // parse the number of elements in the list - PLY::PropertyInstance::ValueUnion v; - PLY::PropertyInstance::ParseValueBinary(streamBuffer, buffer, pCur, bufferSize, prop->eFirstType, &v, p_bBE); + // parse all elements + if (prop->bIsList) { + // parse the number of elements in the list + PLY::PropertyInstance::ValueUnion v; + PLY::PropertyInstance::ParseValueBinary(streamBuffer, buffer, pCur, bufferSize, prop->eFirstType, &v, p_bBE); - // convert to unsigned int - unsigned int iNum = PLY::PropertyInstance::ConvertTo(v, prop->eFirstType); + // convert to unsigned int + unsigned int iNum = PLY::PropertyInstance::ConvertTo(v, prop->eFirstType); - // parse all list elements - p_pcOut->avList.resize(iNum); - for (unsigned int i = 0; i < iNum; ++i) - { - PLY::PropertyInstance::ParseValueBinary(streamBuffer, buffer, pCur, bufferSize, prop->eType, &p_pcOut->avList[i], p_bBE); + // parse all list elements + p_pcOut->avList.resize(iNum); + for (unsigned int i = 0; i < iNum; ++i) { + PLY::PropertyInstance::ParseValueBinary(streamBuffer, buffer, pCur, bufferSize, prop->eType, &p_pcOut->avList[i], p_bBE); + } + } else { + // parse the property + PLY::PropertyInstance::ValueUnion v; + PLY::PropertyInstance::ParseValueBinary(streamBuffer, buffer, pCur, bufferSize, prop->eType, &v, p_bBE); + p_pcOut->avList.push_back(v); } - } - else - { - // parse the property - PLY::PropertyInstance::ValueUnion v; - PLY::PropertyInstance::ParseValueBinary(streamBuffer, buffer, pCur, bufferSize, prop->eType, &v, p_bBE); - p_pcOut->avList.push_back(v); - } - return true; + return true; } // ------------------------------------------------------------------------------------------------ -PLY::PropertyInstance::ValueUnion PLY::PropertyInstance::DefaultValue(PLY::EDataType eType) -{ - PLY::PropertyInstance::ValueUnion out; +PLY::PropertyInstance::ValueUnion PLY::PropertyInstance::DefaultValue(PLY::EDataType eType) { + PLY::PropertyInstance::ValueUnion out; - switch (eType) - { - case EDT_Float: - out.fFloat = 0.f; + switch (eType) { + case EDT_Float: + out.fFloat = 0.f; + return out; + + case EDT_Double: + out.fDouble = 0.; + return out; + + default:; + }; + out.iUInt = 0; return out; - - case EDT_Double: - out.fDouble = 0.; - return out; - - default:; - }; - out.iUInt = 0; - return out; } // ------------------------------------------------------------------------------------------------ -bool PLY::PropertyInstance::ParseValue(const char* &pCur, - PLY::EDataType eType, - PLY::PropertyInstance::ValueUnion* out) -{ - ai_assert(NULL != pCur); - ai_assert(NULL != out); +bool PLY::PropertyInstance::ParseValue(const char *&pCur, + PLY::EDataType eType, + PLY::PropertyInstance::ValueUnion *out) { + ai_assert(nullptr != pCur); + ai_assert(nullptr != out); - //calc element size - bool ret = true; - switch (eType) - { - case EDT_UInt: - case EDT_UShort: - case EDT_UChar: + //calc element size + bool ret = true; + switch (eType) { + case EDT_UInt: + case EDT_UShort: + case EDT_UChar: - out->iUInt = (uint32_t)strtoul10(pCur, &pCur); - break; + out->iUInt = (uint32_t)strtoul10(pCur, &pCur); + break; - case EDT_Int: - case EDT_Short: - case EDT_Char: + case EDT_Int: + case EDT_Short: + case EDT_Char: - out->iInt = (int32_t)strtol10(pCur, &pCur); - break; + out->iInt = (int32_t)strtol10(pCur, &pCur); + break; - case EDT_Float: - // technically this should cast to float, but people tend to use float descriptors for double data - // this is the best way to not risk losing precision on import and it doesn't hurt to do this - ai_real f; - pCur = fast_atoreal_move(pCur, f); - out->fFloat = (ai_real)f; - break; + case EDT_Float: + // technically this should cast to float, but people tend to use float descriptors for double data + // this is the best way to not risk losing precision on import and it doesn't hurt to do this + ai_real f; + pCur = fast_atoreal_move(pCur, f); + out->fFloat = (ai_real)f; + break; - case EDT_Double: - double d; - pCur = fast_atoreal_move(pCur, d); - out->fDouble = (double)d; - break; + case EDT_Double: + double d; + pCur = fast_atoreal_move(pCur, d); + out->fDouble = (double)d; + break; - case EDT_INVALID: - default: - ret = false; - break; - } + case EDT_INVALID: + default: + ret = false; + break; + } - return ret; + return ret; } // ------------------------------------------------------------------------------------------------ bool PLY::PropertyInstance::ParseValueBinary(IOStreamBuffer &streamBuffer, - std::vector &buffer, - const char* &pCur, - unsigned int &bufferSize, - PLY::EDataType eType, - PLY::PropertyInstance::ValueUnion* out, - bool p_bBE) -{ - ai_assert(NULL != out); + std::vector &buffer, + const char *&pCur, + unsigned int &bufferSize, + PLY::EDataType eType, + PLY::PropertyInstance::ValueUnion *out, + bool p_bBE) { + ai_assert(nullptr != out); - //calc element size - unsigned int lsize = 0; - switch (eType) - { - case EDT_Char: - case EDT_UChar: - lsize = 1; - break; + //calc element size + unsigned int lsize = 0; + switch (eType) { + case EDT_Char: + case EDT_UChar: + lsize = 1; + break; - case EDT_UShort: - case EDT_Short: - lsize = 2; - break; + case EDT_UShort: + case EDT_Short: + lsize = 2; + break; - case EDT_UInt: - case EDT_Int: - case EDT_Float: - lsize = 4; - break; + case EDT_UInt: + case EDT_Int: + case EDT_Float: + lsize = 4; + break; - case EDT_Double: - lsize = 8; - break; + case EDT_Double: + lsize = 8; + break; - case EDT_INVALID: - default: - break; - } - - //read the next file block if needed - if (bufferSize < lsize) - { - std::vector nbuffer; - if (streamBuffer.getNextBlock(nbuffer)) - { - //concat buffer contents - buffer = std::vector(buffer.end() - bufferSize, buffer.end()); - buffer.insert(buffer.end(), nbuffer.begin(), nbuffer.end()); - nbuffer.clear(); - bufferSize = static_cast(buffer.size()); - pCur = (char*)&buffer[0]; + case EDT_INVALID: + default: + break; } - else - { - throw DeadlyImportError("Invalid .ply file: File corrupted"); + + //read the next file block if needed + if (bufferSize < lsize) { + std::vector nbuffer; + if (streamBuffer.getNextBlock(nbuffer)) { + //concat buffer contents + buffer = std::vector(buffer.end() - bufferSize, buffer.end()); + buffer.insert(buffer.end(), nbuffer.begin(), nbuffer.end()); + nbuffer.clear(); + bufferSize = static_cast(buffer.size()); + pCur = (char *)&buffer[0]; + } else { + throw DeadlyImportError("Invalid .ply file: File corrupted"); + } } - } - bool ret = true; - switch (eType) - { - case EDT_UInt: - { - uint32_t t; - memcpy(&t, pCur, sizeof(uint32_t)); - pCur += sizeof(uint32_t); + bool ret = true; + switch (eType) { + case EDT_UInt: { + uint32_t t; + memcpy(&t, pCur, sizeof(uint32_t)); + pCur += sizeof(uint32_t); - // Swap endianness - if (p_bBE)ByteSwap::Swap(&t); - out->iUInt = t; - break; - } + // Swap endianness + if (p_bBE) ByteSwap::Swap(&t); + out->iUInt = t; + break; + } - case EDT_UShort: - { - uint16_t t; - memcpy(&t, pCur, sizeof(uint16_t)); - pCur += sizeof(uint16_t); + case EDT_UShort: { + uint16_t t; + memcpy(&t, pCur, sizeof(uint16_t)); + pCur += sizeof(uint16_t); - // Swap endianness - if (p_bBE)ByteSwap::Swap(&t); - out->iUInt = t; - break; - } + // Swap endianness + if (p_bBE) ByteSwap::Swap(&t); + out->iUInt = t; + break; + } - case EDT_UChar: - { - uint8_t t; - memcpy(&t, pCur, sizeof(uint8_t)); - pCur += sizeof(uint8_t); - out->iUInt = t; - break; - } + case EDT_UChar: { + uint8_t t; + memcpy(&t, pCur, sizeof(uint8_t)); + pCur += sizeof(uint8_t); + out->iUInt = t; + break; + } - case EDT_Int: - { - int32_t t; - memcpy(&t, pCur, sizeof(int32_t)); - pCur += sizeof(int32_t); + case EDT_Int: { + int32_t t; + memcpy(&t, pCur, sizeof(int32_t)); + pCur += sizeof(int32_t); - // Swap endianness - if (p_bBE)ByteSwap::Swap(&t); - out->iInt = t; - break; - } + // Swap endianness + if (p_bBE) ByteSwap::Swap(&t); + out->iInt = t; + break; + } - case EDT_Short: - { - int16_t t; - memcpy(&t, pCur, sizeof(int16_t)); - pCur += sizeof(int16_t); + case EDT_Short: { + int16_t t; + memcpy(&t, pCur, sizeof(int16_t)); + pCur += sizeof(int16_t); - // Swap endianness - if (p_bBE)ByteSwap::Swap(&t); - out->iInt = t; - break; - } + // Swap endianness + if (p_bBE) ByteSwap::Swap(&t); + out->iInt = t; + break; + } - case EDT_Char: - { - int8_t t; - memcpy(&t, pCur, sizeof(int8_t)); - pCur += sizeof(int8_t); - out->iInt = t; - break; - } + case EDT_Char: { + int8_t t; + memcpy(&t, pCur, sizeof(int8_t)); + pCur += sizeof(int8_t); + out->iInt = t; + break; + } - case EDT_Float: - { - float t; - memcpy(&t, pCur, sizeof(float)); - pCur += sizeof(float); + case EDT_Float: { + float t; + memcpy(&t, pCur, sizeof(float)); + pCur += sizeof(float); - // Swap endianness - if (p_bBE)ByteSwap::Swap(&t); - out->fFloat = t; - break; - } - case EDT_Double: - { - double t; - memcpy(&t, pCur, sizeof(double)); - pCur += sizeof(double); + // Swap endianness + if (p_bBE) ByteSwap::Swap(&t); + out->fFloat = t; + break; + } + case EDT_Double: { + double t; + memcpy(&t, pCur, sizeof(double)); + pCur += sizeof(double); - // Swap endianness - if (p_bBE)ByteSwap::Swap(&t); - out->fDouble = t; - break; - } - default: - ret = false; - } + // Swap endianness + if (p_bBE) ByteSwap::Swap(&t); + out->fDouble = t; + break; + } + default: + ret = false; + } - bufferSize -= lsize; + bufferSize -= lsize; - return ret; + return ret; } #endif // !! ASSIMP_BUILD_NO_PLY_IMPORTER diff --git a/code/AssetLib/Q3BSP/Q3BSPFileImporter.cpp b/code/AssetLib/Q3BSP/Q3BSPFileImporter.cpp index 131e61534..52a2b7503 100644 --- a/code/AssetLib/Q3BSP/Q3BSPFileImporter.cpp +++ b/code/AssetLib/Q3BSP/Q3BSPFileImporter.cpp @@ -43,27 +43,27 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef ASSIMP_BUILD_NO_Q3BSP_IMPORTER #include "Q3BSPFileImporter.h" -#include "Q3BSPFileParser.h" #include "Q3BSPFileData.h" +#include "Q3BSPFileParser.h" #include #ifdef ASSIMP_BUILD_NO_OWN_ZLIB -# include +#include #else -# include "../contrib/zlib/zlib.h" +#include "../contrib/zlib/zlib.h" #endif -#include +#include +#include +#include +#include +#include #include #include -#include -#include -#include -#include -#include +#include #include -#include +#include static const aiImporterDesc desc = { "Quake III BSP Importer", @@ -84,7 +84,7 @@ using namespace Q3BSP; // ------------------------------------------------------------------------------------------------ // Local function to create a material key name. -static void createKey( int id1, int id2, std::string &key ) { +static void createKey(int id1, int id2, std::string &key) { std::ostringstream str; str << id1 << "." << id2; key = str.str(); @@ -92,27 +92,27 @@ static void createKey( int id1, int id2, std::string &key ) { // ------------------------------------------------------------------------------------------------ // Local function to extract the texture ids from a material key-name. -static void extractIds( const std::string &key, int &id1, int &id2 ) { +static void extractIds(const std::string &key, int &id1, int &id2) { id1 = -1; id2 = -1; if (key.empty()) { return; } - const std::string::size_type pos = key.find( "." ); + const std::string::size_type pos = key.find("."); if (std::string::npos == pos) { return; } - std::string tmp1 = key.substr( 0, pos ); - std::string tmp2 = key.substr( pos + 1, key.size() - pos - 1 ); - id1 = atoi( tmp1.c_str() ); - id2 = atoi( tmp2.c_str() ); + std::string tmp1 = key.substr(0, pos); + std::string tmp2 = key.substr(pos + 1, key.size() - pos - 1); + id1 = atoi(tmp1.c_str()); + id2 = atoi(tmp2.c_str()); } // ------------------------------------------------------------------------------------------------ // Local helper function to normalize filenames. -static void normalizePathName( const std::string &rPath, std::string &normalizedPath ) { +static void normalizePathName(const std::string &rPath, std::string &normalizedPath) { normalizedPath = ""; if (rPath.empty()) { return; @@ -125,12 +125,12 @@ static void normalizePathName( const std::string &rPath, std::string &normalized #endif static const unsigned int numDelimiters = 2; - const char delimiters[ numDelimiters ] = { '/', '\\' }; + const char delimiters[numDelimiters] = { '/', '\\' }; normalizedPath = rPath; for (const char delimiter : delimiters) { - for ( size_t j=0; jfirst; - if ( !matName.empty() ) { + if (!matName.empty()) { delete it->second; } } @@ -164,9 +161,9 @@ Q3BSPFileImporter::~Q3BSPFileImporter() { // ------------------------------------------------------------------------------------------------ // Returns true, if the loader can read this. -bool Q3BSPFileImporter::CanRead( const std::string& rFile, IOSystem* /*pIOHandler*/, bool checkSig ) const { - if(!checkSig) { - return SimpleExtensionCheck( rFile, "pk3", "bsp" ); +bool Q3BSPFileImporter::CanRead(const std::string &rFile, IOSystem * /*pIOHandler*/, bool checkSig) const { + if (!checkSig) { + return SimpleExtensionCheck(rFile, "pk3", "bsp"); } return false; @@ -174,69 +171,69 @@ bool Q3BSPFileImporter::CanRead( const std::string& rFile, IOSystem* /*pIOHandle // ------------------------------------------------------------------------------------------------ // Adds extensions. -const aiImporterDesc* Q3BSPFileImporter::GetInfo () const { +const aiImporterDesc *Q3BSPFileImporter::GetInfo() const { return &desc; } // ------------------------------------------------------------------------------------------------ // Import method. -void Q3BSPFileImporter::InternReadFile(const std::string &rFile, aiScene* scene, IOSystem* ioHandler) { - ZipArchiveIOSystem Archive( ioHandler, rFile ); - if ( !Archive.isOpen() ) { - throw DeadlyImportError( "Failed to open file " + rFile + "." ); +void Q3BSPFileImporter::InternReadFile(const std::string &rFile, aiScene *scene, IOSystem *ioHandler) { + ZipArchiveIOSystem Archive(ioHandler, rFile); + if (!Archive.isOpen()) { + throw DeadlyImportError("Failed to open file " + rFile + "."); } - std::string archiveName( "" ), mapName( "" ); - separateMapName( rFile, archiveName, mapName ); + std::string archiveName(""), mapName(""); + separateMapName(rFile, archiveName, mapName); - if ( mapName.empty() ) { - if ( !findFirstMapInArchive( Archive, mapName ) ) { + if (mapName.empty()) { + if (!findFirstMapInArchive(Archive, mapName)) { return; } } - Q3BSPFileParser fileParser( mapName, &Archive ); + Q3BSPFileParser fileParser(mapName, &Archive); Q3BSPModel *pBSPModel = fileParser.getModel(); - if ( nullptr != pBSPModel ) { - CreateDataFromImport( pBSPModel, scene, &Archive ); + if (nullptr != pBSPModel) { + CreateDataFromImport(pBSPModel, scene, &Archive); } } // ------------------------------------------------------------------------------------------------ // Separates the map name from the import name. -void Q3BSPFileImporter::separateMapName( const std::string &importName, std::string &archiveName, std::string &mapName ) { +void Q3BSPFileImporter::separateMapName(const std::string &importName, std::string &archiveName, std::string &mapName) { archiveName = ""; mapName = ""; if (importName.empty()) { return; } - const std::string::size_type pos = importName.rfind( "," ); - if ( std::string::npos == pos ) { + const std::string::size_type pos = importName.rfind(","); + if (std::string::npos == pos) { archiveName = importName; return; } - archiveName = importName.substr( 0, pos ); - mapName = importName.substr( pos, importName.size() - pos - 1 ); + archiveName = importName.substr(0, pos); + mapName = importName.substr(pos, importName.size() - pos - 1); } // ------------------------------------------------------------------------------------------------ // Returns the first map in the map archive. -bool Q3BSPFileImporter::findFirstMapInArchive(ZipArchiveIOSystem &bspArchive, std::string &mapName ) { +bool Q3BSPFileImporter::findFirstMapInArchive(ZipArchiveIOSystem &bspArchive, std::string &mapName) { mapName = ""; std::vector fileList; - bspArchive.getFileListExtension( fileList, "bsp" ); + bspArchive.getFileListExtension(fileList, "bsp"); if (fileList.empty()) { return false; } - std::vector::iterator it( fileList.begin() ); - for ( ; it != fileList.end(); ++it ) { - const std::string::size_type pos = (*it).find( "maps/" ); - if ( std::string::npos != pos ) { - std::string::size_type extPos = (*it).find( ".bsp" ); - if ( std::string::npos != extPos ) { + std::vector::iterator it(fileList.begin()); + for (; it != fileList.end(); ++it) { + const std::string::size_type pos = (*it).find("maps/"); + if (std::string::npos != pos) { + std::string::size_type extPos = (*it).find(".bsp"); + if (std::string::npos != extPos) { mapName = *it; return true; } @@ -248,122 +245,122 @@ bool Q3BSPFileImporter::findFirstMapInArchive(ZipArchiveIOSystem &bspArchive, st // ------------------------------------------------------------------------------------------------ // Creates the assimp specific data. -void Q3BSPFileImporter::CreateDataFromImport( const Q3BSP::Q3BSPModel *pModel, aiScene* pScene, - ZipArchiveIOSystem *pArchive ) { +void Q3BSPFileImporter::CreateDataFromImport(const Q3BSP::Q3BSPModel *pModel, aiScene *pScene, + ZipArchiveIOSystem *pArchive) { if (nullptr == pModel || nullptr == pScene) { return; } pScene->mRootNode = new aiNode; - if ( !pModel->m_ModelName.empty() ) { - pScene->mRootNode->mName.Set( pModel->m_ModelName ); + if (!pModel->m_ModelName.empty()) { + pScene->mRootNode->mName.Set(pModel->m_ModelName); } // Create the face to material relation map - createMaterialMap( pModel ); + createMaterialMap(pModel); // Create all nodes - CreateNodes( pModel, pScene, pScene->mRootNode ); + CreateNodes(pModel, pScene, pScene->mRootNode); // Create the assigned materials - createMaterials( pModel, pScene, pArchive ); + createMaterials(pModel, pScene, pArchive); } // ------------------------------------------------------------------------------------------------ // Creates all assimp nodes. -void Q3BSPFileImporter::CreateNodes( const Q3BSP::Q3BSPModel *pModel, aiScene* pScene, - aiNode *pParent ) { - if ( nullptr == pModel ) { +void Q3BSPFileImporter::CreateNodes(const Q3BSP::Q3BSPModel *pModel, aiScene *pScene, + aiNode *pParent) { + if (nullptr == pModel) { return; } - unsigned int matIdx( 0 ); - std::vector MeshArray; - std::vector NodeArray; - for ( FaceMapIt it = m_MaterialLookupMap.begin(); it != m_MaterialLookupMap.end(); ++it ) { - std::vector *pArray = (*it).second; - size_t numVerts = countData( *pArray ); - if ( 0 != numVerts ) { - aiMesh *pMesh( nullptr ); - aiNode *pNode = CreateTopology( pModel, matIdx, *pArray, &pMesh ); - if ( nullptr != pNode ) { - NodeArray.push_back( pNode ); - MeshArray.push_back( pMesh ); + unsigned int matIdx(0); + std::vector MeshArray; + std::vector NodeArray; + for (FaceMapIt it = m_MaterialLookupMap.begin(); it != m_MaterialLookupMap.end(); ++it) { + std::vector *pArray = (*it).second; + size_t numVerts = countData(*pArray); + if (0 != numVerts) { + aiMesh *pMesh(nullptr); + aiNode *pNode = CreateTopology(pModel, matIdx, *pArray, &pMesh); + if (nullptr != pNode) { + NodeArray.push_back(pNode); + MeshArray.push_back(pMesh); } } matIdx++; } - pScene->mNumMeshes = static_cast( MeshArray.size() ); - if ( pScene->mNumMeshes > 0 ) { - pScene->mMeshes = new aiMesh*[ pScene->mNumMeshes ]; - for ( size_t i = 0; i < MeshArray.size(); i++ ) { - aiMesh *pMesh = MeshArray[ i ]; - if ( nullptr != pMesh ) { - pScene->mMeshes[ i ] = pMesh; + pScene->mNumMeshes = static_cast(MeshArray.size()); + if (pScene->mNumMeshes > 0) { + pScene->mMeshes = new aiMesh *[pScene->mNumMeshes]; + for (size_t i = 0; i < MeshArray.size(); i++) { + aiMesh *pMesh = MeshArray[i]; + if (nullptr != pMesh) { + pScene->mMeshes[i] = pMesh; } } } pParent->mNumChildren = static_cast(MeshArray.size()); - pParent->mChildren = new aiNode*[ pScene->mRootNode->mNumChildren ]; - for ( size_t i=0; imChildren = new aiNode *[pScene->mRootNode->mNumChildren]; + for (size_t i = 0; i < NodeArray.size(); i++) { + aiNode *pNode = NodeArray[i]; pNode->mParent = pParent; - pParent->mChildren[ i ] = pNode; - pParent->mChildren[ i ]->mMeshes[ 0 ] = static_cast(i); + pParent->mChildren[i] = pNode; + pParent->mChildren[i]->mMeshes[0] = static_cast(i); } } // ------------------------------------------------------------------------------------------------ // Creates the topology. -aiNode *Q3BSPFileImporter::CreateTopology( const Q3BSP::Q3BSPModel *pModel, unsigned int materialIdx, - std::vector &rArray, aiMesh **pMesh ) { - size_t numVerts = countData( rArray ); - if ( 0 == numVerts ) { +aiNode *Q3BSPFileImporter::CreateTopology(const Q3BSP::Q3BSPModel *pModel, unsigned int materialIdx, + std::vector &rArray, aiMesh **pMesh) { + size_t numVerts = countData(rArray); + if (0 == numVerts) { return nullptr; } - size_t numFaces = countFaces( rArray ); - if ( 0 == numFaces ) { + size_t numFaces = countFaces(rArray); + if (0 == numFaces) { return nullptr; } aiMesh *mesh = new aiMesh; - size_t numTriangles = countTriangles( rArray ); + size_t numTriangles = countTriangles(rArray); mesh->mPrimitiveTypes = aiPrimitiveType_TRIANGLE; - mesh->mFaces = new aiFace[ numTriangles ]; + mesh->mFaces = new aiFace[numTriangles]; mesh->mNumFaces = static_cast(numTriangles); mesh->mNumVertices = static_cast(numVerts); - mesh->mVertices = new aiVector3D[ numVerts ]; - mesh->mNormals = new aiVector3D[ numVerts ]; - mesh->mTextureCoords[ 0 ] = new aiVector3D[ numVerts ]; - mesh->mTextureCoords[ 1 ] = new aiVector3D[ numVerts ]; + mesh->mVertices = new aiVector3D[numVerts]; + mesh->mNormals = new aiVector3D[numVerts]; + mesh->mTextureCoords[0] = new aiVector3D[numVerts]; + mesh->mTextureCoords[1] = new aiVector3D[numVerts]; mesh->mMaterialIndex = materialIdx; unsigned int faceIdx = 0; unsigned int vertIdx = 0; - mesh->mNumUVComponents[ 0 ] = 2; - mesh->mNumUVComponents[ 1 ] = 2; - for ( std::vector::const_iterator it = rArray.begin(); it != rArray.end(); ++it ) { + mesh->mNumUVComponents[0] = 2; + mesh->mNumUVComponents[1] = 2; + for (std::vector::const_iterator it = rArray.begin(); it != rArray.end(); ++it) { Q3BSP::sQ3BSPFace *pQ3BSPFace = *it; - ai_assert( NULL != pQ3BSPFace ); - if ( nullptr == pQ3BSPFace ) { + ai_assert(nullptr != pQ3BSPFace); + if (nullptr == pQ3BSPFace) { continue; } - if ( pQ3BSPFace->iNumOfFaceVerts > 0 ) { - if ( pQ3BSPFace->iType == Polygon || pQ3BSPFace->iType == TriangleMesh ) { - createTriangleTopology( pModel, pQ3BSPFace, mesh, faceIdx, vertIdx ); + if (pQ3BSPFace->iNumOfFaceVerts > 0) { + if (pQ3BSPFace->iType == Polygon || pQ3BSPFace->iType == TriangleMesh) { + createTriangleTopology(pModel, pQ3BSPFace, mesh, faceIdx, vertIdx); } } } aiNode *pNode = new aiNode; pNode->mNumMeshes = 1; - pNode->mMeshes = new unsigned int[ 1 ]; + pNode->mMeshes = new unsigned int[1]; *pMesh = mesh; return pNode; @@ -371,27 +368,27 @@ aiNode *Q3BSPFileImporter::CreateTopology( const Q3BSP::Q3BSPModel *pModel, unsi // ------------------------------------------------------------------------------------------------ // Creates the triangle topology from a face array. -void Q3BSPFileImporter::createTriangleTopology( const Q3BSP::Q3BSPModel *pModel, sQ3BSPFace *pQ3BSPFace, - aiMesh* pMesh, unsigned int &faceIdx, unsigned int &vertIdx ) { - ai_assert( faceIdx < pMesh->mNumFaces ); +void Q3BSPFileImporter::createTriangleTopology(const Q3BSP::Q3BSPModel *pModel, sQ3BSPFace *pQ3BSPFace, + aiMesh *pMesh, unsigned int &faceIdx, unsigned int &vertIdx) { + ai_assert(faceIdx < pMesh->mNumFaces); - m_pCurrentFace = getNextFace( pMesh, faceIdx ); - if ( nullptr == m_pCurrentFace ) { + m_pCurrentFace = getNextFace(pMesh, faceIdx); + if (nullptr == m_pCurrentFace) { return; } m_pCurrentFace->mNumIndices = 3; - m_pCurrentFace->mIndices = new unsigned int[ m_pCurrentFace->mNumIndices ]; + m_pCurrentFace->mIndices = new unsigned int[m_pCurrentFace->mNumIndices]; - size_t idx( 0 ); - for ( size_t i = 0; i < (size_t) pQ3BSPFace->iNumOfFaceVerts; ++i ) { - const size_t index = pQ3BSPFace->iVertexIndex + pModel->m_Indices[ pQ3BSPFace->iFaceVertexIndex + i ]; - if ( index >= pModel->m_Vertices.size() ) { + size_t idx(0); + for (size_t i = 0; i < (size_t)pQ3BSPFace->iNumOfFaceVerts; ++i) { + const size_t index = pQ3BSPFace->iVertexIndex + pModel->m_Indices[pQ3BSPFace->iFaceVertexIndex + i]; + if (index >= pModel->m_Vertices.size()) { continue; } - sQ3BSPVertex *pVertex = pModel->m_Vertices[ index ]; - if ( nullptr == pVertex ) { + sQ3BSPVertex *pVertex = pModel->m_Vertices[index]; + if (nullptr == pVertex) { continue; } if (idx > 2) { @@ -400,15 +397,15 @@ void Q3BSPFileImporter::createTriangleTopology( const Q3BSP::Q3BSPModel *pModel, if (nullptr != m_pCurrentFace) { m_pCurrentFace->mNumIndices = 3; m_pCurrentFace->mIndices = new unsigned int[3]; - m_pCurrentFace->mIndices[ idx ] = vertIdx; + m_pCurrentFace->mIndices[idx] = vertIdx; } } - pMesh->mVertices[ vertIdx ].Set( pVertex->vPosition.x, pVertex->vPosition.y, pVertex->vPosition.z ); - pMesh->mNormals[ vertIdx ].Set( pVertex->vNormal.x, pVertex->vNormal.y, pVertex->vNormal.z ); + pMesh->mVertices[vertIdx].Set(pVertex->vPosition.x, pVertex->vPosition.y, pVertex->vPosition.z); + pMesh->mNormals[vertIdx].Set(pVertex->vNormal.x, pVertex->vNormal.y, pVertex->vNormal.z); - pMesh->mTextureCoords[ 0 ][ vertIdx ].Set( pVertex->vTexCoord.x, pVertex->vTexCoord.y, 0.0f ); - pMesh->mTextureCoords[ 1 ][ vertIdx ].Set( pVertex->vLightmap.x, pVertex->vLightmap.y, 0.0f ); + pMesh->mTextureCoords[0][vertIdx].Set(pVertex->vTexCoord.x, pVertex->vTexCoord.y, 0.0f); + pMesh->mTextureCoords[1][vertIdx].Set(pVertex->vLightmap.x, pVertex->vLightmap.y, 0.0f); vertIdx++; idx++; @@ -417,65 +414,61 @@ void Q3BSPFileImporter::createTriangleTopology( const Q3BSP::Q3BSPModel *pModel, // ------------------------------------------------------------------------------------------------ // Creates all referenced materials. -void Q3BSPFileImporter::createMaterials( const Q3BSP::Q3BSPModel *pModel, aiScene* pScene, - ZipArchiveIOSystem *pArchive ) { - if ( m_MaterialLookupMap.empty() ) { +void Q3BSPFileImporter::createMaterials(const Q3BSP::Q3BSPModel *pModel, aiScene *pScene, + ZipArchiveIOSystem *pArchive) { + if (m_MaterialLookupMap.empty()) { return; } - pScene->mMaterials = new aiMaterial*[ m_MaterialLookupMap.size() ]; + pScene->mMaterials = new aiMaterial *[m_MaterialLookupMap.size()]; aiString aiMatName; - int textureId( -1 ), lightmapId( -1 ); - for ( FaceMapIt it = m_MaterialLookupMap.begin(); it != m_MaterialLookupMap.end(); - ++it ) { - const std::string matName( it->first ); - if ( matName.empty() ) { + int textureId(-1), lightmapId(-1); + for (FaceMapIt it = m_MaterialLookupMap.begin(); it != m_MaterialLookupMap.end(); + ++it) { + const std::string matName(it->first); + if (matName.empty()) { continue; } - aiMatName.Set( matName ); + aiMatName.Set(matName); aiMaterial *pMatHelper = new aiMaterial; - pMatHelper->AddProperty( &aiMatName, AI_MATKEY_NAME ); + pMatHelper->AddProperty(&aiMatName, AI_MATKEY_NAME); - extractIds( matName, textureId, lightmapId ); + extractIds(matName, textureId, lightmapId); // Adding the texture - if ( -1 != textureId ) { - sQ3BSPTexture *pTexture = pModel->m_Textures[ textureId ]; - if ( nullptr != pTexture ) { - std::string tmp( "*" ), texName( "" ); + if (-1 != textureId) { + sQ3BSPTexture *pTexture = pModel->m_Textures[textureId]; + if (nullptr != pTexture) { + std::string tmp("*"), texName(""); tmp += pTexture->strName; tmp += ".jpg"; - normalizePathName( tmp, texName ); + normalizePathName(tmp, texName); - if ( !importTextureFromArchive( pModel, pArchive, pScene, pMatHelper, textureId ) ) { + if (!importTextureFromArchive(pModel, pArchive, pScene, pMatHelper, textureId)) { ASSIMP_LOG_ERROR("Cannot import texture from archive " + texName); } } - } - if ( -1 != lightmapId ) - { - importLightmap( pModel, pScene, pMatHelper, lightmapId ); + if (-1 != lightmapId) { + importLightmap(pModel, pScene, pMatHelper, lightmapId); } - pScene->mMaterials[ pScene->mNumMaterials ] = pMatHelper; + pScene->mMaterials[pScene->mNumMaterials] = pMatHelper; pScene->mNumMaterials++; } pScene->mNumTextures = static_cast(mTextures.size()); - pScene->mTextures = new aiTexture*[ pScene->mNumTextures ]; - std::copy( mTextures.begin(), mTextures.end(), pScene->mTextures ); + pScene->mTextures = new aiTexture *[pScene->mNumTextures]; + std::copy(mTextures.begin(), mTextures.end(), pScene->mTextures); } // ------------------------------------------------------------------------------------------------ // Counts the number of referenced vertices. -size_t Q3BSPFileImporter::countData( const std::vector &faceArray ) const { - size_t numVerts( 0 ); - for ( std::vector::const_iterator it = faceArray.begin(); it != faceArray.end(); - ++it ) - { +size_t Q3BSPFileImporter::countData(const std::vector &faceArray) const { + size_t numVerts(0); + for (std::vector::const_iterator it = faceArray.begin(); it != faceArray.end(); + ++it) { sQ3BSPFace *pQ3BSPFace = *it; - if ( pQ3BSPFace->iType == Polygon || pQ3BSPFace->iType == TriangleMesh ) - { + if (pQ3BSPFace->iType == Polygon || pQ3BSPFace->iType == TriangleMesh) { Q3BSP::sQ3BSPFace *face = *it; if (nullptr != face) { numVerts += face->iNumOfFaceVerts; @@ -488,15 +481,12 @@ size_t Q3BSPFileImporter::countData( const std::vector &faceArray ) // ------------------------------------------------------------------------------------------------ // Counts the faces with vertices. -size_t Q3BSPFileImporter::countFaces( const std::vector &rArray ) const -{ +size_t Q3BSPFileImporter::countFaces(const std::vector &rArray) const { size_t numFaces = 0; - for ( std::vector::const_iterator it = rArray.begin(); it != rArray.end(); - ++it ) - { + for (std::vector::const_iterator it = rArray.begin(); it != rArray.end(); + ++it) { Q3BSP::sQ3BSPFace *pQ3BSPFace = *it; - if ( pQ3BSPFace->iNumOfFaceVerts > 0 ) - { + if (pQ3BSPFace->iNumOfFaceVerts > 0) { numFaces++; } } @@ -506,15 +496,12 @@ size_t Q3BSPFileImporter::countFaces( const std::vector &rAr // ------------------------------------------------------------------------------------------------ // Counts the number of triangles in a Q3-face-array. -size_t Q3BSPFileImporter::countTriangles( const std::vector &rArray ) const -{ +size_t Q3BSPFileImporter::countTriangles(const std::vector &rArray) const { size_t numTriangles = 0; - for ( std::vector::const_iterator it = rArray.begin(); it != rArray.end(); - ++it ) - { + for (std::vector::const_iterator it = rArray.begin(); it != rArray.end(); + ++it) { const Q3BSP::sQ3BSPFace *pQ3BSPFace = *it; - if ( NULL != pQ3BSPFace ) - { + if (nullptr != pQ3BSPFace) { numTriangles += pQ3BSPFace->iNumOfFaceVerts / 3; } } @@ -524,38 +511,34 @@ size_t Q3BSPFileImporter::countTriangles( const std::vector // ------------------------------------------------------------------------------------------------ // Creates the faces-to-material map. -void Q3BSPFileImporter::createMaterialMap( const Q3BSP::Q3BSPModel *pModel ) { - std::string key( "" ); - std::vector *pCurFaceArray = NULL; - for ( size_t idx = 0; idx < pModel->m_Faces.size(); idx++ ) - { - Q3BSP::sQ3BSPFace *pQ3BSPFace = pModel->m_Faces[ idx ]; +void Q3BSPFileImporter::createMaterialMap(const Q3BSP::Q3BSPModel *pModel) { + std::string key(""); + std::vector *pCurFaceArray = nullptr; + for (size_t idx = 0; idx < pModel->m_Faces.size(); idx++) { + Q3BSP::sQ3BSPFace *pQ3BSPFace = pModel->m_Faces[idx]; const int texId = pQ3BSPFace->iTextureID; const int lightMapId = pQ3BSPFace->iLightmapID; - createKey( texId, lightMapId, key ); - FaceMapIt it = m_MaterialLookupMap.find( key ); - if ( m_MaterialLookupMap.end() == it ) { - pCurFaceArray = new std::vector; - m_MaterialLookupMap[ key ] = pCurFaceArray; - } - else - { + createKey(texId, lightMapId, key); + FaceMapIt it = m_MaterialLookupMap.find(key); + if (m_MaterialLookupMap.end() == it) { + pCurFaceArray = new std::vector; + m_MaterialLookupMap[key] = pCurFaceArray; + } else { pCurFaceArray = (*it).second; } - ai_assert( nullptr != pCurFaceArray ); - if (nullptr != pCurFaceArray ) - { - pCurFaceArray->push_back( pQ3BSPFace ); + ai_assert(nullptr != pCurFaceArray); + if (nullptr != pCurFaceArray) { + pCurFaceArray->push_back(pQ3BSPFace); } } } // ------------------------------------------------------------------------------------------------ // Returns the next face. -aiFace *Q3BSPFileImporter::getNextFace( aiMesh *mesh, unsigned int &faceIdx ) { - aiFace *face( nullptr ); - if ( faceIdx < mesh->mNumFaces ) { - face = &mesh->mFaces[ faceIdx ]; +aiFace *Q3BSPFileImporter::getNextFace(aiMesh *mesh, unsigned int &faceIdx) { + aiFace *face(nullptr); + if (faceIdx < mesh->mNumFaces) { + face = &mesh->mFaces[faceIdx]; ++faceIdx; } @@ -564,31 +547,31 @@ aiFace *Q3BSPFileImporter::getNextFace( aiMesh *mesh, unsigned int &faceIdx ) { // ------------------------------------------------------------------------------------------------ // Imports a texture file. -bool Q3BSPFileImporter::importTextureFromArchive( const Q3BSP::Q3BSPModel *model, - ZipArchiveIOSystem *archive, aiScene*, - aiMaterial *pMatHelper, int textureId ) { - if (nullptr == archive || nullptr == pMatHelper ) { +bool Q3BSPFileImporter::importTextureFromArchive(const Q3BSP::Q3BSPModel *model, + ZipArchiveIOSystem *archive, aiScene *, + aiMaterial *pMatHelper, int textureId) { + if (nullptr == archive || nullptr == pMatHelper) { return false; } - if ( textureId < 0 || textureId >= static_cast( model->m_Textures.size() ) ) { + if (textureId < 0 || textureId >= static_cast(model->m_Textures.size())) { return false; } bool res = true; - sQ3BSPTexture *pTexture = model->m_Textures[ textureId ]; - if ( !pTexture ) { + sQ3BSPTexture *pTexture = model->m_Textures[textureId]; + if (!pTexture) { return false; } std::vector supportedExtensions; - supportedExtensions.push_back( ".jpg" ); - supportedExtensions.push_back( ".png" ); - supportedExtensions.push_back( ".tga" ); + supportedExtensions.push_back(".jpg"); + supportedExtensions.push_back(".png"); + supportedExtensions.push_back(".tga"); std::string textureName, ext; - if ( expandFile( archive, pTexture->strName, supportedExtensions, textureName, ext ) ) { - IOStream *pTextureStream = archive->Open( textureName.c_str() ); - if ( pTextureStream ) { + if (expandFile(archive, pTexture->strName, supportedExtensions, textureName, ext)) { + IOStream *pTextureStream = archive->Open(textureName.c_str()); + if (pTextureStream) { size_t texSize = pTextureStream->FileSize(); aiTexture *curTexture = new aiTexture; curTexture->mHeight = 0; @@ -605,20 +588,20 @@ bool Q3BSPFileImporter::importTextureFromArchive( const Q3BSP::Q3BSPModel *model res = true; aiString name; - name.data[ 0 ] = '*'; - name.length = 1 + ASSIMP_itoa10( name.data + 1, static_cast(MAXLEN-1), static_cast(mTextures.size()) ); + name.data[0] = '*'; + name.length = 1 + ASSIMP_itoa10(name.data + 1, static_cast(MAXLEN - 1), static_cast(mTextures.size())); - archive->Close( pTextureStream ); + archive->Close(pTextureStream); - pMatHelper->AddProperty( &name, AI_MATKEY_TEXTURE_DIFFUSE( 0 ) ); + pMatHelper->AddProperty(&name, AI_MATKEY_TEXTURE_DIFFUSE(0)); mTextures.push_back(curTexture); } else { // If it doesn't exist in the archive, it is probably just a reference to an external file. // We'll leave it up to the user to figure out which extension the file has. aiString name; - strncpy( name.data, pTexture->strName, sizeof name.data ); - name.length = static_cast(strlen( name.data )); - pMatHelper->AddProperty( &name, AI_MATKEY_TEXTURE_DIFFUSE( 0 ) ); + strncpy(name.data, pTexture->strName, sizeof name.data); + name.length = static_cast(strlen(name.data)); + pMatHelper->AddProperty(&name, AI_MATKEY_TEXTURE_DIFFUSE(0)); } } @@ -627,19 +610,18 @@ bool Q3BSPFileImporter::importTextureFromArchive( const Q3BSP::Q3BSPModel *model // ------------------------------------------------------------------------------------------------ // Imports a light map file. -bool Q3BSPFileImporter::importLightmap( const Q3BSP::Q3BSPModel *pModel, aiScene* pScene, - aiMaterial *pMatHelper, int lightmapId ) -{ - if (nullptr == pModel || nullptr == pScene || nullptr == pMatHelper ) { +bool Q3BSPFileImporter::importLightmap(const Q3BSP::Q3BSPModel *pModel, aiScene *pScene, + aiMaterial *pMatHelper, int lightmapId) { + if (nullptr == pModel || nullptr == pScene || nullptr == pMatHelper) { return false; } - if ( lightmapId < 0 || lightmapId >= static_cast( pModel->m_Lightmaps.size() ) ) { + if (lightmapId < 0 || lightmapId >= static_cast(pModel->m_Lightmaps.size())) { return false; } - sQ3BSPLightmap *pLightMap = pModel->m_Lightmaps[ lightmapId ]; - if (nullptr == pLightMap ) { + sQ3BSPLightmap *pLightMap = pModel->m_Lightmaps[lightmapId]; + if (nullptr == pLightMap) { return false; } @@ -649,21 +631,21 @@ bool Q3BSPFileImporter::importLightmap( const Q3BSP::Q3BSPModel *pModel, aiScene pTexture->mHeight = CE_BSP_LIGHTMAPHEIGHT; pTexture->pcData = new aiTexel[CE_BSP_LIGHTMAPWIDTH * CE_BSP_LIGHTMAPHEIGHT]; - ::memcpy( pTexture->pcData, pLightMap->bLMapData, pTexture->mWidth ); + ::memcpy(pTexture->pcData, pLightMap->bLMapData, pTexture->mWidth); size_t p = 0; - for ( size_t i = 0; i < CE_BSP_LIGHTMAPWIDTH * CE_BSP_LIGHTMAPHEIGHT; ++i ) { - pTexture->pcData[ i ].r = pLightMap->bLMapData[ p++ ]; - pTexture->pcData[ i ].g = pLightMap->bLMapData[ p++ ]; - pTexture->pcData[ i ].b = pLightMap->bLMapData[ p++ ]; - pTexture->pcData[ i ].a = 0xFF; + for (size_t i = 0; i < CE_BSP_LIGHTMAPWIDTH * CE_BSP_LIGHTMAPHEIGHT; ++i) { + pTexture->pcData[i].r = pLightMap->bLMapData[p++]; + pTexture->pcData[i].g = pLightMap->bLMapData[p++]; + pTexture->pcData[i].b = pLightMap->bLMapData[p++]; + pTexture->pcData[i].a = 0xFF; } aiString name; - name.data[ 0 ] = '*'; - name.length = 1 + ASSIMP_itoa10( name.data + 1, static_cast(MAXLEN-1), static_cast(mTextures.size()) ); + name.data[0] = '*'; + name.length = 1 + ASSIMP_itoa10(name.data + 1, static_cast(MAXLEN - 1), static_cast(mTextures.size())); - pMatHelper->AddProperty( &name,AI_MATKEY_TEXTURE_LIGHTMAP( 1 ) ); - mTextures.push_back( pTexture ); + pMatHelper->AddProperty(&name, AI_MATKEY_TEXTURE_LIGHTMAP(1)); + mTextures.push_back(pTexture); return true; } @@ -671,25 +653,21 @@ bool Q3BSPFileImporter::importLightmap( const Q3BSP::Q3BSPModel *pModel, aiScene // ------------------------------------------------------------------------------------------------ // Will search for a supported extension. bool Q3BSPFileImporter::expandFile(ZipArchiveIOSystem *pArchive, const std::string &rFilename, - const std::vector &rExtList, std::string &rFile, - std::string &rExt ) -{ - ai_assert( NULL != pArchive ); - ai_assert( !rFilename.empty() ); + const std::vector &rExtList, std::string &rFile, + std::string &rExt) { + ai_assert(nullptr != pArchive); + ai_assert(!rFilename.empty()); - if ( rExtList.empty() ) - { - rFile = rFilename; + if (rExtList.empty()) { + rFile = rFilename; rExt = ""; return true; } bool found = false; - for ( std::vector::const_iterator it = rExtList.begin(); it != rExtList.end(); ++it ) - { + for (std::vector::const_iterator it = rExtList.begin(); it != rExtList.end(); ++it) { const std::string textureName = rFilename + *it; - if ( pArchive->Exists( textureName.c_str() ) ) - { + if (pArchive->Exists(textureName.c_str())) { rExt = *it; rFile = textureName; found = true; diff --git a/code/AssetLib/Q3D/Q3DLoader.cpp b/code/AssetLib/Q3D/Q3DLoader.cpp index 693c49abe..717b5702e 100644 --- a/code/AssetLib/Q3D/Q3DLoader.cpp +++ b/code/AssetLib/Q3D/Q3DLoader.cpp @@ -5,8 +5,6 @@ Open Asset Import Library (assimp) Copyright (c) 2006-2020, assimp team - - All rights reserved. Redistribution and use of this software in source and binary forms, @@ -45,17 +43,16 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * @brief Implementation of the Q3D importer class */ - #ifndef ASSIMP_BUILD_NO_Q3D_IMPORTER // internal headers #include "Q3DLoader.h" #include #include -#include -#include -#include #include +#include +#include +#include using namespace Assimp; @@ -74,68 +71,66 @@ static const aiImporterDesc desc = { // ------------------------------------------------------------------------------------------------ // Constructor to be privately used by Importer -Q3DImporter::Q3DImporter() -{} +Q3DImporter::Q3DImporter() { + // empty +} // ------------------------------------------------------------------------------------------------ // Destructor, private as well -Q3DImporter::~Q3DImporter() -{} +Q3DImporter::~Q3DImporter() { + // empty +} // ------------------------------------------------------------------------------------------------ // Returns whether the class can handle the format of the given file. -bool Q3DImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const -{ +bool Q3DImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const { const std::string extension = GetExtension(pFile); if (extension == "q3s" || extension == "q3o") return true; - else if (!extension.length() || checkSig) { + else if (!extension.length() || checkSig) { if (!pIOHandler) return true; - const char* tokens[] = {"quick3Do","quick3Ds"}; - return SearchFileHeaderForToken(pIOHandler,pFile,tokens,2); + const char *tokens[] = { "quick3Do", "quick3Ds" }; + return SearchFileHeaderForToken(pIOHandler, pFile, tokens, 2); } return false; } // ------------------------------------------------------------------------------------------------ -const aiImporterDesc* Q3DImporter::GetInfo () const -{ +const aiImporterDesc *Q3DImporter::GetInfo() const { return &desc; } // ------------------------------------------------------------------------------------------------ // Imports the given file into the given scene structure. -void Q3DImporter::InternReadFile( const std::string& pFile, - aiScene* pScene, IOSystem* pIOHandler) -{ - StreamReaderLE stream(pIOHandler->Open(pFile,"rb")); +void Q3DImporter::InternReadFile(const std::string &pFile, + aiScene *pScene, IOSystem *pIOHandler) { + StreamReaderLE stream(pIOHandler->Open(pFile, "rb")); // The header is 22 bytes large if (stream.GetRemainingSize() < 22) throw DeadlyImportError("File is either empty or corrupt: " + pFile); // Check the file's signature - if (ASSIMP_strincmp( (const char*)stream.GetPtr(), "quick3Do", 8 ) && - ASSIMP_strincmp( (const char*)stream.GetPtr(), "quick3Ds", 8 )) - { + if (ASSIMP_strincmp((const char *)stream.GetPtr(), "quick3Do", 8) && + ASSIMP_strincmp((const char *)stream.GetPtr(), "quick3Ds", 8)) { throw DeadlyImportError("Not a Quick3D file. Signature string is: " + - std::string((const char*)stream.GetPtr(),8)); + std::string((const char *)stream.GetPtr(), 8)); } // Print the file format version ASSIMP_LOG_INFO_F("Quick3D File format version: ", - std::string(&((const char*)stream.GetPtr())[8],2)); + std::string(&((const char *)stream.GetPtr())[8], 2)); // ... an store it - char major = ((const char*)stream.GetPtr())[8]; - char minor = ((const char*)stream.GetPtr())[9]; + char major = ((const char *)stream.GetPtr())[8]; + char minor = ((const char *)stream.GetPtr())[9]; stream.IncPtr(10); - unsigned int numMeshes = (unsigned int)stream.GetI4(); - unsigned int numMats = (unsigned int)stream.GetI4(); - unsigned int numTextures = (unsigned int)stream.GetI4(); + unsigned int numMeshes = (unsigned int)stream.GetI4(); + unsigned int numMats = (unsigned int)stream.GetI4(); + unsigned int numTextures = (unsigned int)stream.GetI4(); std::vector materials; materials.reserve(numMats); @@ -146,124 +141,109 @@ void Q3DImporter::InternReadFile( const std::string& pFile, // Allocate the scene root node pScene->mRootNode = new aiNode(); - aiColor3D fgColor (0.6f,0.6f,0.6f); + aiColor3D fgColor(0.6f, 0.6f, 0.6f); // Now read all file chunks - while (true) - { - if (stream.GetRemainingSize() < 1)break; + while (true) { + if (stream.GetRemainingSize() < 1) break; char c = stream.GetI1(); - switch (c) - { + switch (c) { // Meshes chunk - case 'm': - { - for (unsigned int quak = 0; quak < numMeshes; ++quak) - { - meshes.push_back(Mesh()); - Mesh& mesh = meshes.back(); + case 'm': { + for (unsigned int quak = 0; quak < numMeshes; ++quak) { + meshes.push_back(Mesh()); + Mesh &mesh = meshes.back(); - // read all vertices - unsigned int numVerts = (unsigned int)stream.GetI4(); - if (!numVerts) - throw DeadlyImportError("Quick3D: Found mesh with zero vertices"); + // read all vertices + unsigned int numVerts = (unsigned int)stream.GetI4(); + if (!numVerts) + throw DeadlyImportError("Quick3D: Found mesh with zero vertices"); - std::vector& verts = mesh.verts; - verts.resize(numVerts); + std::vector &verts = mesh.verts; + verts.resize(numVerts); - for (unsigned int i = 0; i < numVerts;++i) - { - verts[i].x = stream.GetF4(); - verts[i].y = stream.GetF4(); - verts[i].z = stream.GetF4(); - } - - // read all faces - numVerts = (unsigned int)stream.GetI4(); - if (!numVerts) - throw DeadlyImportError("Quick3D: Found mesh with zero faces"); - - std::vector& faces = mesh.faces; - faces.reserve(numVerts); - - // number of indices - for (unsigned int i = 0; i < numVerts;++i) - { - faces.push_back(Face(stream.GetI2()) ); - if (faces.back().indices.empty()) - throw DeadlyImportError("Quick3D: Found face with zero indices"); - } - - // indices - for (unsigned int i = 0; i < numVerts;++i) - { - Face& vec = faces[i]; - for (unsigned int a = 0; a < (unsigned int)vec.indices.size();++a) - vec.indices[a] = stream.GetI4(); - } - - // material indices - for (unsigned int i = 0; i < numVerts;++i) - { - faces[i].mat = (unsigned int)stream.GetI4(); - } - - // read all normals - numVerts = (unsigned int)stream.GetI4(); - std::vector& normals = mesh.normals; - normals.resize(numVerts); - - for (unsigned int i = 0; i < numVerts;++i) - { - normals[i].x = stream.GetF4(); - normals[i].y = stream.GetF4(); - normals[i].z = stream.GetF4(); - } - - numVerts = (unsigned int)stream.GetI4(); - if (numTextures && numVerts) - { - // read all texture coordinates - std::vector& uv = mesh.uv; - uv.resize(numVerts); - - for (unsigned int i = 0; i < numVerts;++i) - { - uv[i].x = stream.GetF4(); - uv[i].y = stream.GetF4(); - } - - // UV indices - for (unsigned int i = 0; i < (unsigned int)faces.size();++i) - { - Face& vec = faces[i]; - for (unsigned int a = 0; a < (unsigned int)vec.indices.size();++a) - { - vec.uvindices[a] = stream.GetI4(); - if (!i && !a) - mesh.prevUVIdx = vec.uvindices[a]; - else if (vec.uvindices[a] != mesh.prevUVIdx) - mesh.prevUVIdx = UINT_MAX; - } - } - } - - // we don't need the rest, but we need to get to the next chunk - stream.IncPtr(36); - if (minor > '0' && major == '3') - stream.IncPtr(mesh.faces.size()); + for (unsigned int i = 0; i < numVerts; ++i) { + verts[i].x = stream.GetF4(); + verts[i].y = stream.GetF4(); + verts[i].z = stream.GetF4(); } - // stream.IncPtr(4); // unknown value here + + // read all faces + numVerts = (unsigned int)stream.GetI4(); + if (!numVerts) + throw DeadlyImportError("Quick3D: Found mesh with zero faces"); + + std::vector &faces = mesh.faces; + faces.reserve(numVerts); + + // number of indices + for (unsigned int i = 0; i < numVerts; ++i) { + faces.push_back(Face(stream.GetI2())); + if (faces.back().indices.empty()) + throw DeadlyImportError("Quick3D: Found face with zero indices"); + } + + // indices + for (unsigned int i = 0; i < numVerts; ++i) { + Face &vec = faces[i]; + for (unsigned int a = 0; a < (unsigned int)vec.indices.size(); ++a) + vec.indices[a] = stream.GetI4(); + } + + // material indices + for (unsigned int i = 0; i < numVerts; ++i) { + faces[i].mat = (unsigned int)stream.GetI4(); + } + + // read all normals + numVerts = (unsigned int)stream.GetI4(); + std::vector &normals = mesh.normals; + normals.resize(numVerts); + + for (unsigned int i = 0; i < numVerts; ++i) { + normals[i].x = stream.GetF4(); + normals[i].y = stream.GetF4(); + normals[i].z = stream.GetF4(); + } + + numVerts = (unsigned int)stream.GetI4(); + if (numTextures && numVerts) { + // read all texture coordinates + std::vector &uv = mesh.uv; + uv.resize(numVerts); + + for (unsigned int i = 0; i < numVerts; ++i) { + uv[i].x = stream.GetF4(); + uv[i].y = stream.GetF4(); + } + + // UV indices + for (unsigned int i = 0; i < (unsigned int)faces.size(); ++i) { + Face &vec = faces[i]; + for (unsigned int a = 0; a < (unsigned int)vec.indices.size(); ++a) { + vec.uvindices[a] = stream.GetI4(); + if (!i && !a) + mesh.prevUVIdx = vec.uvindices[a]; + else if (vec.uvindices[a] != mesh.prevUVIdx) + mesh.prevUVIdx = UINT_MAX; + } + } + } + + // we don't need the rest, but we need to get to the next chunk + stream.IncPtr(36); + if (minor > '0' && major == '3') + stream.IncPtr(mesh.faces.size()); } - break; + // stream.IncPtr(4); // unknown value here + } break; // materials chunk case 'c': - for (unsigned int i = 0; i < numMats; ++i) - { + for (unsigned int i = 0; i < numMats; ++i) { materials.push_back(Material()); - Material& mat = materials.back(); + Material &mat = materials.back(); // read the material name c = stream.GetI1(); @@ -308,17 +288,18 @@ void Q3DImporter::InternReadFile( const std::string& pFile, if (!numTextures) { break; } - pScene->mTextures = new aiTexture*[pScene->mNumTextures]; + pScene->mTextures = new aiTexture *[pScene->mNumTextures]; // to make sure we won't crash if we leave through an exception - ::memset(pScene->mTextures,0,sizeof(void*)*pScene->mNumTextures); + ::memset(pScene->mTextures, 0, sizeof(void *) * pScene->mNumTextures); for (unsigned int i = 0; i < pScene->mNumTextures; ++i) { - aiTexture* tex = pScene->mTextures[i] = new aiTexture; + aiTexture *tex = pScene->mTextures[i] = new aiTexture; // skip the texture name - while (stream.GetI1()); + while (stream.GetI1()) + ; // read texture width and height - tex->mWidth = (unsigned int)stream.GetI4(); + tex->mWidth = (unsigned int)stream.GetI4(); tex->mHeight = (unsigned int)stream.GetI4(); if (!tex->mWidth || !tex->mHeight) { @@ -326,11 +307,10 @@ void Q3DImporter::InternReadFile( const std::string& pFile, } unsigned int mul = tex->mWidth * tex->mHeight; - aiTexel* begin = tex->pcData = new aiTexel[mul]; - aiTexel* const end = & begin[mul-1] +1; + aiTexel *begin = tex->pcData = new aiTexel[mul]; + aiTexel *const end = &begin[mul - 1] + 1; - - for (;begin != end; ++begin) { + for (; begin != end; ++begin) { begin->r = stream.GetI1(); begin->g = stream.GetI1(); begin->b = stream.GetI1(); @@ -341,68 +321,66 @@ void Q3DImporter::InternReadFile( const std::string& pFile, break; // scene chunk - case 's': - { - // skip position and rotation - stream.IncPtr(12); + case 's': { + // skip position and rotation + stream.IncPtr(12); - for (unsigned int i = 0; i < 4;++i) - for (unsigned int a = 0; a < 4;++a) - pScene->mRootNode->mTransformation[i][a] = stream.GetF4(); + for (unsigned int i = 0; i < 4; ++i) + for (unsigned int a = 0; a < 4; ++a) + pScene->mRootNode->mTransformation[i][a] = stream.GetF4(); - stream.IncPtr(16); + stream.IncPtr(16); - // now setup a single camera - pScene->mNumCameras = 1; - pScene->mCameras = new aiCamera*[1]; - aiCamera* cam = pScene->mCameras[0] = new aiCamera(); - cam->mPosition.x = stream.GetF4(); - cam->mPosition.y = stream.GetF4(); - cam->mPosition.z = stream.GetF4(); - cam->mName.Set("Q3DCamera"); + // now setup a single camera + pScene->mNumCameras = 1; + pScene->mCameras = new aiCamera *[1]; + aiCamera *cam = pScene->mCameras[0] = new aiCamera(); + cam->mPosition.x = stream.GetF4(); + cam->mPosition.y = stream.GetF4(); + cam->mPosition.z = stream.GetF4(); + cam->mName.Set("Q3DCamera"); - // skip eye rotation for the moment - stream.IncPtr(12); + // skip eye rotation for the moment + stream.IncPtr(12); - // read the default material color - fgColor .r = stream.GetF4(); - fgColor .g = stream.GetF4(); - fgColor .b = stream.GetF4(); + // read the default material color + fgColor.r = stream.GetF4(); + fgColor.g = stream.GetF4(); + fgColor.b = stream.GetF4(); - // skip some unimportant properties - stream.IncPtr(29); + // skip some unimportant properties + stream.IncPtr(29); - // setup a single point light with no attenuation - pScene->mNumLights = 1; - pScene->mLights = new aiLight*[1]; - aiLight* light = pScene->mLights[0] = new aiLight(); - light->mName.Set("Q3DLight"); - light->mType = aiLightSource_POINT; + // setup a single point light with no attenuation + pScene->mNumLights = 1; + pScene->mLights = new aiLight *[1]; + aiLight *light = pScene->mLights[0] = new aiLight(); + light->mName.Set("Q3DLight"); + light->mType = aiLightSource_POINT; - light->mAttenuationConstant = 1; - light->mAttenuationLinear = 0; - light->mAttenuationQuadratic = 0; + light->mAttenuationConstant = 1; + light->mAttenuationLinear = 0; + light->mAttenuationQuadratic = 0; - light->mColorDiffuse.r = stream.GetF4(); - light->mColorDiffuse.g = stream.GetF4(); - light->mColorDiffuse.b = stream.GetF4(); + light->mColorDiffuse.r = stream.GetF4(); + light->mColorDiffuse.g = stream.GetF4(); + light->mColorDiffuse.b = stream.GetF4(); - light->mColorSpecular = light->mColorDiffuse; + light->mColorSpecular = light->mColorDiffuse; + // We don't need the rest, but we need to know where this chunk ends. + unsigned int temp = (unsigned int)(stream.GetI4() * stream.GetI4()); - // We don't need the rest, but we need to know where this chunk ends. - unsigned int temp = (unsigned int)(stream.GetI4() * stream.GetI4()); + // skip the background file name + while (stream.GetI1()) + ; - // skip the background file name - while (stream.GetI1()); + // skip background texture data + the remaining fields + stream.IncPtr(temp * 3 + 20); // 4 bytes of unknown data here - // skip background texture data + the remaining fields - stream.IncPtr(temp*3 + 20); // 4 bytes of unknown data here - - // TODO - goto outer; - } - break; + // TODO + goto outer; + } break; default: throw DeadlyImportError("Quick3D: Unknown chunk"); @@ -416,55 +394,50 @@ outer: throw DeadlyImportError("Quick3D: No meshes loaded"); // If we have no materials loaded - generate a default mat - if (materials.empty()) - { + if (materials.empty()) { ASSIMP_LOG_INFO("Quick3D: No material found, generating one"); materials.push_back(Material()); - materials.back().diffuse = fgColor ; + materials.back().diffuse = fgColor; } // find out which materials we'll need typedef std::pair FaceIdx; - typedef std::vector< FaceIdx > FaceIdxArray; - FaceIdxArray* fidx = new FaceIdxArray[materials.size()]; + typedef std::vector FaceIdxArray; + FaceIdxArray *fidx = new FaceIdxArray[materials.size()]; unsigned int p = 0; for (std::vector::iterator it = meshes.begin(), end = meshes.end(); - it != end; ++it,++p) - { + it != end; ++it, ++p) { unsigned int q = 0; for (std::vector::iterator fit = (*it).faces.begin(), fend = (*it).faces.end(); - fit != fend; ++fit,++q) - { - if ((*fit).mat >= materials.size()) - { + fit != fend; ++fit, ++q) { + if ((*fit).mat >= materials.size()) { ASSIMP_LOG_WARN("Quick3D: Material index overflow"); (*fit).mat = 0; } - if (fidx[(*fit).mat].empty())++pScene->mNumMeshes; - fidx[(*fit).mat].push_back( FaceIdx(p,q) ); + if (fidx[(*fit).mat].empty()) ++pScene->mNumMeshes; + fidx[(*fit).mat].push_back(FaceIdx(p, q)); } } pScene->mNumMaterials = pScene->mNumMeshes; - pScene->mMaterials = new aiMaterial*[pScene->mNumMaterials]; - pScene->mMeshes = new aiMesh*[pScene->mNumMaterials]; + pScene->mMaterials = new aiMaterial *[pScene->mNumMaterials]; + pScene->mMeshes = new aiMesh *[pScene->mNumMaterials]; - for (unsigned int i = 0, real = 0; i < (unsigned int)materials.size(); ++i) - { - if (fidx[i].empty())continue; + for (unsigned int i = 0, real = 0; i < (unsigned int)materials.size(); ++i) { + if (fidx[i].empty()) continue; // Allocate a mesh and a material - aiMesh* mesh = pScene->mMeshes[real] = new aiMesh(); - aiMaterial* mat = new aiMaterial(); + aiMesh *mesh = pScene->mMeshes[real] = new aiMesh(); + aiMaterial *mat = new aiMaterial(); pScene->mMaterials[real] = mat; mesh->mMaterialIndex = real; // Build the output material - Material& srcMat = materials[i]; - mat->AddProperty(&srcMat.diffuse, 1,AI_MATKEY_COLOR_DIFFUSE); - mat->AddProperty(&srcMat.specular, 1,AI_MATKEY_COLOR_SPECULAR); - mat->AddProperty(&srcMat.ambient, 1,AI_MATKEY_COLOR_AMBIENT); + Material &srcMat = materials[i]; + mat->AddProperty(&srcMat.diffuse, 1, AI_MATKEY_COLOR_DIFFUSE); + mat->AddProperty(&srcMat.specular, 1, AI_MATKEY_COLOR_SPECULAR); + mat->AddProperty(&srcMat.ambient, 1, AI_MATKEY_COLOR_AMBIENT); // NOTE: Ignore transparency for the moment - it seems // unclear how to interpret the data @@ -482,57 +455,48 @@ outer: mat->AddProperty(&m, 1, AI_MATKEY_SHADING_MODEL); if (srcMat.name.length) - mat->AddProperty(&srcMat.name,AI_MATKEY_NAME); + mat->AddProperty(&srcMat.name, AI_MATKEY_NAME); // Add a texture - if (srcMat.texIdx < pScene->mNumTextures || real < pScene->mNumTextures) - { + if (srcMat.texIdx < pScene->mNumTextures || real < pScene->mNumTextures) { srcMat.name.data[0] = '*'; - srcMat.name.length = ASSIMP_itoa10(&srcMat.name.data[1],1000, - (srcMat.texIdx < pScene->mNumTextures ? srcMat.texIdx : real)); - mat->AddProperty(&srcMat.name,AI_MATKEY_TEXTURE_DIFFUSE(0)); + srcMat.name.length = ASSIMP_itoa10(&srcMat.name.data[1], 1000, + (srcMat.texIdx < pScene->mNumTextures ? srcMat.texIdx : real)); + mat->AddProperty(&srcMat.name, AI_MATKEY_TEXTURE_DIFFUSE(0)); } mesh->mNumFaces = (unsigned int)fidx[i].size(); - aiFace* faces = mesh->mFaces = new aiFace[mesh->mNumFaces]; + aiFace *faces = mesh->mFaces = new aiFace[mesh->mNumFaces]; // Now build the output mesh. First find out how many // vertices we'll need - for (FaceIdxArray::const_iterator it = fidx[i].begin(),end = fidx[i].end(); - it != end; ++it) - { - mesh->mNumVertices += (unsigned int)meshes[(*it).first].faces[ - (*it).second].indices.size(); + for (FaceIdxArray::const_iterator it = fidx[i].begin(), end = fidx[i].end(); + it != end; ++it) { + mesh->mNumVertices += (unsigned int)meshes[(*it).first].faces[(*it).second].indices.size(); } - aiVector3D* verts = mesh->mVertices = new aiVector3D[mesh->mNumVertices]; - aiVector3D* norms = mesh->mNormals = new aiVector3D[mesh->mNumVertices]; - aiVector3D* uv; - if (real < pScene->mNumTextures) - { - uv = mesh->mTextureCoords[0] = new aiVector3D[mesh->mNumVertices]; - mesh->mNumUVComponents[0] = 2; + aiVector3D *verts = mesh->mVertices = new aiVector3D[mesh->mNumVertices]; + aiVector3D *norms = mesh->mNormals = new aiVector3D[mesh->mNumVertices]; + aiVector3D *uv = nullptr; + if (real < pScene->mNumTextures) { + uv = mesh->mTextureCoords[0] = new aiVector3D[mesh->mNumVertices]; + mesh->mNumUVComponents[0] = 2; } - else uv = NULL; // Build the final array unsigned int cnt = 0; - for (FaceIdxArray::const_iterator it = fidx[i].begin(),end = fidx[i].end(); - it != end; ++it, ++faces) - { - Mesh& curMesh = meshes[(*it).first]; + for (FaceIdxArray::const_iterator it = fidx[i].begin(), end = fidx[i].end(); + it != end; ++it, ++faces) { + Mesh &curMesh = meshes[(*it).first]; Face &face = curMesh.faces[(*it).second]; faces->mNumIndices = (unsigned int)face.indices.size(); - faces->mIndices = new unsigned int [faces->mNumIndices]; - + faces->mIndices = new unsigned int[faces->mNumIndices]; aiVector3D faceNormal; bool fnOK = false; - for (unsigned int n = 0; n < faces->mNumIndices;++n, ++cnt, ++norms, ++verts) - { - if (face.indices[n] >= curMesh.verts.size()) - { + for (unsigned int n = 0; n < faces->mNumIndices; ++n, ++cnt, ++norms, ++verts) { + if (face.indices[n] >= curMesh.verts.size()) { ASSIMP_LOG_WARN("Quick3D: Vertex index overflow"); face.indices[n] = 0; } @@ -540,11 +504,9 @@ outer: // copy vertices *verts = curMesh.verts[face.indices[n]]; - if (face.indices[n] >= curMesh.normals.size() && faces->mNumIndices >= 3) - { + if (face.indices[n] >= curMesh.normals.size() && faces->mNumIndices >= 3) { // we have no normal here - assign the face normal - if (!fnOK) - { + if (!fnOK) { const aiVector3D &pV1 = curMesh.verts[face.indices[0]]; const aiVector3D &pV2 = curMesh.verts[face.indices[1]]; const aiVector3D &pV3 = curMesh.verts[face.indices.size() - 1]; @@ -557,16 +519,12 @@ outer: } // copy texture coordinates - if (uv && curMesh.uv.size()) - { + if (uv && curMesh.uv.size()) { if (curMesh.prevUVIdx != 0xffffffff && curMesh.uv.size() >= curMesh.verts.size()) // workaround { *uv = curMesh.uv[face.indices[n]]; - } - else - { - if (face.uvindices[n] >= curMesh.uv.size()) - { + } else { + if (face.uvindices[n] >= curMesh.uv.size()) { ASSIMP_LOG_WARN("Quick3D: Texture coordinate index overflow"); face.uvindices[n] = 0; } @@ -579,7 +537,6 @@ outer: // setup the new vertex index faces->mIndices[n] = cnt; } - } ++real; } @@ -589,8 +546,8 @@ outer: // Now we need to attach the meshes to the root node of the scene pScene->mRootNode->mNumMeshes = pScene->mNumMeshes; - pScene->mRootNode->mMeshes = new unsigned int [pScene->mNumMeshes]; - for (unsigned int i = 0; i < pScene->mNumMeshes;++i) + pScene->mRootNode->mMeshes = new unsigned int[pScene->mNumMeshes]; + for (unsigned int i = 0; i < pScene->mNumMeshes; ++i) pScene->mRootNode->mMeshes[i] = i; /*pScene->mRootNode->mTransformation *= aiMatrix4x4( @@ -600,13 +557,12 @@ outer: 0.f, 0.f, 0.f, 1.f);*/ // Add cameras and light sources to the scene root node - pScene->mRootNode->mNumChildren = pScene->mNumLights+pScene->mNumCameras; - if (pScene->mRootNode->mNumChildren) - { - pScene->mRootNode->mChildren = new aiNode* [ pScene->mRootNode->mNumChildren ]; + pScene->mRootNode->mNumChildren = pScene->mNumLights + pScene->mNumCameras; + if (pScene->mRootNode->mNumChildren) { + pScene->mRootNode->mChildren = new aiNode *[pScene->mRootNode->mNumChildren]; // the light source - aiNode* nd = pScene->mRootNode->mChildren[0] = new aiNode(); + aiNode *nd = pScene->mRootNode->mChildren[0] = new aiNode(); nd->mParent = pScene->mRootNode; nd->mName.Set("Q3DLight"); nd->mTransformation = pScene->mRootNode->mTransformation; diff --git a/code/AssetLib/Raw/RawLoader.cpp b/code/AssetLib/Raw/RawLoader.cpp index 092323cc0..1363e29c1 100644 --- a/code/AssetLib/Raw/RawLoader.cpp +++ b/code/AssetLib/Raw/RawLoader.cpp @@ -5,8 +5,6 @@ Open Asset Import Library (assimp) Copyright (c) 2006-2020, assimp team - - All rights reserved. Redistribution and use of this software in source and binary forms, @@ -45,18 +43,17 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * @brief Implementation of the RAW importer class */ - #ifndef ASSIMP_BUILD_NO_RAW_IMPORTER // internal headers #include "RawLoader.h" #include #include -#include -#include -#include -#include #include +#include +#include +#include +#include using namespace Assimp; @@ -75,146 +72,129 @@ static const aiImporterDesc desc = { // ------------------------------------------------------------------------------------------------ // Constructor to be privately used by Importer -RAWImporter::RAWImporter() -{} - -// ------------------------------------------------------------------------------------------------ -// Destructor, private as well -RAWImporter::~RAWImporter() -{} - -// ------------------------------------------------------------------------------------------------ -// Returns whether the class can handle the format of the given file. -bool RAWImporter::CanRead( const std::string& pFile, IOSystem* /*pIOHandler*/, bool /*checkSig*/) const -{ - return SimpleExtensionCheck(pFile,"raw"); +RAWImporter::RAWImporter() { + // empty } // ------------------------------------------------------------------------------------------------ -const aiImporterDesc* RAWImporter::GetInfo () const -{ +// Destructor, private as well +RAWImporter::~RAWImporter() { + // empty +} + +// ------------------------------------------------------------------------------------------------ +// Returns whether the class can handle the format of the given file. +bool RAWImporter::CanRead(const std::string &pFile, IOSystem * /*pIOHandler*/, bool /*checkSig*/) const { + return SimpleExtensionCheck(pFile, "raw"); +} + +// ------------------------------------------------------------------------------------------------ +const aiImporterDesc *RAWImporter::GetInfo() const { return &desc; } // ------------------------------------------------------------------------------------------------ // Imports the given file into the given scene structure. -void RAWImporter::InternReadFile( const std::string& pFile, - aiScene* pScene, IOSystem* pIOHandler) -{ - std::unique_ptr file( pIOHandler->Open( pFile, "rb")); +void RAWImporter::InternReadFile(const std::string &pFile, + aiScene *pScene, IOSystem *pIOHandler) { + std::unique_ptr file(pIOHandler->Open(pFile, "rb")); // Check whether we can read from the file - if( file.get() == NULL) { - throw DeadlyImportError( "Failed to open RAW file " + pFile + "."); + if (file.get() == nullptr) { + throw DeadlyImportError("Failed to open RAW file " + pFile + "."); } // allocate storage and copy the contents of the file to a memory buffer // (terminate it with zero) std::vector mBuffer2; - TextFileToBuffer(file.get(),mBuffer2); - const char* buffer = &mBuffer2[0]; + TextFileToBuffer(file.get(), mBuffer2); + const char *buffer = &mBuffer2[0]; // list of groups loaded from the file - std::vector< GroupInformation > outGroups(1,GroupInformation("")); - std::vector< GroupInformation >::iterator curGroup = outGroups.begin(); + std::vector outGroups(1, GroupInformation("")); + std::vector::iterator curGroup = outGroups.begin(); // now read all lines char line[4096]; - while (GetNextLine(buffer,line)) - { + while (GetNextLine(buffer, line)) { // if the line starts with a non-numeric identifier, it marks // the beginning of a new group - const char* sz = line;SkipSpaces(&sz); - if (IsLineEnd(*sz))continue; - if (!IsNumeric(*sz)) - { - const char* sz2 = sz; - while (!IsSpaceOrNewLine(*sz2))++sz2; - const unsigned int length = (unsigned int)(sz2-sz); + const char *sz = line; + SkipSpaces(&sz); + if (IsLineEnd(*sz)) continue; + if (!IsNumeric(*sz)) { + const char *sz2 = sz; + while (!IsSpaceOrNewLine(*sz2)) + ++sz2; + const unsigned int length = (unsigned int)(sz2 - sz); // find an existing group with this name - for (std::vector< GroupInformation >::iterator it = outGroups.begin(), end = outGroups.end(); - it != end;++it) - { - if (length == (*it).name.length() && !::strcmp(sz,(*it).name.c_str())) - { - curGroup = it;sz2 = NULL; + for (std::vector::iterator it = outGroups.begin(), end = outGroups.end(); + it != end; ++it) { + if (length == (*it).name.length() && !::strcmp(sz, (*it).name.c_str())) { + curGroup = it; + sz2 = nullptr; break; } } - if (sz2) - { - outGroups.push_back(GroupInformation(std::string(sz,length))); - curGroup = outGroups.end()-1; + if (sz2) { + outGroups.push_back(GroupInformation(std::string(sz, length))); + curGroup = outGroups.end() - 1; } - } - else - { + } else { // there can be maximally 12 floats plus an extra texture file name float data[12]; unsigned int num; - for (num = 0; num < 12;++num) - { - if(!SkipSpaces(&sz) || !IsNumeric(*sz))break; - sz = fast_atoreal_move(sz,data[num]); + for (num = 0; num < 12; ++num) { + if (!SkipSpaces(&sz) || !IsNumeric(*sz)) break; + sz = fast_atoreal_move(sz, data[num]); } - if (num != 12 && num != 9) - { + if (num != 12 && num != 9) { ASSIMP_LOG_ERROR("A line may have either 9 or 12 floats and an optional texture"); continue; } - MeshInformation* output = NULL; + MeshInformation *output = nullptr; - const char* sz2 = sz; + const char *sz2 = sz; unsigned int length; - if (!IsLineEnd(*sz)) - { - while (!IsSpaceOrNewLine(*sz2))++sz2; - length = (unsigned int)(sz2-sz); - } - else if (9 == num) - { + if (!IsLineEnd(*sz)) { + while (!IsSpaceOrNewLine(*sz2)) + ++sz2; + length = (unsigned int)(sz2 - sz); + } else if (9 == num) { sz = "%default%"; length = 9; - } - else - { + } else { sz = ""; length = 0; } // search in the list of meshes whether we have one with this texture - for (auto &mesh : (*curGroup).meshes) - { - if (length == mesh.name.length() && (length ? !::strcmp(sz, mesh.name.c_str()) : true)) - { + for (auto &mesh : (*curGroup).meshes) { + if (length == mesh.name.length() && (length ? !::strcmp(sz, mesh.name.c_str()) : true)) { output = &mesh; break; } } // if we don't have the mesh, create it - if (!output) - { - (*curGroup).meshes.push_back(MeshInformation(std::string(sz,length))); + if (!output) { + (*curGroup).meshes.push_back(MeshInformation(std::string(sz, length))); output = &((*curGroup).meshes.back()); } - if (12 == num) - { - aiColor4D v(data[0],data[1],data[2],1.0f); + if (12 == num) { + aiColor4D v(data[0], data[1], data[2], 1.0f); output->colors.push_back(v); output->colors.push_back(v); output->colors.push_back(v); - output->vertices.push_back(aiVector3D(data[3],data[4],data[5])); - output->vertices.push_back(aiVector3D(data[6],data[7],data[8])); - output->vertices.push_back(aiVector3D(data[9],data[10],data[11])); - } - else - { - output->vertices.push_back(aiVector3D(data[0],data[1],data[2])); - output->vertices.push_back(aiVector3D(data[3],data[4],data[5])); - output->vertices.push_back(aiVector3D(data[6],data[7],data[8])); + output->vertices.push_back(aiVector3D(data[3], data[4], data[5])); + output->vertices.push_back(aiVector3D(data[6], data[7], data[8])); + output->vertices.push_back(aiVector3D(data[9], data[10], data[11])); + } else { + output->vertices.push_back(aiVector3D(data[0], data[1], data[2])); + output->vertices.push_back(aiVector3D(data[3], data[4], data[5])); + output->vertices.push_back(aiVector3D(data[6], data[7], data[8])); } } } @@ -224,105 +204,96 @@ void RAWImporter::InternReadFile( const std::string& pFile, // count the number of valid groups // (meshes can't be empty) - for (auto & outGroup : outGroups) - { - if (!outGroup.meshes.empty()) - { + for (auto &outGroup : outGroups) { + if (!outGroup.meshes.empty()) { ++pScene->mRootNode->mNumChildren; - pScene->mNumMeshes += (unsigned int) outGroup.meshes.size(); + pScene->mNumMeshes += (unsigned int)outGroup.meshes.size(); } } - if (!pScene->mNumMeshes) - { + if (!pScene->mNumMeshes) { throw DeadlyImportError("RAW: No meshes loaded. The file seems to be corrupt or empty."); } - pScene->mMeshes = new aiMesh*[pScene->mNumMeshes]; - aiNode** cc; - if (1 == pScene->mRootNode->mNumChildren) - { + pScene->mMeshes = new aiMesh *[pScene->mNumMeshes]; + aiNode **cc; + if (1 == pScene->mRootNode->mNumChildren) { cc = &pScene->mRootNode; pScene->mRootNode->mNumChildren = 0; } else { - cc = new aiNode*[pScene->mRootNode->mNumChildren]; - memset(cc, 0, sizeof(aiNode*) * pScene->mRootNode->mNumChildren); + cc = new aiNode *[pScene->mRootNode->mNumChildren]; + memset(cc, 0, sizeof(aiNode *) * pScene->mRootNode->mNumChildren); pScene->mRootNode->mChildren = cc; } pScene->mNumMaterials = pScene->mNumMeshes; - aiMaterial** mats = pScene->mMaterials = new aiMaterial*[pScene->mNumMaterials]; + aiMaterial **mats = pScene->mMaterials = new aiMaterial *[pScene->mNumMaterials]; unsigned int meshIdx = 0; - for (auto & outGroup : outGroups) - { - if (outGroup.meshes.empty())continue; + for (auto &outGroup : outGroups) { + if (outGroup.meshes.empty()) continue; - aiNode* node; - if (pScene->mRootNode->mNumChildren) - { + aiNode *node; + if (pScene->mRootNode->mNumChildren) { node = *cc = new aiNode(); node->mParent = pScene->mRootNode; - } - else node = *cc; + } else + node = *cc; node->mName.Set(outGroup.name); // add all meshes - node->mNumMeshes = (unsigned int) outGroup.meshes.size(); - unsigned int* pi = node->mMeshes = new unsigned int[ node->mNumMeshes ]; - for (std::vector< MeshInformation >::iterator it2 = outGroup.meshes.begin(), - end2 = outGroup.meshes.end(); it2 != end2; ++it2) - { + node->mNumMeshes = (unsigned int)outGroup.meshes.size(); + unsigned int *pi = node->mMeshes = new unsigned int[node->mNumMeshes]; + for (std::vector::iterator it2 = outGroup.meshes.begin(), + end2 = outGroup.meshes.end(); + it2 != end2; ++it2) { ai_assert(!(*it2).vertices.empty()); // allocate the mesh *pi++ = meshIdx; - aiMesh* mesh = pScene->mMeshes[meshIdx] = new aiMesh(); + aiMesh *mesh = pScene->mMeshes[meshIdx] = new aiMesh(); mesh->mMaterialIndex = meshIdx++; mesh->mPrimitiveTypes = aiPrimitiveType_TRIANGLE; // allocate storage for the vertex components and copy them mesh->mNumVertices = (unsigned int)(*it2).vertices.size(); - mesh->mVertices = new aiVector3D[ mesh->mNumVertices ]; - ::memcpy(mesh->mVertices,&(*it2).vertices[0],sizeof(aiVector3D)*mesh->mNumVertices); + mesh->mVertices = new aiVector3D[mesh->mNumVertices]; + ::memcpy(mesh->mVertices, &(*it2).vertices[0], sizeof(aiVector3D) * mesh->mNumVertices); - if ((*it2).colors.size()) - { + if ((*it2).colors.size()) { ai_assert((*it2).colors.size() == mesh->mNumVertices); - mesh->mColors[0] = new aiColor4D[ mesh->mNumVertices ]; - ::memcpy(mesh->mColors[0],&(*it2).colors[0],sizeof(aiColor4D)*mesh->mNumVertices); + mesh->mColors[0] = new aiColor4D[mesh->mNumVertices]; + ::memcpy(mesh->mColors[0], &(*it2).colors[0], sizeof(aiColor4D) * mesh->mNumVertices); } // generate triangles ai_assert(0 == mesh->mNumVertices % 3); - aiFace* fc = mesh->mFaces = new aiFace[ mesh->mNumFaces = mesh->mNumVertices/3 ]; - aiFace* const fcEnd = fc + mesh->mNumFaces; + aiFace *fc = mesh->mFaces = new aiFace[mesh->mNumFaces = mesh->mNumVertices / 3]; + aiFace *const fcEnd = fc + mesh->mNumFaces; unsigned int n = 0; - while (fc != fcEnd) - { - aiFace& f = *fc++; + while (fc != fcEnd) { + aiFace &f = *fc++; f.mIndices = new unsigned int[f.mNumIndices = 3]; - for (unsigned int m = 0; m < 3;++m) + for (unsigned int m = 0; m < 3; ++m) f.mIndices[m] = n++; } // generate a material for the mesh - aiMaterial* mat = new aiMaterial(); + aiMaterial *mat = new aiMaterial(); - aiColor4D clr(1.0f,1.0f,1.0f,1.0f); + aiColor4D clr(1.0f, 1.0f, 1.0f, 1.0f); if ("%default%" == (*it2).name) // a gray default material { clr.r = clr.g = clr.b = 0.6f; - } - else if ((*it2).name.length() > 0) // a texture + } else if ((*it2).name.length() > 0) // a texture { aiString s; s.Set((*it2).name); - mat->AddProperty(&s,AI_MATKEY_TEXTURE_DIFFUSE(0)); + mat->AddProperty(&s, AI_MATKEY_TEXTURE_DIFFUSE(0)); } - mat->AddProperty(&clr,1,AI_MATKEY_COLOR_DIFFUSE); + mat->AddProperty(&clr, 1, AI_MATKEY_COLOR_DIFFUSE); *mats++ = mat; } } diff --git a/code/AssetLib/SIB/SIBImporter.cpp b/code/AssetLib/SIB/SIBImporter.cpp index ac5646412..b36c6d9b1 100644 --- a/code/AssetLib/SIB/SIBImporter.cpp +++ b/code/AssetLib/SIB/SIBImporter.cpp @@ -51,7 +51,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * Nevertheless, this implementation is reasonably complete. */ - #ifndef ASSIMP_BUILD_NO_SIB_IMPORTER // internal headers @@ -60,15 +59,15 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #ifdef ASSIMP_USE_HUNTER -# include +#include #else //# include "../contrib/ConvertUTF/ConvertUTF.h" -# include "../contrib/utf8cpp/source/utf8.h" +#include "../contrib/utf8cpp/source/utf8.h" #endif -#include -#include -#include #include +#include +#include +#include #include @@ -86,14 +85,14 @@ static const aiImporterDesc desc = { }; struct SIBChunk { - uint32_t Tag; - uint32_t Size; + uint32_t Tag; + uint32_t Size; } PACK_STRUCT; -enum { - POS, - NRM, - UV, +enum { + POS, + NRM, + UV, N }; @@ -122,14 +121,14 @@ struct SIBObject { }; struct SIB { - std::vector mtls; - std::vector meshes; - std::vector lights; + std::vector mtls; + std::vector meshes; + std::vector lights; std::vector objs, insts; }; // ------------------------------------------------------------------------------------------------ -static SIBEdge& GetEdge(SIBMesh* mesh, uint32_t posA, uint32_t posB) { +static SIBEdge &GetEdge(SIBMesh *mesh, uint32_t posA, uint32_t posB) { SIBPair pair = (posA < posB) ? SIBPair(posA, posB) : SIBPair(posB, posA); std::map::iterator it = mesh->edgeMap.find(pair); if (it != mesh->edgeMap.end()) @@ -146,10 +145,9 @@ static SIBEdge& GetEdge(SIBMesh* mesh, uint32_t posA, uint32_t posB) { // ------------------------------------------------------------------------------------------------ // Helpers for reading chunked data. -#define TAG(A,B,C,D) ((A << 24) | (B << 16) | (C << 8) | D) +#define TAG(A, B, C, D) ((A << 24) | (B << 16) | (C << 8) | D) -static SIBChunk ReadChunk(StreamReaderLE* stream) -{ +static SIBChunk ReadChunk(StreamReaderLE *stream) { SIBChunk chunk; chunk.Tag = stream->GetU4(); chunk.Size = stream->GetU4(); @@ -159,8 +157,7 @@ static SIBChunk ReadChunk(StreamReaderLE* stream) return chunk; } -static aiColor3D ReadColor(StreamReaderLE* stream) -{ +static aiColor3D ReadColor(StreamReaderLE *stream) { float r = stream->GetF4(); float g = stream->GetF4(); float b = stream->GetF4(); @@ -168,37 +165,36 @@ static aiColor3D ReadColor(StreamReaderLE* stream) return aiColor3D(r, g, b); } -static void UnknownChunk(StreamReaderLE* /*stream*/, const SIBChunk& chunk) -{ +static void UnknownChunk(StreamReaderLE * /*stream*/, const SIBChunk &chunk) { char temp[5] = { - static_cast(( chunk.Tag>>24 ) & 0xff), - static_cast(( chunk.Tag>>16 ) & 0xff), - static_cast(( chunk.Tag>>8 ) & 0xff), + static_cast((chunk.Tag >> 24) & 0xff), + static_cast((chunk.Tag >> 16) & 0xff), + static_cast((chunk.Tag >> 8) & 0xff), static_cast(chunk.Tag & 0xff), '\0' }; - ASSIMP_LOG_WARN((Formatter::format(), "SIB: Skipping unknown '",temp,"' chunk.")); + ASSIMP_LOG_WARN((Formatter::format(), "SIB: Skipping unknown '", temp, "' chunk.")); } // Reads a UTF-16LE string and returns it at UTF-8. static aiString ReadString(StreamReaderLE *stream, uint32_t numWChars) { - if ( nullptr == stream || 0 == numWChars ) { + if (nullptr == stream || 0 == numWChars) { static const aiString empty; return empty; } // Allocate buffers (max expansion is 1 byte -> 4 bytes for UTF-8) std::vector str; - str.reserve( numWChars * 4 + 1 ); - uint16_t *temp = new uint16_t[ numWChars ]; - for ( uint32_t n = 0; n < numWChars; ++n ) { - temp[ n ] = stream->GetU2(); + str.reserve(numWChars * 4 + 1); + uint16_t *temp = new uint16_t[numWChars]; + for (uint32_t n = 0; n < numWChars; ++n) { + temp[n] = stream->GetU2(); } // Convert it and NUL-terminate. - const uint16_t *start( temp ), *end( temp + numWChars ); - utf8::utf16to8( start, end, back_inserter( str ) ); - str[ str.size() - 1 ] = '\0'; + const uint16_t *start(temp), *end(temp + numWChars); + utf8::utf16to8(start, end, back_inserter(str)); + str[str.size() - 1] = '\0'; // Return the final string. aiString result = aiString((const char *)&str[0]); @@ -221,52 +217,49 @@ SIBImporter::~SIBImporter() { // ------------------------------------------------------------------------------------------------ // Returns whether the class can handle the format of the given file. -bool SIBImporter::CanRead( const std::string& pFile, IOSystem* /*pIOHandler*/, bool /*checkSig*/) const { +bool SIBImporter::CanRead(const std::string &pFile, IOSystem * /*pIOHandler*/, bool /*checkSig*/) const { return SimpleExtensionCheck(pFile, "sib"); } // ------------------------------------------------------------------------------------------------ -const aiImporterDesc* SIBImporter::GetInfo () const { +const aiImporterDesc *SIBImporter::GetInfo() const { return &desc; } // ------------------------------------------------------------------------------------------------ -static void ReadVerts(SIBMesh* mesh, StreamReaderLE* stream, uint32_t count) { - if ( nullptr == mesh || nullptr == stream ) { +static void ReadVerts(SIBMesh *mesh, StreamReaderLE *stream, uint32_t count) { + if (nullptr == mesh || nullptr == stream) { return; } mesh->pos.resize(count); - for ( uint32_t n=0; npos[ n ].x = stream->GetF4(); - mesh->pos[ n ].y = stream->GetF4(); - mesh->pos[ n ].z = stream->GetF4(); + for (uint32_t n = 0; n < count; ++n) { + mesh->pos[n].x = stream->GetF4(); + mesh->pos[n].y = stream->GetF4(); + mesh->pos[n].z = stream->GetF4(); } } // ------------------------------------------------------------------------------------------------ -static void ReadFaces(SIBMesh* mesh, StreamReaderLE* stream) -{ +static void ReadFaces(SIBMesh *mesh, StreamReaderLE *stream) { uint32_t ptIdx = 0; - while (stream->GetRemainingSizeToLimit() > 0) - { + while (stream->GetRemainingSizeToLimit() > 0) { uint32_t numPoints = stream->GetU4(); // Store room for the N index channels, plus the point count. size_t pos = mesh->idx.size() + 1; - mesh->idx.resize(pos + numPoints*N); - mesh->idx[pos-1] = numPoints; + mesh->idx.resize(pos + numPoints * N); + mesh->idx[pos - 1] = numPoints; uint32_t *idx = &mesh->idx[pos]; - mesh->faceStart.push_back(static_cast(pos-1)); + mesh->faceStart.push_back(static_cast(pos - 1)); mesh->mtls.push_back(0); // Read all the position data. // UV/normals will be supplied later. // Positions are supplied indexed already, so we preserve that // mapping. UVs are supplied uniquely, so we allocate unique indices. - for (uint32_t n=0;nGetU4(); if (p >= mesh->pos.size()) throw DeadlyImportError("Vertex index is out of range."); @@ -277,17 +270,15 @@ static void ReadFaces(SIBMesh* mesh, StreamReaderLE* stream) } // Allocate data channels for normals/UVs. - mesh->nrm.resize(ptIdx, aiVector3D(0,0,0)); - mesh->uv.resize(ptIdx, aiVector3D(0,0,0)); + mesh->nrm.resize(ptIdx, aiVector3D(0, 0, 0)); + mesh->uv.resize(ptIdx, aiVector3D(0, 0, 0)); mesh->numPts = ptIdx; } // ------------------------------------------------------------------------------------------------ -static void ReadUVs(SIBMesh* mesh, StreamReaderLE* stream) -{ - while (stream->GetRemainingSizeToLimit() > 0) - { +static void ReadUVs(SIBMesh *mesh, StreamReaderLE *stream) { + while (stream->GetRemainingSizeToLimit() > 0) { uint32_t faceIdx = stream->GetU4(); uint32_t numPoints = stream->GetU4(); @@ -297,8 +288,7 @@ static void ReadUVs(SIBMesh* mesh, StreamReaderLE* stream) uint32_t pos = mesh->faceStart[faceIdx]; uint32_t *idx = &mesh->idx[pos + 1]; - for (uint32_t n=0;nuv[id].x = stream->GetF4(); mesh->uv[id].y = stream->GetF4(); @@ -307,19 +297,16 @@ static void ReadUVs(SIBMesh* mesh, StreamReaderLE* stream) } // ------------------------------------------------------------------------------------------------ -static void ReadMtls(SIBMesh* mesh, StreamReaderLE* stream) -{ +static void ReadMtls(SIBMesh *mesh, StreamReaderLE *stream) { // Material assignments are stored run-length encoded. // Also, we add 1 to each material so that we can use mtl #0 // as the default material. uint32_t prevFace = stream->GetU4(); uint32_t prevMtl = stream->GetU4() + 1; - while (stream->GetRemainingSizeToLimit() > 0) - { + while (stream->GetRemainingSizeToLimit() > 0) { uint32_t face = stream->GetU4(); uint32_t mtl = stream->GetU4() + 1; - while (prevFace < face) - { + while (prevFace < face) { if (prevFace >= mesh->mtls.size()) throw DeadlyImportError("Invalid face index."); mesh->mtls[prevFace++] = prevMtl; @@ -334,8 +321,7 @@ static void ReadMtls(SIBMesh* mesh, StreamReaderLE* stream) } // ------------------------------------------------------------------------------------------------ -static void ReadAxis(aiMatrix4x4& axis, StreamReaderLE* stream) -{ +static void ReadAxis(aiMatrix4x4 &axis, StreamReaderLE *stream) { axis.a4 = stream->GetF4(); axis.b4 = stream->GetF4(); axis.c4 = stream->GetF4(); @@ -355,10 +341,8 @@ static void ReadAxis(aiMatrix4x4& axis, StreamReaderLE* stream) } // ------------------------------------------------------------------------------------------------ -static void ReadEdges(SIBMesh* mesh, StreamReaderLE* stream) -{ - while (stream->GetRemainingSizeToLimit() > 0) - { +static void ReadEdges(SIBMesh *mesh, StreamReaderLE *stream) { + while (stream->GetRemainingSizeToLimit() > 0) { uint32_t posA = stream->GetU4(); uint32_t posB = stream->GetU4(); GetEdge(mesh, posA, posB); @@ -366,10 +350,8 @@ static void ReadEdges(SIBMesh* mesh, StreamReaderLE* stream) } // ------------------------------------------------------------------------------------------------ -static void ReadCreases(SIBMesh* mesh, StreamReaderLE* stream) -{ - while (stream->GetRemainingSizeToLimit() > 0) - { +static void ReadCreases(SIBMesh *mesh, StreamReaderLE *stream) { + while (stream->GetRemainingSizeToLimit() > 0) { uint32_t edge = stream->GetU4(); if (edge >= mesh->edges.size()) throw DeadlyImportError("SIB: Invalid edge index."); @@ -378,22 +360,19 @@ static void ReadCreases(SIBMesh* mesh, StreamReaderLE* stream) } // ------------------------------------------------------------------------------------------------ -static void ConnectFaces(SIBMesh* mesh) -{ +static void ConnectFaces(SIBMesh *mesh) { // Find faces connected to each edge. size_t numFaces = mesh->faceStart.size(); - for (size_t faceIdx=0;faceIdxidx[mesh->faceStart[faceIdx]]; uint32_t numPoints = *idx++; - uint32_t prev = idx[(numPoints-1)*N+POS]; + uint32_t prev = idx[(numPoints - 1) * N + POS]; - for (uint32_t i=0;i& faceNormals) -{ +static aiVector3D CalculateVertexNormal(SIBMesh *mesh, uint32_t faceIdx, uint32_t pos, + const std::vector &faceNormals) { // Creased edges complicate this. We need to find the start/end range of the // ring of faces that touch this position. // We do this in two passes. The first pass is to find the end of the range, // the second is to work backwards to the start and calculate the final normal. aiVector3D vtxNormal; - for (int pass=0;pass<2;pass++) - { + for (int pass = 0; pass < 2; pass++) { vtxNormal = aiVector3D(0, 0, 0); uint32_t startFaceIdx = faceIdx; uint32_t prevFaceIdx = faceIdx; // Process each connected face. - while (true) - { + while (true) { // Accumulate the face normal. vtxNormal += faceNormals[faceIdx]; uint32_t nextFaceIdx = 0xffffffff; // Move to the next edge sharing this position. - uint32_t* idx = &mesh->idx[mesh->faceStart[faceIdx]]; + uint32_t *idx = &mesh->idx[mesh->faceStart[faceIdx]]; uint32_t numPoints = *idx++; - uint32_t posA = idx[(numPoints-1)*N+POS]; - for (uint32_t n=0;nfaceStart.size(); // Calculate face normals. std::vector faceNormals(numFaces); - for (size_t faceIdx=0;faceIdxidx[mesh->faceStart[faceIdx]]; + for (size_t faceIdx = 0; faceIdx < numFaces; faceIdx++) { + uint32_t *idx = &mesh->idx[mesh->faceStart[faceIdx]]; uint32_t numPoints = *idx++; aiVector3D faceNormal(0, 0, 0); - uint32_t *prev = &idx[(numPoints-1)*N]; + uint32_t *prev = &idx[(numPoints - 1) * N]; - for (uint32_t i=0;ipos[prev[POS]] ^ mesh->pos[next[POS]]; prev = next; @@ -506,15 +476,13 @@ static void CalculateNormals(SIBMesh* mesh) } // Calculate vertex normals. - for (size_t faceIdx=0;faceIdxidx[mesh->faceStart[faceIdx]]; + for (size_t faceIdx = 0; faceIdx < numFaces; faceIdx++) { + uint32_t *idx = &mesh->idx[mesh->faceStart[faceIdx]]; uint32_t numPoints = *idx++; - for (uint32_t i=0;i(faceIdx), pos, faceNormals); mesh->nrm[nrm] = vtxNorm; } @@ -522,43 +490,39 @@ static void CalculateNormals(SIBMesh* mesh) } // ------------------------------------------------------------------------------------------------ -struct TempMesh -{ +struct TempMesh { std::vector vtx; std::vector nrm; std::vector uv; - std::vector faces; + std::vector faces; }; -static void ReadShape(SIB* sib, StreamReaderLE* stream) -{ +static void ReadShape(SIB *sib, StreamReaderLE *stream) { SIBMesh smesh; aiString name; - while (stream->GetRemainingSizeToLimit() >= sizeof(SIBChunk)) - { + while (stream->GetRemainingSizeToLimit() >= sizeof(SIBChunk)) { SIBChunk chunk = ReadChunk(stream); unsigned oldLimit = stream->SetReadLimit(stream->GetCurrentPos() + chunk.Size); - switch (chunk.Tag) - { - case TAG('M','I','R','P'): break; // mirror plane maybe? - case TAG('I','M','R','P'): break; // instance mirror? (not supported here yet) - case TAG('D','I','N','F'): break; // display info, not needed - case TAG('P','I','N','F'): break; // ? - case TAG('V','M','I','R'): break; // ? - case TAG('F','M','I','R'): break; // ? - case TAG('T','X','S','M'): break; // ? - case TAG('F','A','H','S'): break; // ? - case TAG('V','R','T','S'): ReadVerts(&smesh, stream, chunk.Size/12); break; - case TAG('F','A','C','S'): ReadFaces(&smesh, stream); break; - case TAG('F','T','V','S'): ReadUVs(&smesh, stream); break; - case TAG('S','N','A','M'): name = ReadString(stream, chunk.Size/2); break; - case TAG('F','A','M','A'): ReadMtls(&smesh, stream); break; - case TAG('A','X','I','S'): ReadAxis(smesh.axis, stream); break; - case TAG('E','D','G','S'): ReadEdges(&smesh, stream); break; - case TAG('E','C','R','S'): ReadCreases(&smesh, stream); break; - default: UnknownChunk(stream, chunk); break; + switch (chunk.Tag) { + case TAG('M', 'I', 'R', 'P'): break; // mirror plane maybe? + case TAG('I', 'M', 'R', 'P'): break; // instance mirror? (not supported here yet) + case TAG('D', 'I', 'N', 'F'): break; // display info, not needed + case TAG('P', 'I', 'N', 'F'): break; // ? + case TAG('V', 'M', 'I', 'R'): break; // ? + case TAG('F', 'M', 'I', 'R'): break; // ? + case TAG('T', 'X', 'S', 'M'): break; // ? + case TAG('F', 'A', 'H', 'S'): break; // ? + case TAG('V', 'R', 'T', 'S'): ReadVerts(&smesh, stream, chunk.Size / 12); break; + case TAG('F', 'A', 'C', 'S'): ReadFaces(&smesh, stream); break; + case TAG('F', 'T', 'V', 'S'): ReadUVs(&smesh, stream); break; + case TAG('S', 'N', 'A', 'M'): name = ReadString(stream, chunk.Size / 2); break; + case TAG('F', 'A', 'M', 'A'): ReadMtls(&smesh, stream); break; + case TAG('A', 'X', 'I', 'S'): ReadAxis(smesh.axis, stream); break; + case TAG('E', 'D', 'G', 'S'): ReadEdges(&smesh, stream); break; + case TAG('E', 'C', 'R', 'S'): ReadCreases(&smesh, stream); break; + default: UnknownChunk(stream, chunk); break; } stream->SetCurrentPos(stream->GetReadLimit()); @@ -585,25 +549,22 @@ static void ReadShape(SIB* sib, StreamReaderLE* stream) std::vector meshes(sib->mtls.size()); // Un-index the source data and apply to each vertex. - for (unsigned fi=0;fi= meshes.size()) - { + if (mtl >= meshes.size()) { ASSIMP_LOG_ERROR("SIB: Face material index is invalid."); mtl = 0; } - TempMesh& dest = meshes[mtl]; + TempMesh &dest = meshes[mtl]; aiFace face; face.mNumIndices = *idx++; face.mIndices = new unsigned[face.mNumIndices]; - for (unsigned pt=0;pt(vtxIdx); @@ -611,7 +572,7 @@ static void ReadShape(SIB* sib, StreamReaderLE* stream) // we did it when creating the data. aiVector3D pos = smesh.pos[idx[POS]]; aiVector3D nrm = smesh.nrm[idx[NRM]]; - aiVector3D uv = smesh.uv[idx[UV]]; + aiVector3D uv = smesh.uv[idx[UV]]; // The verts are supplied in world-space, so let's // transform them back into the local space of this mesh: @@ -632,13 +593,12 @@ static void ReadShape(SIB* sib, StreamReaderLE* stream) // Now that we know the size of everything, // we can build the final one-material-per-mesh data. - for (size_t n=0;nmName = name; mesh->mNumFaces = static_cast(src.faces.size()); mesh->mFaces = new aiFace[mesh->mNumFaces]; @@ -649,14 +609,12 @@ static void ReadShape(SIB* sib, StreamReaderLE* stream) mesh->mNumUVComponents[0] = 2; mesh->mMaterialIndex = static_cast(n); - for (unsigned i=0;imNumVertices;i++) - { + for (unsigned i = 0; i < mesh->mNumVertices; i++) { mesh->mVertices[i] = src.vtx[i]; mesh->mNormals[i] = src.nrm[i]; mesh->mTextureCoords[0][i] = src.uv[i]; } - for (unsigned i=0;imNumFaces;i++) - { + for (unsigned i = 0; i < mesh->mNumFaces; i++) { mesh->mFaces[i] = src.faces[i]; } @@ -668,8 +626,7 @@ static void ReadShape(SIB* sib, StreamReaderLE* stream) } // ------------------------------------------------------------------------------------------------ -static void ReadMaterial(SIB* sib, StreamReaderLE* stream) -{ +static void ReadMaterial(SIB *sib, StreamReaderLE *stream) { aiColor3D diff = ReadColor(stream); aiColor3D ambi = ReadColor(stream); aiColor3D spec = ReadColor(stream); @@ -677,11 +634,11 @@ static void ReadMaterial(SIB* sib, StreamReaderLE* stream) float shiny = (float)stream->GetU4(); uint32_t nameLen = stream->GetU4(); - aiString name = ReadString(stream, nameLen/2); + aiString name = ReadString(stream, nameLen / 2); uint32_t texLen = stream->GetU4(); - aiString tex = ReadString(stream, texLen/2); + aiString tex = ReadString(stream, texLen / 2); - aiMaterial* mtl = new aiMaterial(); + aiMaterial *mtl = new aiMaterial(); mtl->AddProperty(&diff, 1, AI_MATKEY_COLOR_DIFFUSE); mtl->AddProperty(&ambi, 1, AI_MATKEY_COLOR_AMBIENT); mtl->AddProperty(&spec, 1, AI_MATKEY_COLOR_SPECULAR); @@ -697,8 +654,7 @@ static void ReadMaterial(SIB* sib, StreamReaderLE* stream) } // ------------------------------------------------------------------------------------------------ -static void ReadLightInfo(aiLight* light, StreamReaderLE* stream) -{ +static void ReadLightInfo(aiLight *light, StreamReaderLE *stream) { uint32_t type = stream->GetU4(); switch (type) { case 0: light->mType = aiLightSource_POINT; break; @@ -728,7 +684,7 @@ static void ReadLightInfo(aiLight* light, StreamReaderLE* stream) // 99% and 1% percentiles. // OpenGL: I = cos(angle)^E // Solving: angle = acos(I^(1/E)) - ai_real E = ai_real( 1.0 ) / std::max(spotExponent, (ai_real)0.00001); + ai_real E = ai_real(1.0) / std::max(spotExponent, (ai_real)0.00001); ai_real inner = std::acos(std::pow((ai_real)0.99, E)); ai_real outer = std::acos(std::pow((ai_real)0.01, E)); @@ -739,20 +695,17 @@ static void ReadLightInfo(aiLight* light, StreamReaderLE* stream) light->mAngleOuterCone = outer; } -static void ReadLight(SIB* sib, StreamReaderLE* stream) -{ - aiLight* light = new aiLight(); +static void ReadLight(SIB *sib, StreamReaderLE *stream) { + aiLight *light = new aiLight(); - while (stream->GetRemainingSizeToLimit() >= sizeof(SIBChunk)) - { + while (stream->GetRemainingSizeToLimit() >= sizeof(SIBChunk)) { SIBChunk chunk = ReadChunk(stream); unsigned oldLimit = stream->SetReadLimit(stream->GetCurrentPos() + chunk.Size); - switch (chunk.Tag) - { - case TAG('L','N','F','O'): ReadLightInfo(light, stream); break; - case TAG('S','N','A','M'): light->mName = ReadString(stream, chunk.Size/2); break; - default: UnknownChunk(stream, chunk); break; + switch (chunk.Tag) { + case TAG('L', 'N', 'F', 'O'): ReadLightInfo(light, stream); break; + case TAG('S', 'N', 'A', 'M'): light->mName = ReadString(stream, chunk.Size / 2); break; + default: UnknownChunk(stream, chunk); break; } stream->SetCurrentPos(stream->GetReadLimit()); @@ -763,8 +716,7 @@ static void ReadLight(SIB* sib, StreamReaderLE* stream) } // ------------------------------------------------------------------------------------------------ -static void ReadScale(aiMatrix4x4& axis, StreamReaderLE* stream) -{ +static void ReadScale(aiMatrix4x4 &axis, StreamReaderLE *stream) { aiMatrix4x4 scale; scale.a1 = stream->GetF4(); scale.b1 = stream->GetF4(); @@ -786,68 +738,61 @@ static void ReadScale(aiMatrix4x4& axis, StreamReaderLE* stream) axis = axis * scale; } -static void ReadInstance(SIB* sib, StreamReaderLE* stream) -{ +static void ReadInstance(SIB *sib, StreamReaderLE *stream) { SIBObject inst; uint32_t shapeIndex = 0; - while (stream->GetRemainingSizeToLimit() >= sizeof(SIBChunk)) - { + while (stream->GetRemainingSizeToLimit() >= sizeof(SIBChunk)) { SIBChunk chunk = ReadChunk(stream); unsigned oldLimit = stream->SetReadLimit(stream->GetCurrentPos() + chunk.Size); - switch (chunk.Tag) - { - case TAG('D','I','N','F'): break; // display info, not needed - case TAG('P','I','N','F'): break; // ? - case TAG('A','X','I','S'): ReadAxis(inst.axis, stream); break; - case TAG('I','N','S','I'): shapeIndex = stream->GetU4(); break; - case TAG('S','M','T','X'): ReadScale(inst.axis, stream); break; - case TAG('S','N','A','M'): inst.name = ReadString(stream, chunk.Size/2); break; - default: UnknownChunk(stream, chunk); break; + switch (chunk.Tag) { + case TAG('D', 'I', 'N', 'F'): break; // display info, not needed + case TAG('P', 'I', 'N', 'F'): break; // ? + case TAG('A', 'X', 'I', 'S'): ReadAxis(inst.axis, stream); break; + case TAG('I', 'N', 'S', 'I'): shapeIndex = stream->GetU4(); break; + case TAG('S', 'M', 'T', 'X'): ReadScale(inst.axis, stream); break; + case TAG('S', 'N', 'A', 'M'): inst.name = ReadString(stream, chunk.Size / 2); break; + default: UnknownChunk(stream, chunk); break; } stream->SetCurrentPos(stream->GetReadLimit()); stream->SetReadLimit(oldLimit); } - if ( shapeIndex >= sib->objs.size() ) { - throw DeadlyImportError( "SIB: Invalid shape index." ); + if (shapeIndex >= sib->objs.size()) { + throw DeadlyImportError("SIB: Invalid shape index."); } - const SIBObject& src = sib->objs[shapeIndex]; + const SIBObject &src = sib->objs[shapeIndex]; inst.meshIdx = src.meshIdx; inst.meshCount = src.meshCount; sib->insts.push_back(inst); } // ------------------------------------------------------------------------------------------------ -static void CheckVersion(StreamReaderLE* stream) -{ +static void CheckVersion(StreamReaderLE *stream) { uint32_t version = stream->GetU4(); - if ( version < 1 || version > 2 ) { - throw DeadlyImportError( "SIB: Unsupported file version." ); + if (version < 1 || version > 2) { + throw DeadlyImportError("SIB: Unsupported file version."); } } -static void ReadScene(SIB* sib, StreamReaderLE* stream) -{ +static void ReadScene(SIB *sib, StreamReaderLE *stream) { // Parse each chunk in turn. - while (stream->GetRemainingSizeToLimit() >= sizeof(SIBChunk)) - { + while (stream->GetRemainingSizeToLimit() >= sizeof(SIBChunk)) { SIBChunk chunk = ReadChunk(stream); unsigned oldLimit = stream->SetReadLimit(stream->GetCurrentPos() + chunk.Size); - switch (chunk.Tag) - { - case TAG('H','E','A','D'): CheckVersion(stream); break; - case TAG('S','H','A','P'): ReadShape(sib, stream); break; - case TAG('G','R','P','S'): break; // group assignment, we don't import this - case TAG('T','E','X','P'): break; // ? - case TAG('I','N','S','T'): ReadInstance(sib, stream); break; - case TAG('M','A','T','R'): ReadMaterial(sib, stream); break; - case TAG('L','G','H','T'): ReadLight(sib, stream); break; - default: UnknownChunk(stream, chunk); break; + switch (chunk.Tag) { + case TAG('H', 'E', 'A', 'D'): CheckVersion(stream); break; + case TAG('S', 'H', 'A', 'P'): ReadShape(sib, stream); break; + case TAG('G', 'R', 'P', 'S'): break; // group assignment, we don't import this + case TAG('T', 'E', 'X', 'P'): break; // ? + case TAG('I', 'N', 'S', 'T'): ReadInstance(sib, stream); break; + case TAG('M', 'A', 'T', 'R'): ReadMaterial(sib, stream); break; + case TAG('L', 'G', 'H', 'T'): ReadLight(sib, stream); break; + default: UnknownChunk(stream, chunk); break; } stream->SetCurrentPos(stream->GetReadLimit()); @@ -857,9 +802,8 @@ static void ReadScene(SIB* sib, StreamReaderLE* stream) // ------------------------------------------------------------------------------------------------ // Imports the given file into the given scene structure. -void SIBImporter::InternReadFile(const std::string& pFile, - aiScene* pScene, IOSystem* pIOHandler) -{ +void SIBImporter::InternReadFile(const std::string &pFile, + aiScene *pScene, IOSystem *pIOHandler) { StreamReaderLE stream(pIOHandler->Open(pFile, "rb")); // We should have at least one chunk @@ -869,7 +813,7 @@ void SIBImporter::InternReadFile(const std::string& pFile, SIB sib; // Default material. - aiMaterial* defmtl = new aiMaterial; + aiMaterial *defmtl = new aiMaterial; aiString defname = aiString(AI_DEFAULT_MATERIAL_NAME); defmtl->AddProperty(&defname, AI_MATKEY_NAME); sib.mtls.push_back(defmtl); @@ -886,57 +830,54 @@ void SIBImporter::InternReadFile(const std::string& pFile, pScene->mNumMaterials = static_cast(sib.mtls.size()); pScene->mNumMeshes = static_cast(sib.meshes.size()); pScene->mNumLights = static_cast(sib.lights.size()); - pScene->mMaterials = pScene->mNumMaterials ? new aiMaterial*[pScene->mNumMaterials] : NULL; - pScene->mMeshes = pScene->mNumMeshes ? new aiMesh*[pScene->mNumMeshes] : NULL; - pScene->mLights = pScene->mNumLights ? new aiLight*[pScene->mNumLights] : NULL; + pScene->mMaterials = pScene->mNumMaterials ? new aiMaterial *[pScene->mNumMaterials] : nullptr; + pScene->mMeshes = pScene->mNumMeshes ? new aiMesh *[pScene->mNumMeshes] : nullptr; + pScene->mLights = pScene->mNumLights ? new aiLight *[pScene->mNumLights] : nullptr; if (pScene->mNumMaterials) - memcpy(pScene->mMaterials, &sib.mtls[0], sizeof(aiMaterial*) * pScene->mNumMaterials); + memcpy(pScene->mMaterials, &sib.mtls[0], sizeof(aiMaterial *) * pScene->mNumMaterials); if (pScene->mNumMeshes) - memcpy(pScene->mMeshes, &sib.meshes[0], sizeof(aiMesh*) * pScene->mNumMeshes); + memcpy(pScene->mMeshes, &sib.meshes[0], sizeof(aiMesh *) * pScene->mNumMeshes); if (pScene->mNumLights) - memcpy(pScene->mLights, &sib.lights[0], sizeof(aiLight*) * pScene->mNumLights); + memcpy(pScene->mLights, &sib.lights[0], sizeof(aiLight *) * pScene->mNumLights); // Construct the root node. size_t childIdx = 0; aiNode *root = new aiNode(); root->mName.Set(""); root->mNumChildren = static_cast(sib.objs.size() + sib.lights.size()); - root->mChildren = root->mNumChildren ? new aiNode*[root->mNumChildren] : NULL; + root->mChildren = root->mNumChildren ? new aiNode *[root->mNumChildren] : nullptr; pScene->mRootNode = root; // Add nodes for each object. - for (size_t n=0;nmChildren); - SIBObject& obj = sib.objs[n]; - aiNode* node = new aiNode; + SIBObject &obj = sib.objs[n]; + aiNode *node = new aiNode; root->mChildren[childIdx++] = node; node->mName = obj.name; node->mParent = root; node->mTransformation = obj.axis; node->mNumMeshes = static_cast(obj.meshCount); - node->mMeshes = node->mNumMeshes ? new unsigned[node->mNumMeshes] : NULL; - for (unsigned i=0;imNumMeshes;i++) + node->mMeshes = node->mNumMeshes ? new unsigned[node->mNumMeshes] : nullptr; + for (unsigned i = 0; i < node->mNumMeshes; i++) node->mMeshes[i] = static_cast(obj.meshIdx + i); // Mark instanced objects as being so. - if (n >= firstInst) - { - node->mMetaData = aiMetadata::Alloc( 1 ); - node->mMetaData->Set( 0, "IsInstance", true ); + if (n >= firstInst) { + node->mMetaData = aiMetadata::Alloc(1); + node->mMetaData->Set(0, "IsInstance", true); } } // Add nodes for each light. // (no transformation as the light is already in world space) - for (size_t n=0;nmChildren); - aiLight* light = sib.lights[n]; - if ( nullptr != light ) { - aiNode* node = new aiNode; - root->mChildren[ childIdx++ ] = node; + aiLight *light = sib.lights[n]; + if (nullptr != light) { + aiNode *node = new aiNode; + root->mChildren[childIdx++] = node; node->mName = light->mName; node->mParent = root; } diff --git a/code/AssetLib/SMD/SMDLoader.cpp b/code/AssetLib/SMD/SMDLoader.cpp index 2d9d677a7..8a7625f93 100644 --- a/code/AssetLib/SMD/SMDLoader.cpp +++ b/code/AssetLib/SMD/SMDLoader.cpp @@ -577,7 +577,7 @@ void SMDImporter::GetAnimationFileList(const std::string &pFile, IOSystem* pIOHa char *context1, *context2; tok1 = strtok_s(&buf[0], "\r\n", &context1); - while (tok1 != NULL) { + while (tok1 != nullptr) { tok2 = strtok_s(tok1, " \t", &context2); if (tok2) { char *p = tok2; diff --git a/code/AssetLib/STEPParser/STEPFileReader.cpp b/code/AssetLib/STEPParser/STEPFileReader.cpp index 84c5c463a..d3f2a344c 100644 --- a/code/AssetLib/STEPParser/STEPFileReader.cpp +++ b/code/AssetLib/STEPParser/STEPFileReader.cpp @@ -299,7 +299,7 @@ void STEP::ReadFile(DB& db,const EXPRESS::ConversionSchema& scheme, } // ------------------------------------------------------------------------------------------------ -std::shared_ptr EXPRESS::DataType::Parse(const char*& inout,uint64_t line, const EXPRESS::ConversionSchema* schema /*= NULL*/) +std::shared_ptr EXPRESS::DataType::Parse(const char*& inout,uint64_t line, const EXPRESS::ConversionSchema* schema /*= nullptr*/) { const char* cur = inout; SkipSpaces(&cur); @@ -422,7 +422,7 @@ std::shared_ptr EXPRESS::DataType::Parse(const char*& i } // ------------------------------------------------------------------------------------------------ -std::shared_ptr EXPRESS::LIST::Parse(const char*& inout,uint64_t line, const EXPRESS::ConversionSchema* schema /*= NULL*/) { +std::shared_ptr EXPRESS::LIST::Parse(const char*& inout,uint64_t line, const EXPRESS::ConversionSchema* schema /*= nullptr*/) { const std::shared_ptr list = std::make_shared(); EXPRESS::LIST::MemberList& members = list->members; @@ -540,9 +540,9 @@ void STEP::LazyObject::LazyInit() const { const char* acopy = args; std::shared_ptr conv_args = EXPRESS::LIST::Parse(acopy,(uint64_t)STEP::SyntaxError::LINE_NOT_SPECIFIED,&db.GetSchema()); delete[] args; - args = NULL; + args = nullptr; - // if the converter fails, it should throw an exception, but it should never return NULL + // if the converter fails, it should throw an exception, but it should never return nullptr try { obj = proc(db,*conv_args); } diff --git a/code/AssetLib/STL/STLExporter.cpp b/code/AssetLib/STL/STLExporter.cpp index 06723cdba..fd4c41033 100644 --- a/code/AssetLib/STL/STLExporter.cpp +++ b/code/AssetLib/STL/STLExporter.cpp @@ -72,7 +72,7 @@ void ExportSceneSTL(const char* pFile,IOSystem* pIOSystem, const aiScene* pScene // we're still here - export successfully completed. Write the file. std::unique_ptr outfile (pIOSystem->Open(pFile,"wt")); - if(outfile == NULL) { + if (outfile == nullptr) { throw DeadlyExportError("could not open output .stl file: " + std::string(pFile)); } @@ -91,7 +91,7 @@ void ExportSceneSTLBinary(const char* pFile,IOSystem* pIOSystem, const aiScene* // we're still here - export successfully completed. Write the file. std::unique_ptr outfile (pIOSystem->Open(pFile,"wb")); - if(outfile == NULL) { + if (outfile == nullptr) { throw DeadlyExportError("could not open output .stl file: " + std::string(pFile)); } diff --git a/code/AssetLib/STL/STLLoader.cpp b/code/AssetLib/STL/STLLoader.cpp index 702f4fe5d..2d710b084 100644 --- a/code/AssetLib/STL/STLLoader.cpp +++ b/code/AssetLib/STL/STLLoader.cpp @@ -5,8 +5,6 @@ Open Asset Import Library (assimp) Copyright (c) 2006-2020, assimp team - - All rights reserved. Redistribution and use of this software in source and binary forms, @@ -101,11 +99,13 @@ static bool IsAsciiSTL(const char *buffer, unsigned int fileSize) { const char *bufferEnd = buffer + fileSize; - if (!SkipSpaces(&buffer)) + if (!SkipSpaces(&buffer)) { return false; + } - if (buffer + 5 >= bufferEnd) + if (buffer + 5 >= bufferEnd) { return false; + } bool isASCII(strncmp(buffer, "solid", 5) == 0); if (isASCII) { @@ -370,13 +370,21 @@ void STLImporter::LoadASCIIFile(aiNode *root) { pMesh->mNumFaces = static_cast(positionBuffer.size() / 3); pMesh->mNumVertices = static_cast(positionBuffer.size()); pMesh->mVertices = new aiVector3D[pMesh->mNumVertices]; - memcpy(pMesh->mVertices, &positionBuffer[0].x, pMesh->mNumVertices * sizeof(aiVector3D)); + for (size_t i=0; imNumVertices; ++i ) { + pMesh->mVertices[i].x = positionBuffer[i].x; + pMesh->mVertices[i].y = positionBuffer[i].y; + pMesh->mVertices[i].z = positionBuffer[i].z; + } positionBuffer.clear(); } // also only process normalBuffer when filled, else exception when accessing with index operator if (!normalBuffer.empty()) { pMesh->mNormals = new aiVector3D[pMesh->mNumVertices]; - memcpy(pMesh->mNormals, &normalBuffer[0].x, pMesh->mNumVertices * sizeof(aiVector3D)); + for (size_t i=0; imNumVertices; ++i ) { + pMesh->mNormals[i].x = normalBuffer[i].x; + pMesh->mNormals[i].y = normalBuffer[i].y; + pMesh->mNormals[i].z = normalBuffer[i].z; + } normalBuffer.clear(); } diff --git a/code/AssetLib/Step/StepExporter.cpp b/code/AssetLib/Step/StepExporter.cpp index 279ecabe9..38723ca97 100644 --- a/code/AssetLib/Step/StepExporter.cpp +++ b/code/AssetLib/Step/StepExporter.cpp @@ -108,7 +108,7 @@ void ExportSceneStep(const char* pFile,IOSystem* pIOSystem, const aiScene* pScen // we're still here - export successfully completed. Write result to the given IOSYstem std::unique_ptr outfile (pIOSystem->Open(pFile,"wt")); - if(outfile == NULL) { + if (outfile == nullptr) { throw DeadlyExportError("could not open output .stp file: " + std::string(pFile)); } @@ -204,7 +204,7 @@ void StepExporter::WriteFile() static const unsigned int date_nb_chars = 20; char date_str[date_nb_chars]; - std::time_t date = std::time(NULL); + std::time_t date = std::time(nullptr); std::strftime(date_str, date_nb_chars, "%Y-%m-%dT%H:%M:%S", std::localtime(&date)); // write the header diff --git a/code/AssetLib/Terragen/TerragenLoader.cpp b/code/AssetLib/Terragen/TerragenLoader.cpp index 5f25c2455..0d0a140c3 100644 --- a/code/AssetLib/Terragen/TerragenLoader.cpp +++ b/code/AssetLib/Terragen/TerragenLoader.cpp @@ -87,12 +87,16 @@ bool TerragenImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, b if (!extension.length() || checkSig) { /* If CanRead() is called in order to check whether we * support a specific file extension in general pIOHandler - * might be NULL and it's our duty to return true here. + * might be nullptr and it's our duty to return true here. */ - if (!pIOHandler) return true; + if (!pIOHandler) { + return true; + } + const char *tokens[] = { "terragen" }; return SearchFileHeaderForToken(pIOHandler, pFile, tokens, 1); } + return false; } @@ -116,7 +120,7 @@ void TerragenImporter::InternReadFile(const std::string &pFile, IOStream *file = pIOHandler->Open(pFile, "rb"); // Check whether we can read from the file - if (file == NULL) + if (file == nullptr) throw DeadlyImportError("Failed to open TERRAGEN TERRAIN file " + pFile + "."); // Construct a stream reader to read all data in the correct endianness @@ -199,7 +203,7 @@ void TerragenImporter::InternReadFile(const std::string &pFile, aiFace *f = m->mFaces = new aiFace[m->mNumFaces = (x - 1) * (y - 1)]; aiVector3D *pv = m->mVertices = new aiVector3D[m->mNumVertices = m->mNumFaces * 4]; - aiVector3D *uv(NULL); + aiVector3D *uv(nullptr); float step_y(0.0f), step_x(0.0f); if (configComputeUVs) { uv = m->mTextureCoords[0] = new aiVector3D[m->mNumVertices]; diff --git a/code/AssetLib/X/XFileExporter.cpp b/code/AssetLib/X/XFileExporter.cpp index 41b58487e..2e4232fb9 100644 --- a/code/AssetLib/X/XFileExporter.cpp +++ b/code/AssetLib/X/XFileExporter.cpp @@ -89,7 +89,7 @@ void ExportSceneXFile(const char* pFile,IOSystem* pIOSystem, const aiScene* pSce // we're still here - export successfully completed. Write result to the given IOSYstem std::unique_ptr outfile (pIOSystem->Open(pFile,"wt")); - if(outfile == NULL) { + if (outfile == nullptr) { throw DeadlyExportError("could not open output .x file: " + std::string(pFile)); } diff --git a/code/AssetLib/X/XFileImporter.cpp b/code/AssetLib/X/XFileImporter.cpp index 277948b08..6c57c9dd2 100644 --- a/code/AssetLib/X/XFileImporter.cpp +++ b/code/AssetLib/X/XFileImporter.cpp @@ -113,7 +113,7 @@ const aiImporterDesc* XFileImporter::GetInfo () const { void XFileImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler) { // read file into memory std::unique_ptr file( pIOHandler->Open( pFile)); - if ( file.get() == NULL ) { + if ( file.get() == nullptr ) { throw DeadlyImportError( "Failed to open file " + pFile + "." ); } diff --git a/code/AssetLib/X/XFileParser.cpp b/code/AssetLib/X/XFileParser.cpp index 8847119c4..f0b751498 100644 --- a/code/AssetLib/X/XFileParser.cpp +++ b/code/AssetLib/X/XFileParser.cpp @@ -43,30 +43,28 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. /** @file Implementation of the XFile parser helper class */ - #ifndef ASSIMP_BUILD_NO_X_IMPORTER #include "XFileParser.h" #include "XFileHelper.h" -#include -#include -#include #include +#include #include +#include +#include #include - using namespace Assimp; using namespace Assimp::XFile; using namespace Assimp::Formatter; #ifndef ASSIMP_BUILD_NO_COMPRESSED_X -# ifdef ASSIMP_BUILD_NO_OWN_ZLIB -# include -# else -# include "../contrib/zlib/zlib.h" -# endif +#ifdef ASSIMP_BUILD_NO_OWN_ZLIB +#include +#else +#include "../contrib/zlib/zlib.h" +#endif // Magic identifier for MSZIP compressed data #define MSZIP_MAGIC 0x4B43 @@ -74,11 +72,11 @@ using namespace Assimp::Formatter; // ------------------------------------------------------------------------------------------------ // Dummy memory wrappers for use with zlib -static void* dummy_alloc (void* /*opaque*/, unsigned int items, unsigned int size) { - return ::operator new(items*size); +static void *dummy_alloc(void * /*opaque*/, unsigned int items, unsigned int size) { + return ::operator new(items *size); } -static void dummy_free (void* /*opaque*/, void* address) { +static void dummy_free(void * /*opaque*/, void *address) { return ::operator delete(address); } @@ -86,15 +84,8 @@ static void dummy_free (void* /*opaque*/, void* address) { // ------------------------------------------------------------------------------------------------ // Constructor. Creates a data structure out of the XFile given in the memory block. -XFileParser::XFileParser( const std::vector& pBuffer) -: mMajorVersion( 0 ) -, mMinorVersion( 0 ) -, mIsBinaryFormat( false ) -, mBinaryNumCount( 0 ) -, mP( nullptr ) -, mEnd( nullptr ) -, mLineNumber( 0 ) -, mScene( nullptr ) { +XFileParser::XFileParser(const std::vector &pBuffer) : + mMajorVersion(0), mMinorVersion(0), mIsBinaryFormat(false), mBinaryNumCount(0), mP(nullptr), mEnd(nullptr), mLineNumber(0), mScene(nullptr) { // vector to store uncompressed file for INFLATE'd X files std::vector uncompressed; @@ -103,8 +94,8 @@ XFileParser::XFileParser( const std::vector& pBuffer) mEnd = mP + pBuffer.size() - 1; // check header - if ( 0 != strncmp( mP, "xof ", 4 ) ) { - throw DeadlyImportError( "Header mismatch, file is not an XFile." ); + if (0 != strncmp(mP, "xof ", 4)) { + throw DeadlyImportError("Header mismatch, file is not an XFile."); } // read version. It comes in a four byte format such as "0302" @@ -114,36 +105,30 @@ XFileParser::XFileParser( const std::vector& pBuffer) bool compressed = false; // txt - pure ASCII text format - if( strncmp( mP + 8, "txt ", 4) == 0) + if (strncmp(mP + 8, "txt ", 4) == 0) mIsBinaryFormat = false; // bin - Binary format - else if( strncmp( mP + 8, "bin ", 4) == 0) + else if (strncmp(mP + 8, "bin ", 4) == 0) mIsBinaryFormat = true; // tzip - Inflate compressed text format - else if( strncmp( mP + 8, "tzip", 4) == 0) - { + else if (strncmp(mP + 8, "tzip", 4) == 0) { mIsBinaryFormat = false; compressed = true; } // bzip - Inflate compressed binary format - else if( strncmp( mP + 8, "bzip", 4) == 0) - { + else if (strncmp(mP + 8, "bzip", 4) == 0) { mIsBinaryFormat = true; compressed = true; - } - else ThrowException( format() << "Unsupported xfile format '" << - mP[8] << mP[9] << mP[10] << mP[11] << "'"); + } else + ThrowException(format() << "Unsupported xfile format '" << mP[8] << mP[9] << mP[10] << mP[11] << "'"); // float size - mBinaryFloatSize = (unsigned int)(mP[12] - 48) * 1000 - + (unsigned int)(mP[13] - 48) * 100 - + (unsigned int)(mP[14] - 48) * 10 - + (unsigned int)(mP[15] - 48); + mBinaryFloatSize = (unsigned int)(mP[12] - 48) * 1000 + (unsigned int)(mP[13] - 48) * 100 + (unsigned int)(mP[14] - 48) * 10 + (unsigned int)(mP[15] - 48); - if( mBinaryFloatSize != 32 && mBinaryFloatSize != 64) - ThrowException( format() << "Unknown float size " << mBinaryFloatSize << " specified in xfile header." ); + if (mBinaryFloatSize != 32 && mBinaryFloatSize != 64) + ThrowException(format() << "Unknown float size " << mBinaryFloatSize << " specified in xfile header."); // The x format specifies size in bits, but we work in bytes mBinaryFloatSize /= 8; @@ -151,8 +136,7 @@ XFileParser::XFileParser( const std::vector& pBuffer) mP += 16; // If this is a compressed X file, apply the inflate algorithm to it - if (compressed) - { + if (compressed) { #ifdef ASSIMP_BUILD_NO_COMPRESSED_X throw DeadlyImportError("Assimp was built without compressed X support"); #else @@ -178,9 +162,9 @@ XFileParser::XFileParser( const std::vector& pBuffer) // build a zlib stream z_stream stream; - stream.opaque = NULL; + stream.opaque = nullptr; stream.zalloc = &dummy_alloc; - stream.zfree = &dummy_free; + stream.zfree = &dummy_free; stream.data_type = (mIsBinaryFormat ? Z_BINARY : Z_ASCII); // initialize the inflation algorithm @@ -190,21 +174,22 @@ XFileParser::XFileParser( const std::vector& pBuffer) mP += 6; // First find out how much storage we'll need. Count sections. - const char* P1 = mP; + const char *P1 = mP; unsigned int est_out = 0; - while (P1 + 3 < mEnd) - { + while (P1 + 3 < mEnd) { // read next offset - uint16_t ofs = *((uint16_t*)P1); - AI_SWAP2(ofs); P1 += 2; + uint16_t ofs = *((uint16_t *)P1); + AI_SWAP2(ofs); + P1 += 2; if (ofs >= MSZIP_BLOCK) throw DeadlyImportError("X: Invalid offset to next MSZIP compressed block"); // check magic word - uint16_t magic = *((uint16_t*)P1); - AI_SWAP2(magic); P1 += 2; + uint16_t magic = *((uint16_t *)P1); + AI_SWAP2(magic); + P1 += 2; if (magic != MSZIP_MAGIC) throw DeadlyImportError("X: Unsupported compressed format, expected MSZIP header"); @@ -216,10 +201,9 @@ XFileParser::XFileParser( const std::vector& pBuffer) // Allocate storage and terminating zero and do the actual uncompressing uncompressed.resize(est_out + 1); - char* out = &uncompressed.front(); - while (mP + 3 < mEnd) - { - uint16_t ofs = *((uint16_t*)mP); + char *out = &uncompressed.front(); + while (mP + 3 < mEnd) { + uint16_t ofs = *((uint16_t *)mP); AI_SWAP2(ofs); mP += 4; @@ -228,22 +212,22 @@ XFileParser::XFileParser( const std::vector& pBuffer) } // push data to the stream - stream.next_in = (Bytef*)mP; - stream.avail_in = ofs; - stream.next_out = (Bytef*)out; + stream.next_in = (Bytef *)mP; + stream.avail_in = ofs; + stream.next_out = (Bytef *)out; stream.avail_out = MSZIP_BLOCK; // and decompress the data .... - int ret = ::inflate( &stream, Z_SYNC_FLUSH ); + int ret = ::inflate(&stream, Z_SYNC_FLUSH); if (ret != Z_OK && ret != Z_STREAM_END) throw DeadlyImportError("X: Failed to decompress MSZIP-compressed data"); - ::inflateReset( &stream ); - ::inflateSetDictionary( &stream, (const Bytef*)out , MSZIP_BLOCK - stream.avail_out ); + ::inflateReset(&stream); + ::inflateSetDictionary(&stream, (const Bytef *)out, MSZIP_BLOCK - stream.avail_out); // and advance to the next offset - out += MSZIP_BLOCK - stream.avail_out; - mP += ofs; + out += MSZIP_BLOCK - stream.avail_out; + mP += ofs; } // terminate zlib @@ -257,9 +241,7 @@ XFileParser::XFileParser( const std::vector& pBuffer) // it already for better memory usage. Consider breaking const-co. ASSIMP_LOG_INFO("Successfully decompressed MSZIP-compressed file"); #endif // !! ASSIMP_BUILD_NO_COMPRESSED_X - } - else - { + } else { // start reading here ReadUntilEndOfLine(); } @@ -268,63 +250,50 @@ XFileParser::XFileParser( const std::vector& pBuffer) ParseFile(); // filter the imported hierarchy for some degenerated cases - if( mScene->mRootNode) { - FilterHierarchy( mScene->mRootNode); + if (mScene->mRootNode) { + FilterHierarchy(mScene->mRootNode); } } // ------------------------------------------------------------------------------------------------ // Destructor. Destroys all imported data along with it -XFileParser::~XFileParser() -{ +XFileParser::~XFileParser() { // kill everything we created delete mScene; } // ------------------------------------------------------------------------------------------------ -void XFileParser::ParseFile() -{ +void XFileParser::ParseFile() { bool running = true; - while( running ) - { + while (running) { // read name of next object std::string objectName = GetNextToken(); if (objectName.length() == 0) break; // parse specific object - if( objectName == "template") + if (objectName == "template") ParseDataObjectTemplate(); - else - if( objectName == "Frame") - ParseDataObjectFrame( NULL); - else - if( objectName == "Mesh") - { + else if (objectName == "Frame") + ParseDataObjectFrame(nullptr); + else if (objectName == "Mesh") { // some meshes have no frames at all - Mesh* mesh = new Mesh; - ParseDataObjectMesh( mesh); - mScene->mGlobalMeshes.push_back( mesh); - } else - if( objectName == "AnimTicksPerSecond") + Mesh *mesh = new Mesh; + ParseDataObjectMesh(mesh); + mScene->mGlobalMeshes.push_back(mesh); + } else if (objectName == "AnimTicksPerSecond") ParseDataObjectAnimTicksPerSecond(); - else - if( objectName == "AnimationSet") + else if (objectName == "AnimationSet") ParseDataObjectAnimationSet(); - else - if( objectName == "Material") - { + else if (objectName == "Material") { // Material outside of a mesh or node Material material; - ParseDataObjectMaterial( &material); - mScene->mGlobalMaterials.push_back( material); - } else - if( objectName == "}") - { + ParseDataObjectMaterial(&material); + mScene->mGlobalMaterials.push_back(material); + } else if (objectName == "}") { // whatever? ASSIMP_LOG_WARN("} found in dataObject"); - } else - { + } else { // unknown format ASSIMP_LOG_WARN("Unknown data object in animation of .x file"); ParseUnknownDataObject(); @@ -333,32 +302,29 @@ void XFileParser::ParseFile() } // ------------------------------------------------------------------------------------------------ -void XFileParser::ParseDataObjectTemplate() -{ +void XFileParser::ParseDataObjectTemplate() { // parse a template data object. Currently not stored. std::string name; - readHeadOfDataObject( &name); + readHeadOfDataObject(&name); // read GUID std::string guid = GetNextToken(); // read and ignore data members bool running = true; - while ( running ) - { + while (running) { std::string s = GetNextToken(); - if( s == "}") + if (s == "}") break; - if( s.length() == 0) - ThrowException( "Unexpected end of file reached while parsing template definition"); + if (s.length() == 0) + ThrowException("Unexpected end of file reached while parsing template definition"); } } // ------------------------------------------------------------------------------------------------ -void XFileParser::ParseDataObjectFrame( Node* pParent) -{ +void XFileParser::ParseDataObjectFrame(Node *pParent) { // A coordinate frame, or "frame of reference." The Frame template // is open and can contain any object. The Direct3D extensions (D3DX) // mesh-loading functions recognize Mesh, FrameTransformMatrix, and @@ -368,30 +334,25 @@ void XFileParser::ParseDataObjectFrame( Node* pParent) readHeadOfDataObject(&name); // create a named node and place it at its parent, if given - Node* node = new Node( pParent); + Node *node = new Node(pParent); node->mName = name; - if( pParent) - { - pParent->mChildren.push_back( node); - } else - { + if (pParent) { + pParent->mChildren.push_back(node); + } else { // there might be multiple root nodes - if( mScene->mRootNode != NULL) - { + if (mScene->mRootNode != nullptr) { // place a dummy root if not there - if( mScene->mRootNode->mName != "$dummy_root") - { - Node* exroot = mScene->mRootNode; - mScene->mRootNode = new Node( NULL); + if (mScene->mRootNode->mName != "$dummy_root") { + Node *exroot = mScene->mRootNode; + mScene->mRootNode = new Node(nullptr); mScene->mRootNode->mName = "$dummy_root"; - mScene->mRootNode->mChildren.push_back( exroot); + mScene->mRootNode->mChildren.push_back(exroot); exroot->mParent = mScene->mRootNode; } // put the new node as its child instead - mScene->mRootNode->mChildren.push_back( node); + mScene->mRootNode->mChildren.push_back(node); node->mParent = mScene->mRootNode; - } else - { + } else { // it's the first node imported. place it as root mScene->mRootNode = node; } @@ -400,28 +361,22 @@ void XFileParser::ParseDataObjectFrame( Node* pParent) // Now inside a frame. // read tokens until closing brace is reached. bool running = true; - while ( running ) - { + while (running) { std::string objectName = GetNextToken(); if (objectName.size() == 0) - ThrowException( "Unexpected end of file reached while parsing frame"); + ThrowException("Unexpected end of file reached while parsing frame"); - if( objectName == "}") + if (objectName == "}") break; // frame finished - else - if( objectName == "Frame") - ParseDataObjectFrame( node); // child frame - else - if( objectName == "FrameTransformMatrix") - ParseDataObjectTransformationMatrix( node->mTrafoMatrix); - else - if( objectName == "Mesh") - { - Mesh* mesh = new Mesh(name); - node->mMeshes.push_back( mesh); - ParseDataObjectMesh( mesh); - } else - { + else if (objectName == "Frame") + ParseDataObjectFrame(node); // child frame + else if (objectName == "FrameTransformMatrix") + ParseDataObjectTransformationMatrix(node->mTrafoMatrix); + else if (objectName == "Mesh") { + Mesh *mesh = new Mesh(name); + node->mMeshes.push_back(mesh); + ParseDataObjectMesh(mesh); + } else { ASSIMP_LOG_WARN("Unknown data object in frame in x file"); ParseUnknownDataObject(); } @@ -429,20 +384,27 @@ void XFileParser::ParseDataObjectFrame( Node* pParent) } // ------------------------------------------------------------------------------------------------ -void XFileParser::ParseDataObjectTransformationMatrix( aiMatrix4x4& pMatrix) -{ +void XFileParser::ParseDataObjectTransformationMatrix(aiMatrix4x4 &pMatrix) { // read header, we're not interested if it has a name readHeadOfDataObject(); // read its components - pMatrix.a1 = ReadFloat(); pMatrix.b1 = ReadFloat(); - pMatrix.c1 = ReadFloat(); pMatrix.d1 = ReadFloat(); - pMatrix.a2 = ReadFloat(); pMatrix.b2 = ReadFloat(); - pMatrix.c2 = ReadFloat(); pMatrix.d2 = ReadFloat(); - pMatrix.a3 = ReadFloat(); pMatrix.b3 = ReadFloat(); - pMatrix.c3 = ReadFloat(); pMatrix.d3 = ReadFloat(); - pMatrix.a4 = ReadFloat(); pMatrix.b4 = ReadFloat(); - pMatrix.c4 = ReadFloat(); pMatrix.d4 = ReadFloat(); + pMatrix.a1 = ReadFloat(); + pMatrix.b1 = ReadFloat(); + pMatrix.c1 = ReadFloat(); + pMatrix.d1 = ReadFloat(); + pMatrix.a2 = ReadFloat(); + pMatrix.b2 = ReadFloat(); + pMatrix.c2 = ReadFloat(); + pMatrix.d2 = ReadFloat(); + pMatrix.a3 = ReadFloat(); + pMatrix.b3 = ReadFloat(); + pMatrix.c3 = ReadFloat(); + pMatrix.d3 = ReadFloat(); + pMatrix.a4 = ReadFloat(); + pMatrix.b4 = ReadFloat(); + pMatrix.c4 = ReadFloat(); + pMatrix.d4 = ReadFloat(); // trailing symbols CheckForSemicolon(); @@ -450,30 +412,29 @@ void XFileParser::ParseDataObjectTransformationMatrix( aiMatrix4x4& pMatrix) } // ------------------------------------------------------------------------------------------------ -void XFileParser::ParseDataObjectMesh( Mesh* pMesh) -{ +void XFileParser::ParseDataObjectMesh(Mesh *pMesh) { std::string name; - readHeadOfDataObject( &name); + readHeadOfDataObject(&name); // read vertex count unsigned int numVertices = ReadInt(); - pMesh->mPositions.resize( numVertices); + pMesh->mPositions.resize(numVertices); // read vertices - for( unsigned int a = 0; a < numVertices; a++) + for (unsigned int a = 0; a < numVertices; a++) pMesh->mPositions[a] = ReadVector3(); // read position faces unsigned int numPosFaces = ReadInt(); - pMesh->mPosFaces.resize( numPosFaces); - for( unsigned int a = 0; a < numPosFaces; ++a) { + pMesh->mPosFaces.resize(numPosFaces); + for (unsigned int a = 0; a < numPosFaces; ++a) { // read indices unsigned int numIndices = ReadInt(); - Face& face = pMesh->mPosFaces[a]; + Face &face = pMesh->mPosFaces[a]; for (unsigned int b = 0; b < numIndices; ++b) { - const int idx( ReadInt() ); - if ( static_cast( idx ) <= numVertices ) { - face.mIndices.push_back( idx ); + const int idx(ReadInt()); + if (static_cast(idx) <= numVertices) { + face.mIndices.push_back(idx); } } TestForSeparator(); @@ -481,37 +442,28 @@ void XFileParser::ParseDataObjectMesh( Mesh* pMesh) // here, other data objects may follow bool running = true; - while ( running ) { + while (running) { std::string objectName = GetNextToken(); - if( objectName.empty() ) - ThrowException( "Unexpected end of file while parsing mesh structure"); - else - if( objectName == "}") + if (objectName.empty()) + ThrowException("Unexpected end of file while parsing mesh structure"); + else if (objectName == "}") break; // mesh finished - else - if( objectName == "MeshNormals") - ParseDataObjectMeshNormals( pMesh); - else - if( objectName == "MeshTextureCoords") - ParseDataObjectMeshTextureCoords( pMesh); - else - if( objectName == "MeshVertexColors") - ParseDataObjectMeshVertexColors( pMesh); - else - if( objectName == "MeshMaterialList") - ParseDataObjectMeshMaterialList( pMesh); - else - if( objectName == "VertexDuplicationIndices") + else if (objectName == "MeshNormals") + ParseDataObjectMeshNormals(pMesh); + else if (objectName == "MeshTextureCoords") + ParseDataObjectMeshTextureCoords(pMesh); + else if (objectName == "MeshVertexColors") + ParseDataObjectMeshVertexColors(pMesh); + else if (objectName == "MeshMaterialList") + ParseDataObjectMeshMaterialList(pMesh); + else if (objectName == "VertexDuplicationIndices") ParseUnknownDataObject(); // we'll ignore vertex duplication indices - else - if( objectName == "XSkinMeshHeader") - ParseDataObjectSkinMeshHeader( pMesh); - else - if( objectName == "SkinWeights") - ParseDataObjectSkinWeights( pMesh); - else - { + else if (objectName == "XSkinMeshHeader") + ParseDataObjectSkinMeshHeader(pMesh); + else if (objectName == "SkinWeights") + ParseDataObjectSkinWeights(pMesh); + else { ASSIMP_LOG_WARN("Unknown data object in mesh in x file"); ParseUnknownDataObject(); } @@ -519,90 +471,95 @@ void XFileParser::ParseDataObjectMesh( Mesh* pMesh) } // ------------------------------------------------------------------------------------------------ -void XFileParser::ParseDataObjectSkinWeights( Mesh *pMesh) { - if ( nullptr == pMesh ) { +void XFileParser::ParseDataObjectSkinWeights(Mesh *pMesh) { + if (nullptr == pMesh) { return; } readHeadOfDataObject(); std::string transformNodeName; - GetNextTokenAsString( transformNodeName); + GetNextTokenAsString(transformNodeName); - pMesh->mBones.push_back( Bone()); - Bone& bone = pMesh->mBones.back(); + pMesh->mBones.push_back(Bone()); + Bone &bone = pMesh->mBones.back(); bone.mName = transformNodeName; // read vertex weights unsigned int numWeights = ReadInt(); - bone.mWeights.reserve( numWeights); + bone.mWeights.reserve(numWeights); - for( unsigned int a = 0; a < numWeights; a++) - { + for (unsigned int a = 0; a < numWeights; a++) { BoneWeight weight; weight.mVertex = ReadInt(); - bone.mWeights.push_back( weight); + bone.mWeights.push_back(weight); } // read vertex weights - for( unsigned int a = 0; a < numWeights; a++) + for (unsigned int a = 0; a < numWeights; a++) bone.mWeights[a].mWeight = ReadFloat(); // read matrix offset - bone.mOffsetMatrix.a1 = ReadFloat(); bone.mOffsetMatrix.b1 = ReadFloat(); - bone.mOffsetMatrix.c1 = ReadFloat(); bone.mOffsetMatrix.d1 = ReadFloat(); - bone.mOffsetMatrix.a2 = ReadFloat(); bone.mOffsetMatrix.b2 = ReadFloat(); - bone.mOffsetMatrix.c2 = ReadFloat(); bone.mOffsetMatrix.d2 = ReadFloat(); - bone.mOffsetMatrix.a3 = ReadFloat(); bone.mOffsetMatrix.b3 = ReadFloat(); - bone.mOffsetMatrix.c3 = ReadFloat(); bone.mOffsetMatrix.d3 = ReadFloat(); - bone.mOffsetMatrix.a4 = ReadFloat(); bone.mOffsetMatrix.b4 = ReadFloat(); - bone.mOffsetMatrix.c4 = ReadFloat(); bone.mOffsetMatrix.d4 = ReadFloat(); + bone.mOffsetMatrix.a1 = ReadFloat(); + bone.mOffsetMatrix.b1 = ReadFloat(); + bone.mOffsetMatrix.c1 = ReadFloat(); + bone.mOffsetMatrix.d1 = ReadFloat(); + bone.mOffsetMatrix.a2 = ReadFloat(); + bone.mOffsetMatrix.b2 = ReadFloat(); + bone.mOffsetMatrix.c2 = ReadFloat(); + bone.mOffsetMatrix.d2 = ReadFloat(); + bone.mOffsetMatrix.a3 = ReadFloat(); + bone.mOffsetMatrix.b3 = ReadFloat(); + bone.mOffsetMatrix.c3 = ReadFloat(); + bone.mOffsetMatrix.d3 = ReadFloat(); + bone.mOffsetMatrix.a4 = ReadFloat(); + bone.mOffsetMatrix.b4 = ReadFloat(); + bone.mOffsetMatrix.c4 = ReadFloat(); + bone.mOffsetMatrix.d4 = ReadFloat(); CheckForSemicolon(); CheckForClosingBrace(); } // ------------------------------------------------------------------------------------------------ -void XFileParser::ParseDataObjectSkinMeshHeader( Mesh* /*pMesh*/ ) -{ +void XFileParser::ParseDataObjectSkinMeshHeader(Mesh * /*pMesh*/) { readHeadOfDataObject(); - /*unsigned int maxSkinWeightsPerVertex =*/ ReadInt(); - /*unsigned int maxSkinWeightsPerFace =*/ ReadInt(); - /*unsigned int numBonesInMesh = */ReadInt(); + /*unsigned int maxSkinWeightsPerVertex =*/ReadInt(); + /*unsigned int maxSkinWeightsPerFace =*/ReadInt(); + /*unsigned int numBonesInMesh = */ ReadInt(); CheckForClosingBrace(); } // ------------------------------------------------------------------------------------------------ -void XFileParser::ParseDataObjectMeshNormals( Mesh* pMesh) -{ +void XFileParser::ParseDataObjectMeshNormals(Mesh *pMesh) { readHeadOfDataObject(); // read count unsigned int numNormals = ReadInt(); - pMesh->mNormals.resize( numNormals); + pMesh->mNormals.resize(numNormals); // read normal vectors - for( unsigned int a = 0; a < numNormals; ++a) { + for (unsigned int a = 0; a < numNormals; ++a) { pMesh->mNormals[a] = ReadVector3(); } // read normal indices unsigned int numFaces = ReadInt(); - if( numFaces != pMesh->mPosFaces.size()) { - ThrowException( "Normal face count does not match vertex face count."); + if (numFaces != pMesh->mPosFaces.size()) { + ThrowException("Normal face count does not match vertex face count."); } // do not crah when no face definitions are there if (numFaces > 0) { // normal face creation - pMesh->mNormFaces.resize( numFaces ); - for( unsigned int a = 0; a < numFaces; ++a ) { + pMesh->mNormFaces.resize(numFaces); + for (unsigned int a = 0; a < numFaces; ++a) { unsigned int numIndices = ReadInt(); pMesh->mNormFaces[a] = Face(); - Face& face = pMesh->mNormFaces[a]; - for( unsigned int b = 0; b < numIndices; ++b ) { - face.mIndices.push_back( ReadInt()); + Face &face = pMesh->mNormFaces[a]; + for (unsigned int b = 0; b < numIndices; ++b) { + face.mIndices.push_back(ReadInt()); } TestForSeparator(); @@ -613,51 +570,47 @@ void XFileParser::ParseDataObjectMeshNormals( Mesh* pMesh) } // ------------------------------------------------------------------------------------------------ -void XFileParser::ParseDataObjectMeshTextureCoords( Mesh* pMesh) -{ +void XFileParser::ParseDataObjectMeshTextureCoords(Mesh *pMesh) { readHeadOfDataObject(); - if( pMesh->mNumTextures + 1 > AI_MAX_NUMBER_OF_TEXTURECOORDS) - ThrowException( "Too many sets of texture coordinates"); + if (pMesh->mNumTextures + 1 > AI_MAX_NUMBER_OF_TEXTURECOORDS) + ThrowException("Too many sets of texture coordinates"); - std::vector& coords = pMesh->mTexCoords[pMesh->mNumTextures++]; + std::vector &coords = pMesh->mTexCoords[pMesh->mNumTextures++]; unsigned int numCoords = ReadInt(); - if( numCoords != pMesh->mPositions.size()) - ThrowException( "Texture coord count does not match vertex count"); + if (numCoords != pMesh->mPositions.size()) + ThrowException("Texture coord count does not match vertex count"); - coords.resize( numCoords); - for( unsigned int a = 0; a < numCoords; a++) + coords.resize(numCoords); + for (unsigned int a = 0; a < numCoords; a++) coords[a] = ReadVector2(); CheckForClosingBrace(); } // ------------------------------------------------------------------------------------------------ -void XFileParser::ParseDataObjectMeshVertexColors( Mesh* pMesh) -{ +void XFileParser::ParseDataObjectMeshVertexColors(Mesh *pMesh) { readHeadOfDataObject(); - if( pMesh->mNumColorSets + 1 > AI_MAX_NUMBER_OF_COLOR_SETS) - ThrowException( "Too many colorsets"); - std::vector& colors = pMesh->mColors[pMesh->mNumColorSets++]; + if (pMesh->mNumColorSets + 1 > AI_MAX_NUMBER_OF_COLOR_SETS) + ThrowException("Too many colorsets"); + std::vector &colors = pMesh->mColors[pMesh->mNumColorSets++]; unsigned int numColors = ReadInt(); - if( numColors != pMesh->mPositions.size()) - ThrowException( "Vertex color count does not match vertex count"); + if (numColors != pMesh->mPositions.size()) + ThrowException("Vertex color count does not match vertex count"); - colors.resize( numColors, aiColor4D( 0, 0, 0, 1)); - for( unsigned int a = 0; a < numColors; a++) - { + colors.resize(numColors, aiColor4D(0, 0, 0, 1)); + for (unsigned int a = 0; a < numColors; a++) { unsigned int index = ReadInt(); - if( index >= pMesh->mPositions.size()) - ThrowException( "Vertex color index out of bounds"); + if (index >= pMesh->mPositions.size()) + ThrowException("Vertex color index out of bounds"); colors[index] = ReadRGBA(); // HACK: (thom) Maxon Cinema XPort plugin puts a third separator here, kwxPort puts a comma. // Ignore gracefully. - if( !mIsBinaryFormat) - { + if (!mIsBinaryFormat) { FindNextNoneWhiteSpace(); - if( *mP == ';' || *mP == ',') + if (*mP == ';' || *mP == ',') mP++; } } @@ -666,68 +619,58 @@ void XFileParser::ParseDataObjectMeshVertexColors( Mesh* pMesh) } // ------------------------------------------------------------------------------------------------ -void XFileParser::ParseDataObjectMeshMaterialList( Mesh* pMesh) -{ +void XFileParser::ParseDataObjectMeshMaterialList(Mesh *pMesh) { readHeadOfDataObject(); // read material count - /*unsigned int numMaterials =*/ ReadInt(); + /*unsigned int numMaterials =*/ReadInt(); // read non triangulated face material index count unsigned int numMatIndices = ReadInt(); // some models have a material index count of 1... to be able to read them we // replicate this single material index on every face - if( numMatIndices != pMesh->mPosFaces.size() && numMatIndices != 1) - ThrowException( "Per-Face material index count does not match face count."); + if (numMatIndices != pMesh->mPosFaces.size() && numMatIndices != 1) + ThrowException("Per-Face material index count does not match face count."); // read per-face material indices - for( unsigned int a = 0; a < numMatIndices; a++) - pMesh->mFaceMaterials.push_back( ReadInt()); + for (unsigned int a = 0; a < numMatIndices; a++) + pMesh->mFaceMaterials.push_back(ReadInt()); // in version 03.02, the face indices end with two semicolons. // commented out version check, as version 03.03 exported from blender also has 2 semicolons - if( !mIsBinaryFormat) // && MajorVersion == 3 && MinorVersion <= 2) + if (!mIsBinaryFormat) // && MajorVersion == 3 && MinorVersion <= 2) { - if(mP < mEnd && *mP == ';') + if (mP < mEnd && *mP == ';') ++mP; } // if there was only a single material index, replicate it on all faces - while( pMesh->mFaceMaterials.size() < pMesh->mPosFaces.size()) - pMesh->mFaceMaterials.push_back( pMesh->mFaceMaterials.front()); + while (pMesh->mFaceMaterials.size() < pMesh->mPosFaces.size()) + pMesh->mFaceMaterials.push_back(pMesh->mFaceMaterials.front()); // read following data objects bool running = true; - while ( running ) - { + while (running) { std::string objectName = GetNextToken(); - if( objectName.size() == 0) - ThrowException( "Unexpected end of file while parsing mesh material list."); - else - if( objectName == "}") + if (objectName.size() == 0) + ThrowException("Unexpected end of file while parsing mesh material list."); + else if (objectName == "}") break; // material list finished - else - if( objectName == "{") - { + else if (objectName == "{") { // template materials std::string matName = GetNextToken(); Material material; material.mIsReference = true; material.mName = matName; - pMesh->mMaterials.push_back( material); + pMesh->mMaterials.push_back(material); CheckForClosingBrace(); // skip } - } else - if( objectName == "Material") - { - pMesh->mMaterials.push_back( Material()); - ParseDataObjectMaterial( &pMesh->mMaterials.back()); - } else - if( objectName == ";") - { + } else if (objectName == "Material") { + pMesh->mMaterials.push_back(Material()); + ParseDataObjectMaterial(&pMesh->mMaterials.back()); + } else if (objectName == ";") { // ignore - } else - { + } else { ASSIMP_LOG_WARN("Unknown data object in material list in x file"); ParseUnknownDataObject(); } @@ -735,12 +678,11 @@ void XFileParser::ParseDataObjectMeshMaterialList( Mesh* pMesh) } // ------------------------------------------------------------------------------------------------ -void XFileParser::ParseDataObjectMaterial( Material* pMaterial) -{ +void XFileParser::ParseDataObjectMaterial(Material *pMaterial) { std::string matName; - readHeadOfDataObject( &matName); - if( matName.empty()) - matName = std::string( "material") + to_string( mLineNumber ); + readHeadOfDataObject(&matName); + if (matName.empty()) + matName = std::string("material") + to_string(mLineNumber); pMaterial->mName = matName; pMaterial->mIsReference = false; @@ -752,30 +694,23 @@ void XFileParser::ParseDataObjectMaterial( Material* pMaterial) // read other data objects bool running = true; - while ( running ) - { + while (running) { std::string objectName = GetNextToken(); - if( objectName.size() == 0) - ThrowException( "Unexpected end of file while parsing mesh material"); - else - if( objectName == "}") + if (objectName.size() == 0) + ThrowException("Unexpected end of file while parsing mesh material"); + else if (objectName == "}") break; // material finished - else - if( objectName == "TextureFilename" || objectName == "TextureFileName") - { + else if (objectName == "TextureFilename" || objectName == "TextureFileName") { // some exporters write "TextureFileName" instead. std::string texname; - ParseDataObjectTextureFilename( texname); - pMaterial->mTextures.push_back( TexEntry( texname)); - } else - if( objectName == "NormalmapFilename" || objectName == "NormalmapFileName") - { + ParseDataObjectTextureFilename(texname); + pMaterial->mTextures.push_back(TexEntry(texname)); + } else if (objectName == "NormalmapFilename" || objectName == "NormalmapFileName") { // one exporter writes out the normal map in a separate filename tag std::string texname; - ParseDataObjectTextureFilename( texname); - pMaterial->mTextures.push_back( TexEntry( texname, true)); - } else - { + ParseDataObjectTextureFilename(texname); + pMaterial->mTextures.push_back(TexEntry(texname, true)); + } else { ASSIMP_LOG_WARN("Unknown data object in material in x file"); ParseUnknownDataObject(); } @@ -783,37 +718,31 @@ void XFileParser::ParseDataObjectMaterial( Material* pMaterial) } // ------------------------------------------------------------------------------------------------ -void XFileParser::ParseDataObjectAnimTicksPerSecond() -{ +void XFileParser::ParseDataObjectAnimTicksPerSecond() { readHeadOfDataObject(); mScene->mAnimTicksPerSecond = ReadInt(); CheckForClosingBrace(); } // ------------------------------------------------------------------------------------------------ -void XFileParser::ParseDataObjectAnimationSet() -{ +void XFileParser::ParseDataObjectAnimationSet() { std::string animName; - readHeadOfDataObject( &animName); + readHeadOfDataObject(&animName); - Animation* anim = new Animation; - mScene->mAnims.push_back( anim); + Animation *anim = new Animation; + mScene->mAnims.push_back(anim); anim->mName = animName; bool running = true; - while ( running ) - { + while (running) { std::string objectName = GetNextToken(); - if( objectName.length() == 0) - ThrowException( "Unexpected end of file while parsing animation set."); - else - if( objectName == "}") + if (objectName.length() == 0) + ThrowException("Unexpected end of file while parsing animation set."); + else if (objectName == "}") break; // animation set finished - else - if( objectName == "Animation") - ParseDataObjectAnimation( anim); - else - { + else if (objectName == "Animation") + ParseDataObjectAnimation(anim); + else { ASSIMP_LOG_WARN("Unknown data object in animation set in x file"); ParseUnknownDataObject(); } @@ -821,36 +750,28 @@ void XFileParser::ParseDataObjectAnimationSet() } // ------------------------------------------------------------------------------------------------ -void XFileParser::ParseDataObjectAnimation( Animation* pAnim) -{ +void XFileParser::ParseDataObjectAnimation(Animation *pAnim) { readHeadOfDataObject(); - AnimBone* banim = new AnimBone; - pAnim->mAnims.push_back( banim); + AnimBone *banim = new AnimBone; + pAnim->mAnims.push_back(banim); bool running = true; - while( running ) - { + while (running) { std::string objectName = GetNextToken(); - if( objectName.length() == 0) - ThrowException( "Unexpected end of file while parsing animation."); - else - if( objectName == "}") + if (objectName.length() == 0) + ThrowException("Unexpected end of file while parsing animation."); + else if (objectName == "}") break; // animation finished - else - if( objectName == "AnimationKey") - ParseDataObjectAnimationKey( banim); - else - if( objectName == "AnimationOptions") + else if (objectName == "AnimationKey") + ParseDataObjectAnimationKey(banim); + else if (objectName == "AnimationOptions") ParseUnknownDataObject(); // not interested - else - if( objectName == "{") - { + else if (objectName == "{") { // read frame name banim->mBoneName = GetNextToken(); CheckForClosingBrace(); - } else - { + } else { ASSIMP_LOG_WARN("Unknown data object in animation in x file"); ParseUnknownDataObject(); } @@ -858,8 +779,7 @@ void XFileParser::ParseDataObjectAnimation( Animation* pAnim) } // ------------------------------------------------------------------------------------------------ -void XFileParser::ParseDataObjectAnimationKey( AnimBone* pAnimBone) -{ +void XFileParser::ParseDataObjectAnimationKey(AnimBone *pAnimBone) { readHeadOfDataObject(); // read key type @@ -868,78 +788,84 @@ void XFileParser::ParseDataObjectAnimationKey( AnimBone* pAnimBone) // read number of keys unsigned int numKeys = ReadInt(); - for( unsigned int a = 0; a < numKeys; a++) - { + for (unsigned int a = 0; a < numKeys; a++) { // read time unsigned int time = ReadInt(); // read keys - switch( keyType) + switch (keyType) { + case 0: // rotation quaternion { - case 0: // rotation quaternion - { - // read count - if( ReadInt() != 4) - ThrowException( "Invalid number of arguments for quaternion key in animation"); + // read count + if (ReadInt() != 4) + ThrowException("Invalid number of arguments for quaternion key in animation"); - aiQuatKey key; - key.mTime = double( time); - key.mValue.w = ReadFloat(); - key.mValue.x = ReadFloat(); - key.mValue.y = ReadFloat(); - key.mValue.z = ReadFloat(); - pAnimBone->mRotKeys.push_back( key); + aiQuatKey key; + key.mTime = double(time); + key.mValue.w = ReadFloat(); + key.mValue.x = ReadFloat(); + key.mValue.y = ReadFloat(); + key.mValue.z = ReadFloat(); + pAnimBone->mRotKeys.push_back(key); - CheckForSemicolon(); - break; - } + CheckForSemicolon(); + break; + } - case 1: // scale vector - case 2: // position vector - { - // read count - if( ReadInt() != 3) - ThrowException( "Invalid number of arguments for vector key in animation"); + case 1: // scale vector + case 2: // position vector + { + // read count + if (ReadInt() != 3) + ThrowException("Invalid number of arguments for vector key in animation"); - aiVectorKey key; - key.mTime = double( time); - key.mValue = ReadVector3(); + aiVectorKey key; + key.mTime = double(time); + key.mValue = ReadVector3(); - if( keyType == 2) - pAnimBone->mPosKeys.push_back( key); - else - pAnimBone->mScaleKeys.push_back( key); + if (keyType == 2) + pAnimBone->mPosKeys.push_back(key); + else + pAnimBone->mScaleKeys.push_back(key); - break; - } + break; + } - case 3: // combined transformation matrix - case 4: // denoted both as 3 or as 4 - { - // read count - if( ReadInt() != 16) - ThrowException( "Invalid number of arguments for matrix key in animation"); + case 3: // combined transformation matrix + case 4: // denoted both as 3 or as 4 + { + // read count + if (ReadInt() != 16) + ThrowException("Invalid number of arguments for matrix key in animation"); - // read matrix - MatrixKey key; - key.mTime = double( time); - key.mMatrix.a1 = ReadFloat(); key.mMatrix.b1 = ReadFloat(); - key.mMatrix.c1 = ReadFloat(); key.mMatrix.d1 = ReadFloat(); - key.mMatrix.a2 = ReadFloat(); key.mMatrix.b2 = ReadFloat(); - key.mMatrix.c2 = ReadFloat(); key.mMatrix.d2 = ReadFloat(); - key.mMatrix.a3 = ReadFloat(); key.mMatrix.b3 = ReadFloat(); - key.mMatrix.c3 = ReadFloat(); key.mMatrix.d3 = ReadFloat(); - key.mMatrix.a4 = ReadFloat(); key.mMatrix.b4 = ReadFloat(); - key.mMatrix.c4 = ReadFloat(); key.mMatrix.d4 = ReadFloat(); - pAnimBone->mTrafoKeys.push_back( key); + // read matrix + MatrixKey key; + key.mTime = double(time); + key.mMatrix.a1 = ReadFloat(); + key.mMatrix.b1 = ReadFloat(); + key.mMatrix.c1 = ReadFloat(); + key.mMatrix.d1 = ReadFloat(); + key.mMatrix.a2 = ReadFloat(); + key.mMatrix.b2 = ReadFloat(); + key.mMatrix.c2 = ReadFloat(); + key.mMatrix.d2 = ReadFloat(); + key.mMatrix.a3 = ReadFloat(); + key.mMatrix.b3 = ReadFloat(); + key.mMatrix.c3 = ReadFloat(); + key.mMatrix.d3 = ReadFloat(); + key.mMatrix.a4 = ReadFloat(); + key.mMatrix.b4 = ReadFloat(); + key.mMatrix.c4 = ReadFloat(); + key.mMatrix.d4 = ReadFloat(); + pAnimBone->mTrafoKeys.push_back(key); - CheckForSemicolon(); - break; - } + CheckForSemicolon(); + break; + } - default: - ThrowException( format() << "Unknown key type " << keyType << " in animation." ); - break; + default: + ThrowException(format() << "Unknown key type " << keyType << " in animation."); + break; } // end switch // key separator @@ -950,115 +876,103 @@ void XFileParser::ParseDataObjectAnimationKey( AnimBone* pAnimBone) } // ------------------------------------------------------------------------------------------------ -void XFileParser::ParseDataObjectTextureFilename( std::string& pName) -{ +void XFileParser::ParseDataObjectTextureFilename(std::string &pName) { readHeadOfDataObject(); - GetNextTokenAsString( pName); + GetNextTokenAsString(pName); CheckForClosingBrace(); // FIX: some files (e.g. AnimationTest.x) have "" as texture file name - if (!pName.length()) - { + if (!pName.length()) { ASSIMP_LOG_WARN("Length of texture file name is zero. Skipping this texture."); } // some exporters write double backslash paths out. We simply replace them if we find them - while( pName.find( "\\\\") != std::string::npos) - pName.replace( pName.find( "\\\\"), 2, "\\"); + while (pName.find("\\\\") != std::string::npos) + pName.replace(pName.find("\\\\"), 2, "\\"); } // ------------------------------------------------------------------------------------------------ -void XFileParser::ParseUnknownDataObject() -{ +void XFileParser::ParseUnknownDataObject() { // find opening delimiter bool running = true; - while( running ) - { + while (running) { std::string t = GetNextToken(); - if( t.length() == 0) - ThrowException( "Unexpected end of file while parsing unknown segment."); + if (t.length() == 0) + ThrowException("Unexpected end of file while parsing unknown segment."); - if( t == "{") + if (t == "{") break; } unsigned int counter = 1; // parse until closing delimiter - while( counter > 0) - { + while (counter > 0) { std::string t = GetNextToken(); - if( t.length() == 0) - ThrowException( "Unexpected end of file while parsing unknown segment."); + if (t.length() == 0) + ThrowException("Unexpected end of file while parsing unknown segment."); - if( t == "{") + if (t == "{") ++counter; - else - if( t == "}") + else if (t == "}") --counter; } } // ------------------------------------------------------------------------------------------------ //! checks for closing curly brace -void XFileParser::CheckForClosingBrace() -{ - if( GetNextToken() != "}") - ThrowException( "Closing brace expected."); +void XFileParser::CheckForClosingBrace() { + if (GetNextToken() != "}") + ThrowException("Closing brace expected."); } // ------------------------------------------------------------------------------------------------ //! checks for one following semicolon -void XFileParser::CheckForSemicolon() -{ - if( mIsBinaryFormat) +void XFileParser::CheckForSemicolon() { + if (mIsBinaryFormat) return; - if( GetNextToken() != ";") - ThrowException( "Semicolon expected."); + if (GetNextToken() != ";") + ThrowException("Semicolon expected."); } // ------------------------------------------------------------------------------------------------ //! checks for a separator char, either a ',' or a ';' -void XFileParser::CheckForSeparator() -{ - if( mIsBinaryFormat) +void XFileParser::CheckForSeparator() { + if (mIsBinaryFormat) return; std::string token = GetNextToken(); - if( token != "," && token != ";") - ThrowException( "Separator character (';' or ',') expected."); + if (token != "," && token != ";") + ThrowException("Separator character (';' or ',') expected."); } // ------------------------------------------------------------------------------------------------ // tests and possibly consumes a separator char, but does nothing if there was no separator -void XFileParser::TestForSeparator() -{ - if( mIsBinaryFormat) - return; +void XFileParser::TestForSeparator() { + if (mIsBinaryFormat) + return; - FindNextNoneWhiteSpace(); - if( mP >= mEnd) - return; + FindNextNoneWhiteSpace(); + if (mP >= mEnd) + return; - // test and skip - if( *mP == ';' || *mP == ',') - mP++; + // test and skip + if (*mP == ';' || *mP == ',') + mP++; } // ------------------------------------------------------------------------------------------------ -void XFileParser::readHeadOfDataObject( std::string* poName) -{ +void XFileParser::readHeadOfDataObject(std::string *poName) { std::string nameOrBrace = GetNextToken(); - if( nameOrBrace != "{") - { - if( poName) + if (nameOrBrace != "{") { + if (poName) *poName = nameOrBrace; - if ( GetNextToken() != "{" ) { + if (GetNextToken() != "{") { delete mScene; - ThrowException( "Opening brace expected." ); + ThrowException("Opening brace expected."); } } } @@ -1068,157 +982,151 @@ std::string XFileParser::GetNextToken() { std::string s; // process binary-formatted file - if( mIsBinaryFormat) { + if (mIsBinaryFormat) { // in binary mode it will only return NAME and STRING token // and (correctly) skip over other tokens. - if ( mEnd - mP < 2 ) { + if (mEnd - mP < 2) { return s; } unsigned int tok = ReadBinWord(); unsigned int len; // standalone tokens - switch( tok ) { - case 1: { - // name token - if ( mEnd - mP < 4 ) { - return s; - } - len = ReadBinDWord(); - const int bounds = int( mEnd - mP ); - const int iLen = int( len ); - if ( iLen < 0 ) { - return s; - } - if ( bounds < iLen ) { - return s; - } - s = std::string( mP, len ); - mP += len; + switch (tok) { + case 1: { + // name token + if (mEnd - mP < 4) { + return s; } + len = ReadBinDWord(); + const int bounds = int(mEnd - mP); + const int iLen = int(len); + if (iLen < 0) { + return s; + } + if (bounds < iLen) { + return s; + } + s = std::string(mP, len); + mP += len; + } return s; - case 2: - // string token - if( mEnd - mP < 4) return s; - len = ReadBinDWord(); - if( mEnd - mP < int(len)) return s; - s = std::string(mP, len); - mP += (len + 2); - return s; - case 3: - // integer token - mP += 4; - return ""; - case 5: - // GUID token - mP += 16; - return ""; - case 6: - if( mEnd - mP < 4) return s; - len = ReadBinDWord(); - mP += (len * 4); - return ""; - case 7: - if( mEnd - mP < 4) return s; - len = ReadBinDWord(); - mP += (len * mBinaryFloatSize); - return ""; - case 0x0a: - return "{"; - case 0x0b: - return "}"; - case 0x0c: - return "("; - case 0x0d: - return ")"; - case 0x0e: - return "["; - case 0x0f: - return "]"; - case 0x10: - return "<"; - case 0x11: - return ">"; - case 0x12: - return "."; - case 0x13: - return ","; - case 0x14: - return ";"; - case 0x1f: - return "template"; - case 0x28: - return "WORD"; - case 0x29: - return "DWORD"; - case 0x2a: - return "FLOAT"; - case 0x2b: - return "DOUBLE"; - case 0x2c: - return "CHAR"; - case 0x2d: - return "UCHAR"; - case 0x2e: - return "SWORD"; - case 0x2f: - return "SDWORD"; - case 0x30: - return "void"; - case 0x31: - return "string"; - case 0x32: - return "unicode"; - case 0x33: - return "cstring"; - case 0x34: - return "array"; + case 2: + // string token + if (mEnd - mP < 4) return s; + len = ReadBinDWord(); + if (mEnd - mP < int(len)) return s; + s = std::string(mP, len); + mP += (len + 2); + return s; + case 3: + // integer token + mP += 4; + return ""; + case 5: + // GUID token + mP += 16; + return ""; + case 6: + if (mEnd - mP < 4) return s; + len = ReadBinDWord(); + mP += (len * 4); + return ""; + case 7: + if (mEnd - mP < 4) return s; + len = ReadBinDWord(); + mP += (len * mBinaryFloatSize); + return ""; + case 0x0a: + return "{"; + case 0x0b: + return "}"; + case 0x0c: + return "("; + case 0x0d: + return ")"; + case 0x0e: + return "["; + case 0x0f: + return "]"; + case 0x10: + return "<"; + case 0x11: + return ">"; + case 0x12: + return "."; + case 0x13: + return ","; + case 0x14: + return ";"; + case 0x1f: + return "template"; + case 0x28: + return "WORD"; + case 0x29: + return "DWORD"; + case 0x2a: + return "FLOAT"; + case 0x2b: + return "DOUBLE"; + case 0x2c: + return "CHAR"; + case 0x2d: + return "UCHAR"; + case 0x2e: + return "SWORD"; + case 0x2f: + return "SDWORD"; + case 0x30: + return "void"; + case 0x31: + return "string"; + case 0x32: + return "unicode"; + case 0x33: + return "cstring"; + case 0x34: + return "array"; } } // process text-formatted file - else - { + else { FindNextNoneWhiteSpace(); - if( mP >= mEnd) + if (mP >= mEnd) return s; - while( (mP < mEnd) && !isspace( (unsigned char) *mP)) - { + while ((mP < mEnd) && !isspace((unsigned char)*mP)) { // either keep token delimiters when already holding a token, or return if first valid char - if( *mP == ';' || *mP == '}' || *mP == '{' || *mP == ',') - { - if( !s.size()) - s.append( mP++, 1); + if (*mP == ';' || *mP == '}' || *mP == '{' || *mP == ',') { + if (!s.size()) + s.append(mP++, 1); break; // stop for delimiter } - s.append( mP++, 1); + s.append(mP++, 1); } } return s; } // ------------------------------------------------------------------------------------------------ -void XFileParser::FindNextNoneWhiteSpace() -{ - if( mIsBinaryFormat) +void XFileParser::FindNextNoneWhiteSpace() { + if (mIsBinaryFormat) return; bool running = true; - while( running ) - { - while( mP < mEnd && isspace( (unsigned char) *mP)) - { - if( *mP == '\n') + while (running) { + while (mP < mEnd && isspace((unsigned char)*mP)) { + if (*mP == '\n') mLineNumber++; ++mP; } - if( mP >= mEnd) + if (mP >= mEnd) return; // check if this is a comment - if( (mP[0] == '/' && mP[1] == '/') || mP[0] == '#') + if ((mP[0] == '/' && mP[1] == '/') || mP[0] == '#') ReadUntilEndOfLine(); else break; @@ -1226,52 +1134,48 @@ void XFileParser::FindNextNoneWhiteSpace() } // ------------------------------------------------------------------------------------------------ -void XFileParser::GetNextTokenAsString( std::string& poString) -{ - if( mIsBinaryFormat) - { +void XFileParser::GetNextTokenAsString(std::string &poString) { + if (mIsBinaryFormat) { poString = GetNextToken(); return; } FindNextNoneWhiteSpace(); - if ( mP >= mEnd ) { + if (mP >= mEnd) { delete mScene; - ThrowException( "Unexpected end of file while parsing string" ); + ThrowException("Unexpected end of file while parsing string"); } - if ( *mP != '"' ) { + if (*mP != '"') { delete mScene; - ThrowException( "Expected quotation mark." ); + ThrowException("Expected quotation mark."); } ++mP; - while( mP < mEnd && *mP != '"') - poString.append( mP++, 1); + while (mP < mEnd && *mP != '"') + poString.append(mP++, 1); - if ( mP >= mEnd - 1 ) { + if (mP >= mEnd - 1) { delete mScene; - ThrowException( "Unexpected end of file while parsing string" ); + ThrowException("Unexpected end of file while parsing string"); } - if ( mP[ 1 ] != ';' || mP[ 0 ] != '"' ) { + if (mP[1] != ';' || mP[0] != '"') { delete mScene; - ThrowException( "Expected quotation mark and semicolon at the end of a string." ); + ThrowException("Expected quotation mark and semicolon at the end of a string."); } - mP+=2; + mP += 2; } // ------------------------------------------------------------------------------------------------ -void XFileParser::ReadUntilEndOfLine() -{ - if( mIsBinaryFormat) +void XFileParser::ReadUntilEndOfLine() { + if (mIsBinaryFormat) return; - while( mP < mEnd) - { - if( *mP == '\n' || *mP == '\r') - { - ++mP; mLineNumber++; + while (mP < mEnd) { + if (*mP == '\n' || *mP == '\r') { + ++mP; + mLineNumber++; return; } @@ -1280,10 +1184,9 @@ void XFileParser::ReadUntilEndOfLine() } // ------------------------------------------------------------------------------------------------ -unsigned short XFileParser::ReadBinWord() -{ +unsigned short XFileParser::ReadBinWord() { ai_assert(mEnd - mP >= 2); - const unsigned char* q = (const unsigned char*) mP; + const unsigned char *q = (const unsigned char *)mP; unsigned short tmp = q[0] | (q[1] << 8); mP += 2; return tmp; @@ -1293,57 +1196,51 @@ unsigned short XFileParser::ReadBinWord() unsigned int XFileParser::ReadBinDWord() { ai_assert(mEnd - mP >= 4); - const unsigned char* q = (const unsigned char*) mP; + const unsigned char *q = (const unsigned char *)mP; unsigned int tmp = q[0] | (q[1] << 8) | (q[2] << 16) | (q[3] << 24); mP += 4; return tmp; } // ------------------------------------------------------------------------------------------------ -unsigned int XFileParser::ReadInt() -{ - if( mIsBinaryFormat) - { - if( mBinaryNumCount == 0 && mEnd - mP >= 2) - { +unsigned int XFileParser::ReadInt() { + if (mIsBinaryFormat) { + if (mBinaryNumCount == 0 && mEnd - mP >= 2) { unsigned short tmp = ReadBinWord(); // 0x06 or 0x03 - if( tmp == 0x06 && mEnd - mP >= 4) // array of ints follows + if (tmp == 0x06 && mEnd - mP >= 4) // array of ints follows mBinaryNumCount = ReadBinDWord(); else // single int follows mBinaryNumCount = 1; } --mBinaryNumCount; - const size_t len( mEnd - mP ); - if ( len >= 4) { + const size_t len(mEnd - mP); + if (len >= 4) { return ReadBinDWord(); } else { mP = mEnd; return 0; } - } else - { + } else { FindNextNoneWhiteSpace(); // TODO: consider using strtol10 instead??? // check preceding minus sign bool isNegative = false; - if( *mP == '-') - { + if (*mP == '-') { isNegative = true; mP++; } // at least one digit expected - if( !isdigit( *mP)) - ThrowException( "Number expected."); + if (!isdigit(*mP)) + ThrowException("Number expected."); // read digits unsigned int number = 0; - while( mP < mEnd) - { - if( !isdigit( *mP)) + while (mP < mEnd) { + if (!isdigit(*mP)) break; number = number * 10 + (*mP - 48); mP++; @@ -1351,40 +1248,37 @@ unsigned int XFileParser::ReadInt() CheckForSeparator(); - return isNegative ? ((unsigned int) -int( number)) : number; + return isNegative ? ((unsigned int)-int(number)) : number; } } // ------------------------------------------------------------------------------------------------ -ai_real XFileParser::ReadFloat() -{ - if( mIsBinaryFormat) - { - if( mBinaryNumCount == 0 && mEnd - mP >= 2) - { +ai_real XFileParser::ReadFloat() { + if (mIsBinaryFormat) { + if (mBinaryNumCount == 0 && mEnd - mP >= 2) { unsigned short tmp = ReadBinWord(); // 0x07 or 0x42 - if( tmp == 0x07 && mEnd - mP >= 4) // array of floats following + if (tmp == 0x07 && mEnd - mP >= 4) // array of floats following mBinaryNumCount = ReadBinDWord(); else // single float following mBinaryNumCount = 1; } --mBinaryNumCount; - if( mBinaryFloatSize == 8) { - if( mEnd - mP >= 8) { + if (mBinaryFloatSize == 8) { + if (mEnd - mP >= 8) { double res; - ::memcpy( &res, mP, 8 ); + ::memcpy(&res, mP, 8); mP += 8; - const ai_real result( static_cast( res ) ); + const ai_real result(static_cast(res)); return result; } else { mP = mEnd; return 0; } } else { - if( mEnd - mP >= 4) { + if (mEnd - mP >= 4) { ai_real result; - ::memcpy( &result, mP, 4 ); + ::memcpy(&result, mP, 4); mP += 4; return result; } else { @@ -1399,21 +1293,18 @@ ai_real XFileParser::ReadFloat() // check for various special strings to allow reading files from faulty exporters // I mean you, Blender! // Reading is safe because of the terminating zero - if( strncmp( mP, "-1.#IND00", 9) == 0 || strncmp( mP, "1.#IND00", 8) == 0) - { + if (strncmp(mP, "-1.#IND00", 9) == 0 || strncmp(mP, "1.#IND00", 8) == 0) { mP += 9; CheckForSeparator(); return 0.0; - } else - if( strncmp( mP, "1.#QNAN0", 8) == 0) - { + } else if (strncmp(mP, "1.#QNAN0", 8) == 0) { mP += 8; CheckForSeparator(); return 0.0; } ai_real result = 0.0; - mP = fast_atoreal_move( mP, result); + mP = fast_atoreal_move(mP, result); CheckForSeparator(); @@ -1421,8 +1312,7 @@ ai_real XFileParser::ReadFloat() } // ------------------------------------------------------------------------------------------------ -aiVector2D XFileParser::ReadVector2() -{ +aiVector2D XFileParser::ReadVector2() { aiVector2D vector; vector.x = ReadFloat(); vector.y = ReadFloat(); @@ -1432,8 +1322,7 @@ aiVector2D XFileParser::ReadVector2() } // ------------------------------------------------------------------------------------------------ -aiVector3D XFileParser::ReadVector3() -{ +aiVector3D XFileParser::ReadVector3() { aiVector3D vector; vector.x = ReadFloat(); vector.y = ReadFloat(); @@ -1444,8 +1333,7 @@ aiVector3D XFileParser::ReadVector3() } // ------------------------------------------------------------------------------------------------ -aiColor4D XFileParser::ReadRGBA() -{ +aiColor4D XFileParser::ReadRGBA() { aiColor4D color; color.r = ReadFloat(); color.g = ReadFloat(); @@ -1457,8 +1345,7 @@ aiColor4D XFileParser::ReadRGBA() } // ------------------------------------------------------------------------------------------------ -aiColor3D XFileParser::ReadRGB() -{ +aiColor3D XFileParser::ReadRGB() { aiColor3D color; color.r = ReadFloat(); color.g = ReadFloat(); @@ -1470,29 +1357,26 @@ aiColor3D XFileParser::ReadRGB() // ------------------------------------------------------------------------------------------------ // Throws an exception with a line number and the given text. -AI_WONT_RETURN void XFileParser::ThrowException( const std::string& pText) { - if ( mIsBinaryFormat ) { - throw DeadlyImportError( pText ); +AI_WONT_RETURN void XFileParser::ThrowException(const std::string &pText) { + if (mIsBinaryFormat) { + throw DeadlyImportError(pText); } else { - throw DeadlyImportError( format() << "Line " << mLineNumber << ": " << pText ); + throw DeadlyImportError(format() << "Line " << mLineNumber << ": " << pText); } } // ------------------------------------------------------------------------------------------------ // Filters the imported hierarchy for some degenerated cases that some exporters produce. -void XFileParser::FilterHierarchy( XFile::Node* pNode) -{ +void XFileParser::FilterHierarchy(XFile::Node *pNode) { // if the node has just a single unnamed child containing a mesh, remove // the anonymous node between. The 3DSMax kwXport plugin seems to produce this // mess in some cases - if( pNode->mChildren.size() == 1 && pNode->mMeshes.empty() ) - { - XFile::Node* child = pNode->mChildren.front(); - if( child->mName.length() == 0 && child->mMeshes.size() > 0) - { + if (pNode->mChildren.size() == 1 && pNode->mMeshes.empty()) { + XFile::Node *child = pNode->mChildren.front(); + if (child->mName.length() == 0 && child->mMeshes.size() > 0) { // transfer its meshes to us - for( unsigned int a = 0; a < child->mMeshes.size(); a++) - pNode->mMeshes.push_back( child->mMeshes[a]); + for (unsigned int a = 0; a < child->mMeshes.size(); a++) + pNode->mMeshes.push_back(child->mMeshes[a]); child->mMeshes.clear(); // transfer the transform as well @@ -1505,8 +1389,8 @@ void XFileParser::FilterHierarchy( XFile::Node* pNode) } // recurse - for( unsigned int a = 0; a < pNode->mChildren.size(); a++) - FilterHierarchy( pNode->mChildren[a]); + for (unsigned int a = 0; a < pNode->mChildren.size(); a++) + FilterHierarchy(pNode->mChildren[a]); } #endif // !! ASSIMP_BUILD_NO_X_IMPORTER diff --git a/code/AssetLib/X/XFileParser.h b/code/AssetLib/X/XFileParser.h index ea7aca266..41abe2286 100644 --- a/code/AssetLib/X/XFileParser.h +++ b/code/AssetLib/X/XFileParser.h @@ -104,7 +104,7 @@ protected: //! reads header of data object including the opening brace. //! returns false if error happened, and writes name of object //! if there is one - void readHeadOfDataObject( std::string* poName = NULL); + void readHeadOfDataObject(std::string *poName = nullptr); //! checks for closing curly brace, throws exception if not there void CheckForClosingBrace(); diff --git a/code/AssetLib/X3D/X3DImporter_Shape.cpp b/code/AssetLib/X3D/X3DImporter_Shape.cpp index 189ed145d..a77b0d20c 100644 --- a/code/AssetLib/X3D/X3DImporter_Shape.cpp +++ b/code/AssetLib/X3D/X3DImporter_Shape.cpp @@ -64,8 +64,8 @@ namespace Assimp // A ProtoInstance node (with the proper node type) can be substituted for any node in this content model." // // A Shape node is unlit if either of the following is true: -// The shape's appearance field is NULL (default). -// The material field in the Appearance node is NULL (default). +// The shape's appearance field is nullptr (default). +// The material field in the Appearance node is nullptr (default). // NOTE Geometry nodes that represent lines or points do not support lighting. void X3DImporter::ParseNode_Shape_Shape() { diff --git a/code/AssetLib/XGL/XGLLoader.cpp b/code/AssetLib/XGL/XGLLoader.cpp index 93c3b559c..fe5fff3c1 100644 --- a/code/AssetLib/XGL/XGLLoader.cpp +++ b/code/AssetLib/XGL/XGLLoader.cpp @@ -71,8 +71,13 @@ using namespace Assimp; namespace Assimp { // this has to be in here because LogFunctions is in ::Assimp template <> const char *LogFunctions::Prefix() { +<<<<<<< HEAD static auto prefix = "XGL: "; return prefix; +======= + static auto prefix = "XGL: "; + return prefix; +>>>>>>> master } } // namespace Assimp @@ -92,8 +97,13 @@ static const aiImporterDesc desc = { // ------------------------------------------------------------------------------------------------ // Constructor to be privately used by Importer XGLImporter::XGLImporter() : +<<<<<<< HEAD m_xmlParser(nullptr), m_scene(nullptr) { // empty +======= + m_reader(nullptr), m_scene(nullptr) { + // empty +>>>>>>> master } // ------------------------------------------------------------------------------------------------ @@ -105,13 +115,18 @@ XGLImporter::~XGLImporter() { // ------------------------------------------------------------------------------------------------ // Returns whether the class can handle the format of the given file. bool XGLImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const { +<<<<<<< HEAD /* NOTE: A simple check for the file extension is not enough +======= + /* NOTE: A simple check for the file extension is not enough +>>>>>>> master * here. XGL and ZGL are ok, but xml is too generic * and might be collada as well. So open the file and * look for typical signal tokens. */ const std::string extension = GetExtension(pFile); +<<<<<<< HEAD if (extension == "xgl" || extension == "zgl") { return true; } else if (extension == "xml" || checkSig) { @@ -121,22 +136,42 @@ bool XGLImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool c return SearchFileHeaderForToken(pIOHandler, pFile, tokens, 3); } return false; +======= + if (extension == "xgl" || extension == "zgl") { + return true; + } else if (extension == "xml" || checkSig) { + ai_assert(pIOHandler != nullptr); + + const char *tokens[] = { "", "", "" }; + return SearchFileHeaderForToken(pIOHandler, pFile, tokens, 3); + } + return false; +>>>>>>> master } // ------------------------------------------------------------------------------------------------ // Get a list of all file extensions which are handled by this class const aiImporterDesc *XGLImporter::GetInfo() const { +<<<<<<< HEAD return &desc; +======= + return &desc; +>>>>>>> master } // ------------------------------------------------------------------------------------------------ // Imports the given file into the given scene structure. void XGLImporter::InternReadFile(const std::string &pFile, +<<<<<<< HEAD aiScene *pScene, IOSystem *pIOHandler) { +======= + aiScene *pScene, IOSystem *pIOHandler) { +>>>>>>> master #ifndef ASSIMP_BUILD_NO_COMPRESSED_XGL std::vector uncompressed; #endif +<<<<<<< HEAD m_scene = pScene; std::shared_ptr stream(pIOHandler->Open(pFile, "rb")); @@ -144,12 +179,22 @@ void XGLImporter::InternReadFile(const std::string &pFile, if (stream.get() == NULL) { throw DeadlyImportError("Failed to open XGL/ZGL file " + pFile + ""); } +======= + m_scene = pScene; + std::shared_ptr stream(pIOHandler->Open(pFile, "rb")); + + // check whether we can read from the file + if (stream.get() == nullptr) { + throw DeadlyImportError("Failed to open XGL/ZGL file " + pFile + ""); + } +>>>>>>> master // see if its compressed, if so uncompress it if (GetExtension(pFile) == "zgl") { #ifdef ASSIMP_BUILD_NO_COMPRESSED_XGL ThrowException("Cannot read ZGL file since Assimp was built without compression support"); #else +<<<<<<< HEAD std::unique_ptr raw_reader(new StreamReaderLE(stream)); // build a zlib stream @@ -214,10 +259,69 @@ void XGLImporter::InternReadFile(const std::string &pFile, /* while (ReadElement()) { if (!ASSIMP_stricmp(m_reader->getNodeName(),"world")) { +======= + std::unique_ptr raw_reader(new StreamReaderLE(stream)); + + // build a zlib stream + z_stream zstream; + zstream.opaque = Z_NULL; + zstream.zalloc = Z_NULL; + zstream.zfree = Z_NULL; + zstream.data_type = Z_BINARY; + + // raw decompression without a zlib or gzip header + inflateInit2(&zstream, -MAX_WBITS); + + // skip two extra bytes, zgl files do carry a crc16 upfront (I think) + raw_reader->IncPtr(2); + + zstream.next_in = reinterpret_cast(raw_reader->GetPtr()); + zstream.avail_in = (uInt)raw_reader->GetRemainingSize(); + + size_t total = 0l; + + // TODO: be smarter about this, decompress directly into heap buffer + // and decompress the data .... do 1k chunks in the hope that we won't kill the stack +#define MYBLOCK 1024 + Bytef block[MYBLOCK]; + int ret; + do { + zstream.avail_out = MYBLOCK; + zstream.next_out = block; + ret = inflate(&zstream, Z_NO_FLUSH); + + if (ret != Z_STREAM_END && ret != Z_OK) { + ThrowException("Failure decompressing this file using gzip, seemingly it is NOT a compressed .XGL file"); + } + const size_t have = MYBLOCK - zstream.avail_out; + total += have; + uncompressed.resize(total); + memcpy(uncompressed.data() + total - have, block, have); + } while (ret != Z_STREAM_END); + + // terminate zlib + inflateEnd(&zstream); + + // replace the input stream with a memory stream + stream.reset(new MemoryIOStream(reinterpret_cast(uncompressed.data()), total)); +#endif + } + + // construct the irrXML parser + CIrrXML_IOStreamReader st(stream.get()); + m_reader.reset(createIrrXMLReader((IFileReadCallBack *)&st)); + + // parse the XML file + TempScope scope; + + while (ReadElement()) { + if (!ASSIMP_stricmp(m_reader->getNodeName(), "world")) { +>>>>>>> master ReadWorld(scope); } }*/ +<<<<<<< HEAD std::vector &meshes = scope.meshes_linear; std::vector &materials = scope.materials_linear; if (!meshes.size() || !materials.size()) { @@ -238,6 +342,28 @@ void XGLImporter::InternReadFile(const std::string &pFile, m_scene->mNumLights = 1; m_scene->mLights = new aiLight *[1]; m_scene->mLights[0] = scope.light; +======= + std::vector &meshes = scope.meshes_linear; + std::vector &materials = scope.materials_linear; + if (!meshes.size() || !materials.size()) { + ThrowException("failed to extract data from XGL file, no meshes loaded"); + } + + // copy meshes + m_scene->mNumMeshes = static_cast(meshes.size()); + m_scene->mMeshes = new aiMesh *[m_scene->mNumMeshes](); + std::copy(meshes.begin(), meshes.end(), m_scene->mMeshes); + + // copy materials + m_scene->mNumMaterials = static_cast(materials.size()); + m_scene->mMaterials = new aiMaterial *[m_scene->mNumMaterials](); + std::copy(materials.begin(), materials.end(), m_scene->mMaterials); + + if (scope.light) { + m_scene->mNumLights = 1; + m_scene->mLights = new aiLight *[1]; + m_scene->mLights[0] = scope.light; +>>>>>>> master scope.light->mName = m_scene->mRootNode->mName; } @@ -246,6 +372,7 @@ void XGLImporter::InternReadFile(const std::string &pFile, } // ------------------------------------------------------------------------------------------------ +<<<<<<< HEAD void XGLImporter::ReadWorld(TempScope &scope) { XmlNode *root = m_xmlParser->getRootNode(); for (XmlNode &node : root->children()) { @@ -422,6 +549,223 @@ aiMatrix4x4 XGLImporter::ReadTrafo(XmlNode &node) { if (forward.SquareLength() < 1e-4 || up.SquareLength() < 1e-4) { LogError("A direction vector in is zero, ignoring trafo"); return m; +======= +bool XGLImporter::ReadElement() { + while (m_reader->read()) { + if (m_reader->getNodeType() == EXN_ELEMENT) { + return true; + } + } + return false; +} + +// ------------------------------------------------------------------------------------------------ +bool XGLImporter::ReadElementUpToClosing(const char *closetag) { + while (m_reader->read()) { + if (m_reader->getNodeType() == EXN_ELEMENT) { + return true; + } else if (m_reader->getNodeType() == EXN_ELEMENT_END && !ASSIMP_stricmp(m_reader->getNodeName(), closetag)) { + return false; + } + } + LogError("unexpected EOF, expected closing <" + std::string(closetag) + "> tag"); + return false; +} + +// ------------------------------------------------------------------------------------------------ +bool XGLImporter::SkipToText() { + while (m_reader->read()) { + if (m_reader->getNodeType() == EXN_TEXT) { + return true; + } else if (m_reader->getNodeType() == EXN_ELEMENT || m_reader->getNodeType() == EXN_ELEMENT_END) { + ThrowException("expected text contents but found another element (or element end)"); + } + } + return false; +} + +// ------------------------------------------------------------------------------------------------ +std::string XGLImporter::GetElementName() { + const char *s = m_reader->getNodeName(); + size_t len = strlen(s); + + std::string ret; + ret.resize(len); + std::transform(s, s + len, ret.begin(), ::ToLower); + return ret; +} + +// ------------------------------------------------------------------------------------------------ +void XGLImporter::ReadWorld(TempScope &scope) { + while (ReadElementUpToClosing("world")) { + const std::string &s = GetElementName(); + // XXX right now we'd skip if it comes after + // or + if (s == "lighting") { + ReadLighting(scope); + } else if (s == "object" || s == "mesh" || s == "mat") { + break; + } + } + + aiNode *const nd = ReadObject(scope, true, "world"); + if (!nd) { + ThrowException("failure reading "); + } + if (!nd->mName.length) { + nd->mName.Set("WORLD"); + } + + m_scene->mRootNode = nd; +} + +// ------------------------------------------------------------------------------------------------ +void XGLImporter::ReadLighting(TempScope &scope) { + while (ReadElementUpToClosing("lighting")) { + const std::string &s = GetElementName(); + if (s == "directionallight") { + scope.light = ReadDirectionalLight(); + } else if (s == "ambient") { + LogWarn("ignoring tag"); + } else if (s == "spheremap") { + LogWarn("ignoring tag"); + } + } +} + +// ------------------------------------------------------------------------------------------------ +aiLight *XGLImporter::ReadDirectionalLight() { + std::unique_ptr l(new aiLight()); + l->mType = aiLightSource_DIRECTIONAL; + + while (ReadElementUpToClosing("directionallight")) { + const std::string &s = GetElementName(); + if (s == "direction") { + l->mDirection = ReadVec3(); + } else if (s == "diffuse") { + l->mColorDiffuse = ReadCol3(); + } else if (s == "specular") { + l->mColorSpecular = ReadCol3(); + } + } + return l.release(); +} + +// ------------------------------------------------------------------------------------------------ +aiNode *XGLImporter::ReadObject(TempScope &scope, bool skipFirst, const char *closetag) { + aiNode *nd = new aiNode; + std::vector children; + std::vector meshes; + + try { + while (skipFirst || ReadElementUpToClosing(closetag)) { + skipFirst = false; + + const std::string &s = GetElementName(); + if (s == "mesh") { + const size_t prev = scope.meshes_linear.size(); + if (ReadMesh(scope)) { + const size_t newc = scope.meshes_linear.size(); + for (size_t i = 0; i < newc - prev; ++i) { + meshes.push_back(static_cast(i + prev)); + } + } + } else if (s == "mat") { + ReadMaterial(scope); + } else if (s == "object") { + children.push_back(ReadObject(scope)); + } else if (s == "objectref") { + // XXX + } else if (s == "meshref") { + const unsigned int id = static_cast(ReadIndexFromText()); + + std::multimap::iterator it = scope.meshes.find(id), end = scope.meshes.end(); + if (it == end) { + ThrowException(" index out of range"); + } + + for (; it != end && (*it).first == id; ++it) { + // ok, this is n^2 and should get optimized one day + aiMesh *const m = (*it).second; + + unsigned int i = 0, mcount = static_cast(scope.meshes_linear.size()); + for (; i < mcount; ++i) { + if (scope.meshes_linear[i] == m) { + meshes.push_back(i); + break; + } + } + + ai_assert(i < mcount); + } + } else if (s == "transform") { + nd->mTransformation = ReadTrafo(); + } + } + + } catch (...) { + for (aiNode *ch : children) { + delete ch; + } + throw; + } + + // FIX: since we used std::multimap<> to keep meshes by id, mesh order now depends on the behaviour + // of the multimap implementation with respect to the ordering of entries with same values. + // C++11 gives the guarantee that it uses insertion order, before it is implementation-specific. + // Sort by material id to always guarantee a deterministic result. + std::sort(meshes.begin(), meshes.end(), SortMeshByMaterialId(scope)); + + // link meshes to node + nd->mNumMeshes = static_cast(meshes.size()); + if (nd->mNumMeshes) { + nd->mMeshes = new unsigned int[nd->mNumMeshes](); + for (unsigned int i = 0; i < nd->mNumMeshes; ++i) { + nd->mMeshes[i] = meshes[i]; + } + } + + // link children to parent + nd->mNumChildren = static_cast(children.size()); + if (nd->mNumChildren) { + nd->mChildren = new aiNode *[nd->mNumChildren](); + for (unsigned int i = 0; i < nd->mNumChildren; ++i) { + nd->mChildren[i] = children[i]; + children[i]->mParent = nd; + } + } + + return nd; +} + +// ------------------------------------------------------------------------------------------------ +aiMatrix4x4 XGLImporter::ReadTrafo() { + aiVector3D forward, up, right, position; + float scale = 1.0f; + + while (ReadElementUpToClosing("transform")) { + const std::string &s = GetElementName(); + if (s == "forward") { + forward = ReadVec3(); + } else if (s == "up") { + up = ReadVec3(); + } else if (s == "position") { + position = ReadVec3(); + } + if (s == "scale") { + scale = ReadFloat(); + if (scale < 0.f) { + // this is wrong, but we can leave the value and pass it to the caller + LogError("found negative scaling in , ignoring"); + } + } + } + + aiMatrix4x4 m; + if (forward.SquareLength() < 1e-4 || up.SquareLength() < 1e-4) { + LogError("A direction vector in is zero, ignoring trafo"); + return m; +>>>>>>> master } forward.Normalize(); @@ -460,6 +804,7 @@ aiMatrix4x4 XGLImporter::ReadTrafo(XmlNode &node) { // ------------------------------------------------------------------------------------------------ aiMesh *XGLImporter::ToOutputMesh(const TempMaterialMesh &m) { +<<<<<<< HEAD std::unique_ptr mesh(new aiMesh()); mesh->mNumVertices = static_cast(m.positions.size()); @@ -494,6 +839,40 @@ aiMesh *XGLImporter::ToOutputMesh(const TempMaterialMesh &m) { } ai_assert(idx == mesh->mNumVertices); +======= + std::unique_ptr mesh(new aiMesh()); + + mesh->mNumVertices = static_cast(m.positions.size()); + mesh->mVertices = new aiVector3D[mesh->mNumVertices]; + std::copy(m.positions.begin(), m.positions.end(), mesh->mVertices); + + if (m.normals.size()) { + mesh->mNormals = new aiVector3D[mesh->mNumVertices]; + std::copy(m.normals.begin(), m.normals.end(), mesh->mNormals); + } + + if (m.uvs.size()) { + mesh->mNumUVComponents[0] = 2; + mesh->mTextureCoords[0] = new aiVector3D[mesh->mNumVertices]; + + for (unsigned int i = 0; i < mesh->mNumVertices; ++i) { + mesh->mTextureCoords[0][i] = aiVector3D(m.uvs[i].x, m.uvs[i].y, 0.f); + } + } + + mesh->mNumFaces = static_cast(m.vcounts.size()); + mesh->mFaces = new aiFace[m.vcounts.size()]; + + unsigned int idx = 0; + for (unsigned int i = 0; i < mesh->mNumFaces; ++i) { + aiFace &f = mesh->mFaces[i]; + f.mNumIndices = m.vcounts[i]; + f.mIndices = new unsigned int[f.mNumIndices]; + for (unsigned int c = 0; c < f.mNumIndices; ++c) { + f.mIndices[c] = idx++; + } + } +>>>>>>> master mesh->mPrimitiveTypes = m.pflags; mesh->mMaterialIndex = m.matid; @@ -502,6 +881,7 @@ aiMesh *XGLImporter::ToOutputMesh(const TempMaterialMesh &m) { } // ------------------------------------------------------------------------------------------------ +<<<<<<< HEAD bool XGLImporter::ReadMesh(XmlNode &node, TempScope &scope) { TempMesh t; @@ -629,9 +1009,137 @@ unsigned int XGLImporter::ResolveMaterialRef(XmlNode &node, TempScope &scope) { ReadMaterial(node, scope); return static_cast(scope.materials_linear.size() - 1); } +======= +bool XGLImporter::ReadMesh(TempScope &scope) { + TempMesh t; + + std::map bymat; + const unsigned int mesh_id = ReadIDAttr(); + + while (ReadElementUpToClosing("mesh")) { + const std::string &s = GetElementName(); + + if (s == "mat") { + ReadMaterial(scope); + } else if (s == "p") { + if (!m_reader->getAttributeValue("ID")) { + LogWarn("no ID attribute on

, ignoring"); + } else { + int id = m_reader->getAttributeValueAsInt("ID"); + t.points[id] = ReadVec3(); + } + } else if (s == "n") { + if (!m_reader->getAttributeValue("ID")) { + LogWarn("no ID attribute on , ignoring"); + } else { + int id = m_reader->getAttributeValueAsInt("ID"); + t.normals[id] = ReadVec3(); + } + } else if (s == "tc") { + if (!m_reader->getAttributeValue("ID")) { + LogWarn("no ID attribute on , ignoring"); + } else { + int id = m_reader->getAttributeValueAsInt("ID"); + t.uvs[id] = ReadVec2(); + } + } else if (s == "f" || s == "l" || s == "p") { + const unsigned int vcount = s == "f" ? 3 : (s == "l" ? 2 : 1); + + unsigned int mid = ~0u; + TempFace tf[3]; + bool has[3] = { 0 }; + + while (ReadElementUpToClosing(s.c_str())) { + const std::string &elemName = GetElementName(); + if (elemName == "fv1" || elemName == "lv1" || elemName == "pv1") { + ReadFaceVertex(t, tf[0]); + has[0] = true; + } else if (elemName == "fv2" || elemName == "lv2") { + ReadFaceVertex(t, tf[1]); + has[1] = true; + } else if (elemName == "fv3") { + ReadFaceVertex(t, tf[2]); + has[2] = true; + } else if (elemName == "mat") { + if (mid != ~0u) { + LogWarn("only one material tag allowed per "); + } + mid = ResolveMaterialRef(scope); + } else if (elemName == "matref") { + if (mid != ~0u) { + LogWarn("only one material tag allowed per "); + } + mid = ResolveMaterialRef(scope); + } + } + + if (mid == ~0u) { + ThrowException("missing material index"); + } + + bool nor = false; + bool uv = false; + for (unsigned int i = 0; i < vcount; ++i) { + if (!has[i]) { + ThrowException("missing face vertex data"); + } + + nor = nor || tf[i].has_normal; + uv = uv || tf[i].has_uv; + } + + if (mid >= (1 << 30)) { + LogWarn("material indices exhausted, this may cause errors in the output"); + } + unsigned int meshId = mid | ((nor ? 1 : 0) << 31) | ((uv ? 1 : 0) << 30); + + TempMaterialMesh &mesh = bymat[meshId]; + mesh.matid = mid; + + for (unsigned int i = 0; i < vcount; ++i) { + mesh.positions.push_back(tf[i].pos); + if (nor) { + mesh.normals.push_back(tf[i].normal); + } + if (uv) { + mesh.uvs.push_back(tf[i].uv); + } + + mesh.pflags |= 1 << (vcount - 1); + } + + mesh.vcounts.push_back(vcount); + } + } + + // finally extract output meshes and add them to the scope + typedef std::pair pairt; + for (const pairt &p : bymat) { + aiMesh *const m = ToOutputMesh(p.second); + scope.meshes_linear.push_back(m); + + // if this is a definition, keep it on the stack + if (mesh_id != ~0u) { + scope.meshes.insert(std::pair(mesh_id, m)); + } + } + + // no id == not a reference, insert this mesh right *here* + return mesh_id == ~0u; +} + +// ---------------------------------------------------------------------------------------------- +unsigned int XGLImporter::ResolveMaterialRef(TempScope &scope) { + const std::string &s = GetElementName(); + if (s == "mat") { + ReadMaterial(scope); + return static_cast(scope.materials_linear.size() - 1); + } +>>>>>>> master const int id = ReadIndexFromText(node); +<<<<<<< HEAD std::map::iterator it = scope.materials.find(id), end = scope.materials.end(); if (it == end) { ThrowException(" index out of range"); @@ -648,11 +1156,28 @@ unsigned int XGLImporter::ResolveMaterialRef(XmlNode &node, TempScope &scope) { } ai_assert(false); +======= + std::map::iterator it = scope.materials.find(id), end = scope.materials.end(); + if (it == end) { + ThrowException(" index out of range"); + } + + // ok, this is n^2 and should get optimized one day + aiMaterial *const m = (*it).second; + + unsigned int i = 0, mcount = static_cast(scope.materials_linear.size()); + for (; i < mcount; ++i) { + if (scope.materials_linear[i] == m) { + return i; + } + } +>>>>>>> master return 0; } // ------------------------------------------------------------------------------------------------ +<<<<<<< HEAD void XGLImporter::ReadMaterial(XmlNode &node, TempScope &scope) { const unsigned int mat_id = ReadIDAttr(node); @@ -801,11 +1326,178 @@ aiVector2D XGLImporter::ReadVec2(XmlNode &node) { } vec.x = v[0]; vec.y = v[1]; +======= +void XGLImporter::ReadMaterial(TempScope &scope) { + const unsigned int mat_id = ReadIDAttr(); + + aiMaterial *mat(new aiMaterial); + while (ReadElementUpToClosing("mat")) { + const std::string &s = GetElementName(); + if (s == "amb") { + const aiColor3D c = ReadCol3(); + mat->AddProperty(&c, 1, AI_MATKEY_COLOR_AMBIENT); + } else if (s == "diff") { + const aiColor3D c = ReadCol3(); + mat->AddProperty(&c, 1, AI_MATKEY_COLOR_DIFFUSE); + } else if (s == "spec") { + const aiColor3D c = ReadCol3(); + mat->AddProperty(&c, 1, AI_MATKEY_COLOR_SPECULAR); + } else if (s == "emiss") { + const aiColor3D c = ReadCol3(); + mat->AddProperty(&c, 1, AI_MATKEY_COLOR_EMISSIVE); + } else if (s == "alpha") { + const float f = ReadFloat(); + mat->AddProperty(&f, 1, AI_MATKEY_OPACITY); + } else if (s == "shine") { + const float f = ReadFloat(); + mat->AddProperty(&f, 1, AI_MATKEY_SHININESS); + } + } + + scope.materials[mat_id] = mat; + scope.materials_linear.push_back(mat); +} + +// ---------------------------------------------------------------------------------------------- +void XGLImporter::ReadFaceVertex(const TempMesh &t, TempFace &out) { + const std::string &end = GetElementName(); + + bool havep = false; + while (ReadElementUpToClosing(end.c_str())) { + const std::string &s = GetElementName(); + if (s == "pref") { + const unsigned int id = ReadIndexFromText(); + std::map::const_iterator it = t.points.find(id); + if (it == t.points.end()) { + ThrowException("point index out of range"); + } + + out.pos = (*it).second; + havep = true; + } else if (s == "nref") { + const unsigned int id = ReadIndexFromText(); + std::map::const_iterator it = t.normals.find(id); + if (it == t.normals.end()) { + ThrowException("normal index out of range"); + } + + out.normal = (*it).second; + out.has_normal = true; + } else if (s == "tcref") { + const unsigned int id = ReadIndexFromText(); + std::map::const_iterator it = t.uvs.find(id); + if (it == t.uvs.end()) { + ThrowException("uv index out of range"); + } + + out.uv = (*it).second; + out.has_uv = true; + } else if (s == "p") { + out.pos = ReadVec3(); + } else if (s == "n") { + out.normal = ReadVec3(); + } else if (s == "tc") { + out.uv = ReadVec2(); + } + } + + if (!havep) { + ThrowException("missing in element"); + } +} + +// ------------------------------------------------------------------------------------------------ +unsigned int XGLImporter::ReadIDAttr() { + for (int i = 0, e = m_reader->getAttributeCount(); i < e; ++i) { + + if (!ASSIMP_stricmp(m_reader->getAttributeName(i), "id")) { + return m_reader->getAttributeValueAsInt(i); + } + } + return ~0u; +} + +// ------------------------------------------------------------------------------------------------ +float XGLImporter::ReadFloat() { + if (!SkipToText()) { + LogError("unexpected EOF reading float element contents"); + return 0.f; + } + const char *s = m_reader->getNodeData(), *se; + + if (!SkipSpaces(&s)) { + LogError("unexpected EOL, failed to parse float"); + return 0.f; + } + + float t; + se = fast_atoreal_move(s, t); + + if (se == s) { + LogError("failed to read float text"); + return 0.f; + } + + return t; +} + +// ------------------------------------------------------------------------------------------------ +unsigned int XGLImporter::ReadIndexFromText() { + if (!SkipToText()) { + LogError("unexpected EOF reading index element contents"); + return ~0u; + } + const char *s = m_reader->getNodeData(), *se; + if (!SkipSpaces(&s)) { + LogError("unexpected EOL, failed to parse index element"); + return ~0u; + } + + const unsigned int t = strtoul10(s, &se); + + if (se == s) { + LogError("failed to read index"); + return ~0u; + } + + return t; +} + +// ------------------------------------------------------------------------------------------------ +aiVector2D XGLImporter::ReadVec2() { + aiVector2D vec; + + if (!SkipToText()) { + LogError("unexpected EOF reading vec2 contents"); + return vec; + } + const char *s = m_reader->getNodeData(); + + ai_real v[2]; + for (int i = 0; i < 2; ++i) { + if (!SkipSpaces(&s)) { + LogError("unexpected EOL, failed to parse vec2"); + return vec; + } + + v[i] = fast_atof(&s); + + SkipSpaces(&s); + if (i != 1 && *s != ',') { + LogError("expected comma, failed to parse vec2"); + return vec; + } + ++s; + } + vec.x = v[0]; + vec.y = v[1]; +>>>>>>> master return vec; } // ------------------------------------------------------------------------------------------------ +<<<<<<< HEAD aiVector3D XGLImporter::ReadVec3(XmlNode &node) { aiVector3D vec; const char *s = node.value(); @@ -834,6 +1526,42 @@ aiColor3D XGLImporter::ReadCol3(XmlNode &node) { LogWarn("color values out of range, ignoring"); } return aiColor3D(v.x, v.y, v.z); +======= +aiVector3D XGLImporter::ReadVec3() { + aiVector3D vec; + + if (!SkipToText()) { + LogError("unexpected EOF reading vec3 contents"); + return vec; + } + const char *s = m_reader->getNodeData(); + + for (int i = 0; i < 3; ++i) { + if (!SkipSpaces(&s)) { + LogError("unexpected EOL, failed to parse vec3"); + return vec; + } + vec[i] = fast_atof(&s); + + SkipSpaces(&s); + if (i != 2 && *s != ',') { + LogError("expected comma, failed to parse vec3"); + return vec; + } + ++s; + } + + return vec; +} + +// ------------------------------------------------------------------------------------------------ +aiColor3D XGLImporter::ReadCol3() { + const aiVector3D &v = ReadVec3(); + if (v.x < 0.f || v.x > 1.0f || v.y < 0.f || v.y > 1.0f || v.z < 0.f || v.z > 1.0f) { + LogWarn("color values out of range, ignoring"); + } + return aiColor3D(v.x, v.y, v.z); +>>>>>>> master } #endif diff --git a/code/AssetLib/XGL/XGLLoader.h b/code/AssetLib/XGL/XGLLoader.h index e3861fe9b..ac7d83482 100644 --- a/code/AssetLib/XGL/XGLLoader.h +++ b/code/AssetLib/XGL/XGLLoader.h @@ -47,19 +47,28 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define AI_XGLLOADER_H_INCLUDED #include +<<<<<<< HEAD #include +======= +>>>>>>> master #include +#include +#include #include -#include #include +<<<<<<< HEAD #include #include +======= +#include +>>>>>>> master #include +#include struct aiNode; -namespace Assimp { +namespace Assimp { // --------------------------------------------------------------------------- /** XGL/ZGL importer. @@ -71,26 +80,30 @@ public: XGLImporter(); ~XGLImporter(); +<<<<<<< HEAD +======= +public: +>>>>>>> master // ------------------------------------------------------------------- /** Returns whether the class can handle the format of the given file. * See BaseImporter::CanRead() for details. */ - bool CanRead( const std::string& pFile, IOSystem* pIOHandler, - bool checkSig) const; + bool CanRead(const std::string &pFile, IOSystem *pIOHandler, + bool checkSig) const; protected: - // ------------------------------------------------------------------- /** Return importer meta information. * See #BaseImporter::GetInfo for the details */ - const aiImporterDesc* GetInfo () const; + const aiImporterDesc *GetInfo() const; // ------------------------------------------------------------------- /** Imports the given file into the given scene structure. * See BaseImporter::InternReadFile() for details */ - void InternReadFile( const std::string& pFile, aiScene* pScene, - IOSystem* pIOHandler); + void InternReadFile(const std::string &pFile, aiScene *pScene, + IOSystem *pIOHandler); private: +<<<<<<< HEAD struct TempScope { TempScope() @@ -100,10 +113,18 @@ private: ~TempScope() { for(aiMesh* m : meshes_linear) { +======= + struct TempScope { + TempScope() : + light() {} + + ~TempScope() { + for (aiMesh *m : meshes_linear) { +>>>>>>> master delete m; } - for(aiMaterial* m : materials_linear) { + for (aiMaterial *m : materials_linear) { delete m; } @@ -111,45 +132,41 @@ private: } void dismiss() { - light = NULL; + light = nullptr; meshes_linear.clear(); materials_linear.clear(); meshes.clear(); materials.clear(); } - std::multimap meshes; - std::map materials; + std::multimap meshes; + std::map materials; - std::vector meshes_linear; - std::vector materials_linear; + std::vector meshes_linear; + std::vector materials_linear; - aiLight* light; + aiLight *light; }; - struct SortMeshByMaterialId { - SortMeshByMaterialId(const TempScope& scope) : scope(scope) {} + SortMeshByMaterialId(const TempScope &scope) : + scope(scope) {} bool operator()(unsigned int a, unsigned int b) const { return scope.meshes_linear[a]->mMaterialIndex < scope.meshes_linear[b]->mMaterialIndex; }; - const TempScope& scope; + const TempScope &scope; }; - struct TempMesh - { + struct TempMesh { std::map points; std::map normals; std::map uvs; }; - struct TempMaterialMesh - { - TempMaterialMesh() - : pflags() - , matid() - {} + struct TempMaterialMesh { + TempMaterialMesh() : + pflags(), matid() {} std::vector positions, normals; std::vector uvs; @@ -159,12 +176,9 @@ private: unsigned int matid; }; - struct TempFace - { - TempFace() - : has_uv() - , has_normal() - {} + struct TempFace { + TempFace() : + has_uv(), has_normal() {} aiVector3D pos; aiVector3D normal; @@ -176,6 +190,7 @@ private: private: void Cleanup(); +<<<<<<< HEAD unsigned int ReadIDAttr(XmlNode &node); void ReadWorld(TempScope& scope); @@ -199,6 +214,34 @@ private: //std::shared_ptr m_reader; XmlParser *m_xmlParser; aiScene* m_scene; +======= + std::string GetElementName(); + bool ReadElement(); + bool ReadElementUpToClosing(const char *closetag); + bool SkipToText(); + unsigned int ReadIDAttr(); + + void ReadWorld(TempScope &scope); + void ReadLighting(TempScope &scope); + aiLight *ReadDirectionalLight(); + aiNode *ReadObject(TempScope &scope, bool skipFirst = false, const char *closetag = "object"); + bool ReadMesh(TempScope &scope); + void ReadMaterial(TempScope &scope); + aiVector2D ReadVec2(); + aiVector3D ReadVec3(); + aiColor3D ReadCol3(); + aiMatrix4x4 ReadTrafo(); + unsigned int ReadIndexFromText(); + float ReadFloat(); + + aiMesh *ToOutputMesh(const TempMaterialMesh &m); + void ReadFaceVertex(const TempMesh &t, TempFace &out); + unsigned int ResolveMaterialRef(TempScope &scope); + +private: + std::shared_ptr m_reader; + aiScene *m_scene; +>>>>>>> master }; } // end of namespace Assimp diff --git a/code/AssetLib/glTF/glTFAsset.h b/code/AssetLib/glTF/glTFAsset.h index 4c7aaa908..d6d1dd372 100644 --- a/code/AssetLib/glTF/glTFAsset.h +++ b/code/AssetLib/glTF/glTFAsset.h @@ -4,7 +4,6 @@ Open Asset Import Library (assimp) Copyright (c) 2006-2020, assimp team - All rights reserved. Redistribution and use of this software in source and binary forms, @@ -61,11 +60,27 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include +#ifndef RAPIDJSON_HAS_STDSTRING #define RAPIDJSON_HAS_STDSTRING 1 +#endif + +#if (__GNUC__ == 8 && __GNUC_MINOR__ >= 0) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wclass-memaccess" +#endif + +#ifndef RAPIDJSON_NOMEMBERITERATORCLASS +#define RAPIDJSON_NOMEMBERITERATORCLASS +#endif + #include #include #include +#if (__GNUC__ == 8 && __GNUC_MINOR__ >= 0) +#pragma GCC diagnostic pop +#endif + #ifdef ASSIMP_API # include # include diff --git a/code/AssetLib/glTF/glTFCommon.h b/code/AssetLib/glTF/glTFCommon.h index d161e8cd6..b151918b6 100644 --- a/code/AssetLib/glTF/glTFCommon.h +++ b/code/AssetLib/glTF/glTFCommon.h @@ -53,6 +53,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #define RAPIDJSON_HAS_STDSTRING 1 +#define RAPIDJSON_NOMEMBERITERATORCLASS #include #include #include diff --git a/code/AssetLib/glTF/glTFImporter.cpp b/code/AssetLib/glTF/glTFImporter.cpp index 7bf43b6ad..b4ef9b06f 100644 --- a/code/AssetLib/glTF/glTFImporter.cpp +++ b/code/AssetLib/glTF/glTFImporter.cpp @@ -48,12 +48,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include -#include -#include #include -#include -#include #include +#include +#include +#include +#include #include @@ -69,8 +69,7 @@ static const aiImporterDesc desc = { "", "", "", - aiImporterFlags_SupportTextFlavour | aiImporterFlags_SupportBinaryFlavour | aiImporterFlags_SupportCompressedFlavour - | aiImporterFlags_LimitedSupport | aiImporterFlags_Experimental, + aiImporterFlags_SupportTextFlavour | aiImporterFlags_SupportBinaryFlavour | aiImporterFlags_SupportCompressedFlavour | aiImporterFlags_LimitedSupport | aiImporterFlags_Experimental, 0, 0, 0, @@ -78,11 +77,8 @@ static const aiImporterDesc desc = { "gltf glb" }; -glTFImporter::glTFImporter() -: BaseImporter() -, meshOffsets() -, embeddedTexIdxs() -, mScene( nullptr ) { +glTFImporter::glTFImporter() : + BaseImporter(), meshOffsets(), embeddedTexIdxs(), mScene(nullptr) { // empty } @@ -90,11 +86,11 @@ glTFImporter::~glTFImporter() { // empty } -const aiImporterDesc* glTFImporter::GetInfo() const { +const aiImporterDesc *glTFImporter::GetInfo() const { return &desc; } -bool glTFImporter::CanRead(const std::string& pFile, IOSystem* pIOHandler, bool /* checkSig */) const { +bool glTFImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /* checkSig */) const { const std::string &extension = GetExtension(pFile); if (extension != "gltf" && extension != "glb") { @@ -115,9 +111,8 @@ bool glTFImporter::CanRead(const std::string& pFile, IOSystem* pIOHandler, bool return false; } -inline -void SetMaterialColorProperty(std::vector& embeddedTexIdxs, Asset& /*r*/, glTF::TexProperty prop, aiMaterial* mat, - aiTextureType texType, const char* pKey, unsigned int type, unsigned int idx) { +inline void SetMaterialColorProperty(std::vector &embeddedTexIdxs, Asset & /*r*/, glTF::TexProperty prop, aiMaterial *mat, + aiTextureType texType, const char *pKey, unsigned int type, unsigned int idx) { if (prop.texture) { if (prop.texture->source) { aiString uri(prop.texture->source->uri); @@ -138,22 +133,22 @@ void SetMaterialColorProperty(std::vector& embeddedTexIdxs, Asset& /*r*/, g } } -void glTFImporter::ImportMaterials(glTF::Asset& r) { +void glTFImporter::ImportMaterials(glTF::Asset &r) { mScene->mNumMaterials = unsigned(r.materials.Size()); - mScene->mMaterials = new aiMaterial*[mScene->mNumMaterials]; + mScene->mMaterials = new aiMaterial *[mScene->mNumMaterials]; for (unsigned int i = 0; i < mScene->mNumMaterials; ++i) { - aiMaterial* aimat = mScene->mMaterials[i] = new aiMaterial(); + aiMaterial *aimat = mScene->mMaterials[i] = new aiMaterial(); - Material& mat = r.materials[i]; + Material &mat = r.materials[i]; /*if (!mat.name.empty())*/ { aiString str(mat.id /*mat.name*/); aimat->AddProperty(&str, AI_MATKEY_NAME); } - SetMaterialColorProperty(embeddedTexIdxs, r, mat.ambient, aimat, aiTextureType_AMBIENT, AI_MATKEY_COLOR_AMBIENT ); - SetMaterialColorProperty(embeddedTexIdxs, r, mat.diffuse, aimat, aiTextureType_DIFFUSE, AI_MATKEY_COLOR_DIFFUSE ); + SetMaterialColorProperty(embeddedTexIdxs, r, mat.ambient, aimat, aiTextureType_AMBIENT, AI_MATKEY_COLOR_AMBIENT); + SetMaterialColorProperty(embeddedTexIdxs, r, mat.diffuse, aimat, aiTextureType_DIFFUSE, AI_MATKEY_COLOR_DIFFUSE); SetMaterialColorProperty(embeddedTexIdxs, r, mat.specular, aimat, aiTextureType_SPECULAR, AI_MATKEY_COLOR_SPECULAR); SetMaterialColorProperty(embeddedTexIdxs, r, mat.emission, aimat, aiTextureType_EMISSIVE, AI_MATKEY_COLOR_EMISSIVE); @@ -172,29 +167,25 @@ void glTFImporter::ImportMaterials(glTF::Asset& r) { mScene->mNumMaterials = 1; // Delete the array of length zero created above. delete[] mScene->mMaterials; - mScene->mMaterials = new aiMaterial*[1]; + mScene->mMaterials = new aiMaterial *[1]; mScene->mMaterials[0] = new aiMaterial(); } } - -static inline void SetFace(aiFace& face, int a) -{ +static inline void SetFace(aiFace &face, int a) { face.mNumIndices = 1; face.mIndices = new unsigned int[1]; face.mIndices[0] = a; } -static inline void SetFace(aiFace& face, int a, int b) -{ +static inline void SetFace(aiFace &face, int a, int b) { face.mNumIndices = 2; face.mIndices = new unsigned int[2]; face.mIndices[0] = a; face.mIndices[1] = b; } -static inline void SetFace(aiFace& face, int a, int b, int c) -{ +static inline void SetFace(aiFace &face, int a, int b, int c) { face.mNumIndices = 3; face.mIndices = new unsigned int[3]; face.mIndices[0] = a; @@ -202,9 +193,7 @@ static inline void SetFace(aiFace& face, int a, int b, int c) face.mIndices[2] = c; } -#ifdef ASSIMP_BUILD_DEBUG -static inline bool CheckValidFacesIndices(aiFace* faces, unsigned nFaces, unsigned nVerts) -{ +static inline bool CheckValidFacesIndices(aiFace *faces, unsigned nFaces, unsigned nVerts) { for (unsigned i = 0; i < nFaces; ++i) { for (unsigned j = 0; j < faces[i].mNumIndices; ++j) { unsigned idx = faces[i].mIndices[j]; @@ -214,105 +203,98 @@ static inline bool CheckValidFacesIndices(aiFace* faces, unsigned nFaces, unsign } return true; } -#endif // ASSIMP_BUILD_DEBUG -void glTFImporter::ImportMeshes(glTF::Asset& r) -{ - std::vector meshes; +void glTFImporter::ImportMeshes(glTF::Asset &r) { + std::vector meshes; unsigned int k = 0; meshOffsets.clear(); for (unsigned int m = 0; m < r.meshes.Size(); ++m) { - Mesh& mesh = r.meshes[m]; + Mesh &mesh = r.meshes[m]; - // Check if mesh extensions is used - if(mesh.Extension.size() > 0) - { - for(Mesh::SExtension* cur_ext : mesh.Extension) - { + // Check if mesh extensions is used + if (mesh.Extension.size() > 0) { + for (Mesh::SExtension *cur_ext : mesh.Extension) { #ifdef ASSIMP_IMPORTER_GLTF_USE_OPEN3DGC - if(cur_ext->Type == Mesh::SExtension::EType::Compression_Open3DGC) - { - // Limitations for meshes when using Open3DGC-compression. - // It's a current limitation of sp... Specification have not this part still - about mesh compression. Why only one primitive? - // Because glTF is very flexibly. But in fact it ugly flexible. Every primitive can has own set of accessors and accessors can - // point to a-a-a-a-any part of buffer (through bufferview of course) and even to another buffer. We know that "Open3DGC-compression" - // is applicable only to part of buffer. As we can't guaranty continuity of the data for decoder, we will limit quantity of primitives. - // Yes indices, coordinates etc. still can br stored in different buffers, but with current specification it's a exporter problem. - // Also primitive can has only one of "POSITION", "NORMAL" and less then "AI_MAX_NUMBER_OF_TEXTURECOORDS" of "TEXCOORD". All accessor - // of primitive must point to one continuous region of the buffer. - if(mesh.primitives.size() > 2) throw DeadlyImportError("GLTF: When using Open3DGC compression then only one primitive per mesh are allowed."); + if (cur_ext->Type == Mesh::SExtension::EType::Compression_Open3DGC) { + // Limitations for meshes when using Open3DGC-compression. + // It's a current limitation of sp... Specification have not this part still - about mesh compression. Why only one primitive? + // Because glTF is very flexibly. But in fact it ugly flexible. Every primitive can has own set of accessors and accessors can + // point to a-a-a-a-any part of buffer (through bufferview of course) and even to another buffer. We know that "Open3DGC-compression" + // is applicable only to part of buffer. As we can't guaranty continuity of the data for decoder, we will limit quantity of primitives. + // Yes indices, coordinates etc. still can br stored in different buffers, but with current specification it's a exporter problem. + // Also primitive can has only one of "POSITION", "NORMAL" and less then "AI_MAX_NUMBER_OF_TEXTURECOORDS" of "TEXCOORD". All accessor + // of primitive must point to one continuous region of the buffer. + if (mesh.primitives.size() > 2) throw DeadlyImportError("GLTF: When using Open3DGC compression then only one primitive per mesh are allowed."); - Mesh::SCompression_Open3DGC* o3dgc_ext = (Mesh::SCompression_Open3DGC*)cur_ext; - Ref buf = r.buffers.Get(o3dgc_ext->Buffer); + Mesh::SCompression_Open3DGC *o3dgc_ext = (Mesh::SCompression_Open3DGC *)cur_ext; + Ref buf = r.buffers.Get(o3dgc_ext->Buffer); - buf->EncodedRegion_SetCurrent(mesh.id); - } - else + buf->EncodedRegion_SetCurrent(mesh.id); + } else #endif - { - throw DeadlyImportError("GLTF: Can not import mesh: unknown mesh extension (code: \"" + to_string(cur_ext->Type) + - "\"), only Open3DGC is supported."); - } - } - }// if(mesh.Extension.size() > 0) + { + throw DeadlyImportError("GLTF: Can not import mesh: unknown mesh extension (code: \"" + to_string(cur_ext->Type) + + "\"), only Open3DGC is supported."); + } + } + } // if(mesh.Extension.size() > 0) - meshOffsets.push_back(k); + meshOffsets.push_back(k); k += unsigned(mesh.primitives.size()); for (unsigned int p = 0; p < mesh.primitives.size(); ++p) { - Mesh::Primitive& prim = mesh.primitives[p]; + Mesh::Primitive &prim = mesh.primitives[p]; - aiMesh* aim = new aiMesh(); + aiMesh *aim = new aiMesh(); meshes.push_back(aim); aim->mName = mesh.id; if (mesh.primitives.size() > 1) { - ai_uint32& len = aim->mName.length; + ai_uint32 &len = aim->mName.length; aim->mName.data[len] = '-'; len += 1 + ASSIMP_itoa10(aim->mName.data + len + 1, unsigned(MAXLEN - len - 1), p); } switch (prim.mode) { - case PrimitiveMode_POINTS: - aim->mPrimitiveTypes |= aiPrimitiveType_POINT; - break; + case PrimitiveMode_POINTS: + aim->mPrimitiveTypes |= aiPrimitiveType_POINT; + break; - case PrimitiveMode_LINES: - case PrimitiveMode_LINE_LOOP: - case PrimitiveMode_LINE_STRIP: - aim->mPrimitiveTypes |= aiPrimitiveType_LINE; - break; + case PrimitiveMode_LINES: + case PrimitiveMode_LINE_LOOP: + case PrimitiveMode_LINE_STRIP: + aim->mPrimitiveTypes |= aiPrimitiveType_LINE; + break; - case PrimitiveMode_TRIANGLES: - case PrimitiveMode_TRIANGLE_STRIP: - case PrimitiveMode_TRIANGLE_FAN: - aim->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE; - break; + case PrimitiveMode_TRIANGLES: + case PrimitiveMode_TRIANGLE_STRIP: + case PrimitiveMode_TRIANGLE_FAN: + aim->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE; + break; } - Mesh::Primitive::Attributes& attr = prim.attributes; + Mesh::Primitive::Attributes &attr = prim.attributes; - if (attr.position.size() > 0 && attr.position[0]) { + if (attr.position.size() > 0 && attr.position[0]) { aim->mNumVertices = attr.position[0]->count; attr.position[0]->ExtractData(aim->mVertices); - } + } - if (attr.normal.size() > 0 && attr.normal[0]) attr.normal[0]->ExtractData(aim->mNormals); + if (attr.normal.size() > 0 && attr.normal[0]) attr.normal[0]->ExtractData(aim->mNormals); for (size_t tc = 0; tc < attr.texcoord.size() && tc < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++tc) { attr.texcoord[tc]->ExtractData(aim->mTextureCoords[tc]); aim->mNumUVComponents[tc] = attr.texcoord[tc]->GetNumComponents(); - aiVector3D* values = aim->mTextureCoords[tc]; + aiVector3D *values = aim->mTextureCoords[tc]; for (unsigned int i = 0; i < aim->mNumVertices; ++i) { values[i].y = 1 - values[i].y; // Flip Y coords } } - - aiFace* faces = 0; + aiFace *faces = 0; unsigned int nFaces = 0; if (prim.indices) { @@ -322,76 +304,75 @@ void glTFImporter::ImportMeshes(glTF::Asset& r) ai_assert(data.IsValid()); switch (prim.mode) { - case PrimitiveMode_POINTS: { - nFaces = count; - faces = new aiFace[nFaces]; - for (unsigned int i = 0; i < count; ++i) { - SetFace(faces[i], data.GetUInt(i)); - } - break; + case PrimitiveMode_POINTS: { + nFaces = count; + faces = new aiFace[nFaces]; + for (unsigned int i = 0; i < count; ++i) { + SetFace(faces[i], data.GetUInt(i)); } - - case PrimitiveMode_LINES: { - nFaces = count / 2; - if (nFaces * 2 != count) { - ASSIMP_LOG_WARN("The number of vertices was not compatible with the LINES mode. Some vertices were dropped."); - count = nFaces * 2; - } - faces = new aiFace[nFaces]; - for (unsigned int i = 0; i < count; i += 2) { - SetFace(faces[i / 2], data.GetUInt(i), data.GetUInt(i + 1)); - } - break; - } - - case PrimitiveMode_LINE_LOOP: - case PrimitiveMode_LINE_STRIP: { - nFaces = count - ((prim.mode == PrimitiveMode_LINE_STRIP) ? 1 : 0); - faces = new aiFace[nFaces]; - SetFace(faces[0], data.GetUInt(0), data.GetUInt(1)); - for (unsigned int i = 2; i < count; ++i) { - SetFace(faces[i - 1], faces[i - 2].mIndices[1], data.GetUInt(i)); - } - if (prim.mode == PrimitiveMode_LINE_LOOP) { // close the loop - SetFace(faces[count - 1], faces[count - 2].mIndices[1], faces[0].mIndices[0]); - } - break; - } - - case PrimitiveMode_TRIANGLES: { - nFaces = count / 3; - if (nFaces * 3 != count) { - ASSIMP_LOG_WARN("The number of vertices was not compatible with the TRIANGLES mode. Some vertices were dropped."); - count = nFaces * 3; - } - faces = new aiFace[nFaces]; - for (unsigned int i = 0; i < count; i += 3) { - SetFace(faces[i / 3], data.GetUInt(i), data.GetUInt(i + 1), data.GetUInt(i + 2)); - } - break; - } - case PrimitiveMode_TRIANGLE_STRIP: { - nFaces = count - 2; - faces = new aiFace[nFaces]; - SetFace(faces[0], data.GetUInt(0), data.GetUInt(1), data.GetUInt(2)); - for (unsigned int i = 3; i < count; ++i) { - SetFace(faces[i - 2], faces[i - 1].mIndices[1], faces[i - 1].mIndices[2], data.GetUInt(i)); - } - break; - } - case PrimitiveMode_TRIANGLE_FAN: - nFaces = count - 2; - faces = new aiFace[nFaces]; - SetFace(faces[0], data.GetUInt(0), data.GetUInt(1), data.GetUInt(2)); - for (unsigned int i = 3; i < count; ++i) { - SetFace(faces[i - 2], faces[0].mIndices[0], faces[i - 1].mIndices[2], data.GetUInt(i)); - } - break; + break; } - } - else { // no indices provided so directly generate from counts - // use the already determined count as it includes checks + case PrimitiveMode_LINES: { + nFaces = count / 2; + if (nFaces * 2 != count) { + ASSIMP_LOG_WARN("The number of vertices was not compatible with the LINES mode. Some vertices were dropped."); + count = nFaces * 2; + } + faces = new aiFace[nFaces]; + for (unsigned int i = 0; i < count; i += 2) { + SetFace(faces[i / 2], data.GetUInt(i), data.GetUInt(i + 1)); + } + break; + } + + case PrimitiveMode_LINE_LOOP: + case PrimitiveMode_LINE_STRIP: { + nFaces = count - ((prim.mode == PrimitiveMode_LINE_STRIP) ? 1 : 0); + faces = new aiFace[nFaces]; + SetFace(faces[0], data.GetUInt(0), data.GetUInt(1)); + for (unsigned int i = 2; i < count; ++i) { + SetFace(faces[i - 1], faces[i - 2].mIndices[1], data.GetUInt(i)); + } + if (prim.mode == PrimitiveMode_LINE_LOOP) { // close the loop + SetFace(faces[count - 1], faces[count - 2].mIndices[1], faces[0].mIndices[0]); + } + break; + } + + case PrimitiveMode_TRIANGLES: { + nFaces = count / 3; + if (nFaces * 3 != count) { + ASSIMP_LOG_WARN("The number of vertices was not compatible with the TRIANGLES mode. Some vertices were dropped."); + count = nFaces * 3; + } + faces = new aiFace[nFaces]; + for (unsigned int i = 0; i < count; i += 3) { + SetFace(faces[i / 3], data.GetUInt(i), data.GetUInt(i + 1), data.GetUInt(i + 2)); + } + break; + } + case PrimitiveMode_TRIANGLE_STRIP: { + nFaces = count - 2; + faces = new aiFace[nFaces]; + SetFace(faces[0], data.GetUInt(0), data.GetUInt(1), data.GetUInt(2)); + for (unsigned int i = 3; i < count; ++i) { + SetFace(faces[i - 2], faces[i - 1].mIndices[1], faces[i - 1].mIndices[2], data.GetUInt(i)); + } + break; + } + case PrimitiveMode_TRIANGLE_FAN: + nFaces = count - 2; + faces = new aiFace[nFaces]; + SetFace(faces[0], data.GetUInt(0), data.GetUInt(1), data.GetUInt(2)); + for (unsigned int i = 3; i < count; ++i) { + SetFace(faces[i - 2], faces[0].mIndices[0], faces[i - 1].mIndices[2], data.GetUInt(i)); + } + break; + } + } else { // no indices provided so directly generate from counts + + // use the already determined count as it includes checks unsigned int count = aim->mNumVertices; switch (prim.mode) { @@ -466,7 +447,11 @@ void glTFImporter::ImportMeshes(glTF::Asset& r) if (faces) { aim->mFaces = faces; aim->mNumFaces = nFaces; - ai_assert(CheckValidFacesIndices(faces, nFaces, aim->mNumVertices)); + const bool validRes = CheckValidFacesIndices(faces, nFaces, aim->mNumVertices); + if (!validRes) { + ai_assert(validRes); + ASSIMP_LOG_WARN("Invalid number of faces detected."); + } } if (prim.material) { @@ -480,22 +465,22 @@ void glTFImporter::ImportMeshes(glTF::Asset& r) CopyVector(meshes, mScene->mMeshes, mScene->mNumMeshes); } -void glTFImporter::ImportCameras(glTF::Asset& r) { +void glTFImporter::ImportCameras(glTF::Asset &r) { if (!r.cameras.Size()) { return; } mScene->mNumCameras = r.cameras.Size(); - mScene->mCameras = new aiCamera*[r.cameras.Size()]; + mScene->mCameras = new aiCamera *[r.cameras.Size()]; for (size_t i = 0; i < r.cameras.Size(); ++i) { - Camera& cam = r.cameras[i]; + Camera &cam = r.cameras[i]; - aiCamera* aicam = mScene->mCameras[i] = new aiCamera(); + aiCamera *aicam = mScene->mCameras[i] = new aiCamera(); if (cam.type == Camera::Perspective) { - aicam->mAspect = cam.perspective.aspectRatio; + aicam->mAspect = cam.perspective.aspectRatio; aicam->mHorizontalFOV = cam.perspective.yfov * ((aicam->mAspect == 0.f) ? 1.f : aicam->mAspect); - aicam->mClipPlaneFar = cam.perspective.zfar; + aicam->mClipPlaneFar = cam.perspective.zfar; aicam->mClipPlaneNear = cam.perspective.znear; } else { aicam->mClipPlaneFar = cam.ortographic.zfar; @@ -509,30 +494,33 @@ void glTFImporter::ImportCameras(glTF::Asset& r) { } } -void glTFImporter::ImportLights(glTF::Asset& r) -{ +void glTFImporter::ImportLights(glTF::Asset &r) { if (!r.lights.Size()) return; mScene->mNumLights = r.lights.Size(); - mScene->mLights = new aiLight*[r.lights.Size()]; + mScene->mLights = new aiLight *[r.lights.Size()]; for (size_t i = 0; i < r.lights.Size(); ++i) { - Light& l = r.lights[i]; + Light &l = r.lights[i]; - aiLight* ail = mScene->mLights[i] = new aiLight(); + aiLight *ail = mScene->mLights[i] = new aiLight(); switch (l.type) { - case Light::Type_directional: - ail->mType = aiLightSource_DIRECTIONAL; break; + case Light::Type_directional: + ail->mType = aiLightSource_DIRECTIONAL; + break; - case Light::Type_spot: - ail->mType = aiLightSource_SPOT; break; + case Light::Type_spot: + ail->mType = aiLightSource_SPOT; + break; - case Light::Type_ambient: - ail->mType = aiLightSource_AMBIENT; break; + case Light::Type_ambient: + ail->mType = aiLightSource_AMBIENT; + break; - default: // Light::Type_point - ail->mType = aiLightSource_POINT; break; + default: // Light::Type_point + ail->mType = aiLightSource_POINT; + break; } CopyValue(l.color, ail->mColorAmbient); @@ -542,35 +530,32 @@ void glTFImporter::ImportLights(glTF::Asset& r) ail->mAngleOuterCone = l.falloffAngle; ail->mAngleInnerCone = l.falloffExponent; // TODO fix this, it does not look right at all - ail->mAttenuationConstant = l.constantAttenuation; - ail->mAttenuationLinear = l.linearAttenuation; + ail->mAttenuationConstant = l.constantAttenuation; + ail->mAttenuationLinear = l.linearAttenuation; ail->mAttenuationQuadratic = l.quadraticAttenuation; } } +aiNode *ImportNode(aiScene *pScene, glTF::Asset &r, std::vector &meshOffsets, glTF::Ref &ptr) { + Node &node = *ptr; -aiNode* ImportNode(aiScene* pScene, glTF::Asset& r, std::vector& meshOffsets, glTF::Ref& ptr) -{ - Node& node = *ptr; - - aiNode* ainode = new aiNode(node.id); + aiNode *ainode = new aiNode(node.id); if (!node.children.empty()) { ainode->mNumChildren = unsigned(node.children.size()); - ainode->mChildren = new aiNode*[ainode->mNumChildren]; + ainode->mChildren = new aiNode *[ainode->mNumChildren]; for (unsigned int i = 0; i < ainode->mNumChildren; ++i) { - aiNode* child = ImportNode(pScene, r, meshOffsets, node.children[i]); + aiNode *child = ImportNode(pScene, r, meshOffsets, node.children[i]); child->mParent = ainode; ainode->mChildren[i] = child; } } - aiMatrix4x4& matrix = ainode->mTransformation; + aiMatrix4x4 &matrix = ainode->mTransformation; if (node.matrix.isPresent) { CopyValue(node.matrix.value, matrix); - } - else { + } else { if (node.translation.isPresent) { aiVector3D trans; CopyValue(node.translation.value, trans); @@ -587,7 +572,6 @@ aiNode* ImportNode(aiScene* pScene, glTF::Asset& r, std::vector& m matrix = s * matrix; } - if (node.rotation.isPresent) { aiQuaternion rot; CopyValue(node.rotation.value, rot); @@ -625,22 +609,20 @@ aiNode* ImportNode(aiScene* pScene, glTF::Asset& r, std::vector& m return ainode; } -void glTFImporter::ImportNodes(glTF::Asset& r) -{ +void glTFImporter::ImportNodes(glTF::Asset &r) { if (!r.scene) return; - std::vector< Ref > rootNodes = r.scene->nodes; + std::vector> rootNodes = r.scene->nodes; // The root nodes unsigned int numRootNodes = unsigned(rootNodes.size()); if (numRootNodes == 1) { // a single root node: use it mScene->mRootNode = ImportNode(mScene, r, meshOffsets, rootNodes[0]); - } - else if (numRootNodes > 1) { // more than one root node: create a fake root - aiNode* root = new aiNode("ROOT"); - root->mChildren = new aiNode*[numRootNodes]; + } else if (numRootNodes > 1) { // more than one root node: create a fake root + aiNode *root = new aiNode("ROOT"); + root->mChildren = new aiNode *[numRootNodes]; for (unsigned int i = 0; i < numRootNodes; ++i) { - aiNode* node = ImportNode(mScene, r, meshOffsets, rootNodes[i]); + aiNode *node = ImportNode(mScene, r, meshOffsets, rootNodes[i]); node->mParent = root; root->mChildren[root->mNumChildren++] = node; } @@ -652,8 +634,7 @@ void glTFImporter::ImportNodes(glTF::Asset& r) //} } -void glTFImporter::ImportEmbeddedTextures(glTF::Asset& r) -{ +void glTFImporter::ImportEmbeddedTextures(glTF::Asset &r) { embeddedTexIdxs.resize(r.images.Size(), -1); int numEmbeddedTexs = 0; @@ -665,7 +646,7 @@ void glTFImporter::ImportEmbeddedTextures(glTF::Asset& r) if (numEmbeddedTexs == 0) return; - mScene->mTextures = new aiTexture*[numEmbeddedTexs]; + mScene->mTextures = new aiTexture *[numEmbeddedTexs]; // Add the embedded textures for (size_t i = 0; i < r.images.Size(); ++i) { @@ -675,18 +656,18 @@ void glTFImporter::ImportEmbeddedTextures(glTF::Asset& r) int idx = mScene->mNumTextures++; embeddedTexIdxs[i] = idx; - aiTexture* tex = mScene->mTextures[idx] = new aiTexture(); + aiTexture *tex = mScene->mTextures[idx] = new aiTexture(); size_t length = img.GetDataLength(); - void* data = img.StealData(); + void *data = img.StealData(); tex->mFilename = img.name; tex->mWidth = static_cast(length); tex->mHeight = 0; - tex->pcData = reinterpret_cast(data); + tex->pcData = reinterpret_cast(data); if (!img.mimeType.empty()) { - const char* ext = strchr(img.mimeType.c_str(), '/') + 1; + const char *ext = strchr(img.mimeType.c_str(), '/') + 1; if (ext) { if (strcmp(ext, "jpeg") == 0) ext = "jpg"; @@ -699,32 +680,26 @@ void glTFImporter::ImportEmbeddedTextures(glTF::Asset& r) } } -void glTFImporter::ImportCommonMetadata(glTF::Asset& a) -{ +void glTFImporter::ImportCommonMetadata(glTF::Asset &a) { ai_assert(mScene->mMetaData == nullptr); const bool hasVersion = !a.asset.version.empty(); const bool hasGenerator = !a.asset.generator.empty(); const bool hasCopyright = !a.asset.copyright.empty(); - if (hasVersion || hasGenerator || hasCopyright) - { + if (hasVersion || hasGenerator || hasCopyright) { mScene->mMetaData = new aiMetadata; - if (hasVersion) - { + if (hasVersion) { mScene->mMetaData->Add(AI_METADATA_SOURCE_FORMAT_VERSION, aiString(a.asset.version)); } - if (hasGenerator) - { + if (hasGenerator) { mScene->mMetaData->Add(AI_METADATA_SOURCE_GENERATOR, aiString(a.asset.generator)); } - if (hasCopyright) - { + if (hasCopyright) { mScene->mMetaData->Add(AI_METADATA_SOURCE_COPYRIGHT, aiString(a.asset.copyright)); } } } -void glTFImporter::InternReadFile(const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler) -{ +void glTFImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler) { // clean all member arrays meshOffsets.clear(); embeddedTexIdxs.clear(); @@ -735,7 +710,6 @@ void glTFImporter::InternReadFile(const std::string& pFile, aiScene* pScene, IOS glTF::Asset asset(pIOHandler); asset.Load(pFile, GetExtension(pFile) == "glb"); - // // Copy the data out // @@ -757,4 +731,3 @@ void glTFImporter::InternReadFile(const std::string& pFile, aiScene* pScene, IOS } #endif // ASSIMP_BUILD_NO_GLTF_IMPORTER - diff --git a/code/AssetLib/glTF2/glTF2Asset.h b/code/AssetLib/glTF2/glTF2Asset.h index bfd4e4342..f79ddee87 100644 --- a/code/AssetLib/glTF2/glTF2Asset.h +++ b/code/AssetLib/glTF2/glTF2Asset.h @@ -4,7 +4,6 @@ Open Asset Import Library (assimp) Copyright (c) 2006-2020, assimp team - All rights reserved. Redistribution and use of this software in source and binary forms, @@ -63,11 +62,27 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include +#ifndef RAPIDJSON_HAS_STDSTRING #define RAPIDJSON_HAS_STDSTRING 1 +#endif + +#if (__GNUC__ == 8 && __GNUC_MINOR__ >= 0) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wclass-memaccess" +#endif + +#ifndef RAPIDJSON_NOMEMBERITERATORCLASS +#define RAPIDJSON_NOMEMBERITERATORCLASS +#endif + #include #include #include +#if (__GNUC__ == 8 && __GNUC_MINOR__ >= 0) +#pragma GCC diagnostic pop +#endif + #ifdef ASSIMP_API #include #include @@ -175,19 +190,19 @@ enum ComponentType { inline unsigned int ComponentTypeSize(ComponentType t) { switch (t) { - case ComponentType_SHORT: - case ComponentType_UNSIGNED_SHORT: - return 2; + case ComponentType_SHORT: + case ComponentType_UNSIGNED_SHORT: + return 2; - case ComponentType_UNSIGNED_INT: - case ComponentType_FLOAT: - return 4; + case ComponentType_UNSIGNED_INT: + case ComponentType_FLOAT: + return 4; - case ComponentType_BYTE: - case ComponentType_UNSIGNED_BYTE: - return 1; - default: - throw DeadlyImportError("GLTF: Unsupported Component Type " + to_string(t)); + case ComponentType_BYTE: + case ComponentType_UNSIGNED_BYTE: + return 1; + default: + throw DeadlyImportError("GLTF: Unsupported Component Type " + to_string(t)); } } @@ -318,9 +333,11 @@ class Ref { public: Ref() : - vector(0), index(0) {} + vector(0), + index(0) {} Ref(std::vector &vec, unsigned int idx) : - vector(&vec), index(idx) {} + vector(&vec), + index(idx) {} inline unsigned int GetIndex() const { return index; } @@ -340,7 +357,8 @@ struct Nullable { Nullable() : isPresent(false) {} Nullable(T &val) : - value(val), isPresent(true) {} + value(val), + isPresent(true) {} }; //! Base class for all glTF top-level objects @@ -363,49 +381,28 @@ struct Object { // Classes for each glTF top-level object type // -//! Base class for types that access binary data from a BufferView, such as accessors -//! or sparse accessors' indices. -//! N.B. not a virtual class. All owned pointers to BufferViewClient instances should -//! be to their most derived types (which may of course be just BufferViewClient). -struct BufferViewClient : public Object { - Ref bufferView; //!< The ID of the bufferView. (required) - size_t byteOffset; //!< The offset relative to the start of the bufferView in bytes. (required) - - inline uint8_t *GetPointer(); - - void Read(Value &obj, Asset &r); -}; - -//! BufferViewClient with component type information. -//! N.B. not a virtual class. All owned pointers to ComponentTypedBufferViewClient -//! instances should be to their most derived types (which may of course be just -//! ComponentTypedBufferViewClient). -struct ComponentTypedBufferViewClient : public BufferViewClient { - ComponentType componentType; //!< The datatype of components in the attribute. (required) - - unsigned int GetBytesPerComponent(); - - void Read(Value &obj, Asset &r); -}; - //! A typed view into a BufferView. A BufferView contains raw binary data. //! An accessor provides a typed view into a BufferView or a subset of a BufferView //! similar to how WebGL's vertexAttribPointer() defines an attribute in a buffer. -struct Accessor : public ComponentTypedBufferViewClient { +struct Accessor : public Object { struct Sparse; + Ref bufferView; //!< The ID of the bufferView. (required) + size_t byteOffset; //!< The offset relative to the start of the bufferView in bytes. (required) + ComponentType componentType; //!< The datatype of components in the attribute. (required) size_t count; //!< The number of attributes referenced by this accessor. (required) AttribType::Value type; //!< Specifies if the attribute is a scalar, vector, or matrix. (required) std::vector max; //!< Maximum value of each component in this attribute. std::vector min; //!< Minimum value of each component in this attribute. - std::unique_ptr sparse; //!< Sparse accessor information + std::unique_ptr sparse; unsigned int GetNumComponents(); + unsigned int GetBytesPerComponent(); unsigned int GetElementSize(); inline uint8_t *GetPointer(); - template + template void ExtractData(T *&outData); void WriteData(size_t count, const void *src_buffer, size_t src_stride); @@ -414,8 +411,8 @@ struct Accessor : public ComponentTypedBufferViewClient { class Indexer { friend struct Accessor; - // This field is reported as not used, making it protectd is the easiest way to work around it without going to the bottom of what the problem is: - // ../code/glTF2/glTF2Asset.h:392:19: error: private field 'accessor' is not used [-Werror,-Wunused-private-field] + // This field is reported as not used, making it protectd is the easiest way to work around it without going to the bottom of what the problem is: + // ../code/glTF2/glTF2Asset.h:392:19: error: private field 'accessor' is not used [-Werror,-Wunused-private-field] protected: Accessor &accessor; @@ -424,8 +421,7 @@ struct Accessor : public ComponentTypedBufferViewClient { size_t elemSize, stride; Indexer(Accessor &acc); - - + public: //! Accesses the i-th value as defined by the accessor template @@ -441,62 +437,27 @@ struct Accessor : public ComponentTypedBufferViewClient { } }; - //! Sparse accessor information - struct Sparse { - size_t count; - ComponentTypedBufferViewClient indices; - BufferViewClient values; - - std::vector data; //!< Actual data, which may be defaulted to an array of zeros or the original data, with the sparse buffer view applied on top of it. - - inline void PopulateData(size_t numBytes, uint8_t *bytes) { - if (bytes) { - data.assign(bytes, bytes + numBytes); - } else { - data.resize(numBytes, 0x00); - } - } - - inline void PatchData(unsigned int elementSize) - { - uint8_t *pIndices = indices.GetPointer(); - const unsigned int indexSize = indices.GetBytesPerComponent(); - uint8_t *indicesEnd = pIndices + count * indexSize; - - uint8_t *pValues = values.GetPointer(); - while (pIndices != indicesEnd) { - size_t offset; - switch (indices.componentType) { - case ComponentType_UNSIGNED_BYTE: - offset = *pIndices; - break; - case ComponentType_UNSIGNED_SHORT: - offset = *reinterpret_cast(pIndices); - break; - case ComponentType_UNSIGNED_INT: - offset = *reinterpret_cast(pIndices); - break; - default: - // have fun with float and negative values from signed types as indices. - throw DeadlyImportError("Unsupported component type in index."); - } - - offset *= elementSize; - std::memcpy(data.data() + offset, pValues, elementSize); - - pValues += elementSize; - pIndices += indexSize; - } - } - }; - inline Indexer GetIndexer() { return Indexer(*this); } Accessor() {} - void Read(Value &obj, Asset &r); + + //sparse + struct Sparse { + size_t count; + ComponentType indicesType; + Ref indices; + size_t indicesByteOffset; + Ref values; + size_t valuesByteOffset; + + std::vector data; //!< Actual data, which may be defaulted to an array of zeros or the original data, with the sparse buffer view applied on top of it. + + void PopulateData(size_t numBytes, uint8_t *bytes); + void PatchData(unsigned int elementSize); + }; }; //! A buffer points to binary geometry, animation, or skins. @@ -525,7 +486,11 @@ public: /// \param [in] pDecodedData_Length - size of encoded region, in bytes. /// \param [in] pID - ID of the region. SEncodedRegion(const size_t pOffset, const size_t pEncodedData_Length, uint8_t *pDecodedData, const size_t pDecodedData_Length, const std::string pID) : - Offset(pOffset), EncodedData_Length(pEncodedData_Length), DecodedData(pDecodedData), DecodedData_Length(pDecodedData_Length), ID(pID) {} + Offset(pOffset), + EncodedData_Length(pEncodedData_Length), + DecodedData(pDecodedData), + DecodedData_Length(pDecodedData_Length), + ID(pID) {} /// \fn ~SEncodedRegion() /// Destructor. @@ -629,6 +594,7 @@ struct BufferView : public Object { BufferViewTarget target; //! The target that the WebGL buffer should be bound to. void Read(Value &obj, Asset &r); + uint8_t *GetPointer(size_t accOffset); }; struct Camera : public Object { @@ -656,7 +622,8 @@ struct Camera : public Object { } cameraProperties; Camera() : - type(Perspective), cameraProperties() { + type(Perspective), + cameraProperties() { // empty } void Read(Value &obj, Asset &r); @@ -817,6 +784,50 @@ struct Mesh : public Object { void Read(Value &pJSON_Object, Asset &pAsset_Root); }; +struct CustomExtension : public Object { + // + // A struct containing custom extension data added to a glTF2 file + // Has to contain Object, Array, String, Double, Uint64, and Int64 at a minimum + // String, Double, Uint64, and Int64 are stored in the Nullables + // Object and Array are stored in the std::vector + // + + Nullable mStringValue; + Nullable mDoubleValue; + Nullable mUint64Value; + Nullable mInt64Value; + Nullable mBoolValue; + + // std::vector handles both Object and Array + Nullable> mValues; + + operator bool() const { + return Size(); + } + + size_t Size() const { + if (mValues.isPresent) { + return mValues.value.size(); + } else if (mStringValue.isPresent || mDoubleValue.isPresent || mUint64Value.isPresent || mInt64Value.isPresent || mBoolValue.isPresent) { + return 1; + } + return 0; + } + + CustomExtension() = default; + + CustomExtension(const CustomExtension& other) + : Object(other) + , mStringValue(other.mStringValue) + , mDoubleValue(other.mDoubleValue) + , mUint64Value(other.mUint64Value) + , mInt64Value(other.mInt64Value) + , mBoolValue(other.mBoolValue) + , mValues(other.mValues) + { + } +}; + struct Node : public Object { std::vector> children; std::vector> meshes; @@ -835,6 +846,8 @@ struct Node : public Object { Ref parent; //!< This is not part of the glTF specification. Used as a helper. + CustomExtension extensions; + Node() {} void Read(Value &obj, Asset &r); }; @@ -961,7 +974,7 @@ class LazyDict : public LazyDictBase { Value *mDict; //! JSON dictionary object Asset &mAsset; //! The asset instance - std::gltf_unordered_set mRecursiveReferenceCheck; //! Used by Retrieve to prevent recursive lookups + std::gltf_unordered_set mRecursiveReferenceCheck; //! Used by Retrieve to prevent recursive lookups void AttachToDocument(Document &doc); void DetachFromDocument(); @@ -1075,7 +1088,22 @@ public: public: Asset(IOSystem *io = 0) : - mIOSystem(io), asset(), accessors(*this, "accessors"), animations(*this, "animations"), buffers(*this, "buffers"), bufferViews(*this, "bufferViews"), cameras(*this, "cameras"), lights(*this, "lights", "KHR_lights_punctual"), images(*this, "images"), materials(*this, "materials"), meshes(*this, "meshes"), nodes(*this, "nodes"), samplers(*this, "samplers"), scenes(*this, "scenes"), skins(*this, "skins"), textures(*this, "textures") { + mIOSystem(io), + asset(), + accessors(*this, "accessors"), + animations(*this, "animations"), + buffers(*this, "buffers"), + bufferViews(*this, "bufferViews"), + cameras(*this, "cameras"), + lights(*this, "lights", "KHR_lights_punctual"), + images(*this, "images"), + materials(*this, "materials"), + meshes(*this, "meshes"), + nodes(*this, "nodes"), + samplers(*this, "samplers"), + scenes(*this, "scenes"), + skins(*this, "skins"), + textures(*this, "textures") { memset(&extensionsUsed, 0, sizeof(extensionsUsed)); memset(&extensionsRequired, 0, sizeof(extensionsRequired)); } diff --git a/code/AssetLib/glTF2/glTF2Asset.inl b/code/AssetLib/glTF2/glTF2Asset.inl index 9015847e3..94f8d9ffa 100644 --- a/code/AssetLib/glTF2/glTF2Asset.inl +++ b/code/AssetLib/glTF2/glTF2Asset.inl @@ -180,7 +180,10 @@ inline Value *FindObject(Value &val, const char *id) { template inline LazyDict::LazyDict(Asset &asset, const char *dictId, const char *extId) : - mDictId(dictId), mExtId(extId), mDict(0), mAsset(asset) { + mDictId(dictId), + mExtId(extId), + mDict(0), + mAsset(asset) { asset.mDicts.push_back(this); // register to the list of dictionaries } @@ -342,7 +345,10 @@ Ref LazyDict::Create(const char *id) { // inline Buffer::Buffer() : - byteLength(0), type(Type_arraybuffer), EncodedRegion_Current(nullptr), mIsSpecial(false) {} + byteLength(0), + type(Type_arraybuffer), + EncodedRegion_Current(nullptr), + mIsSpecial(false) {} inline Buffer::~Buffer() { for (SEncodedRegion *reg : EncodedRegion_List) @@ -517,7 +523,7 @@ inline void Buffer::Grow(size_t amount) { if (amount <= 0) { return; } - + // Capacity is big enough if (capacity >= byteLength + amount) { byteLength += amount; @@ -550,11 +556,130 @@ inline void BufferView::Read(Value &obj, Asset &r) { byteStride = MemberOrDefault(obj, "byteStride", 0u); } -// -// struct BufferViewClient -// +inline uint8_t *BufferView::GetPointer(size_t accOffset) { + if (!buffer) return 0; + uint8_t *basePtr = buffer->GetPointer(); + if (!basePtr) return 0; + + size_t offset = accOffset + byteOffset; + if (buffer->EncodedRegion_Current != nullptr) { + const size_t begin = buffer->EncodedRegion_Current->Offset; + const size_t end = begin + buffer->EncodedRegion_Current->DecodedData_Length; + if ((offset >= begin) && (offset < end)) + return &buffer->EncodedRegion_Current->DecodedData[offset - begin]; + } + + return basePtr + offset; +} + +// +// struct Accessor +// +inline void Accessor::Sparse::PopulateData(size_t numBytes, uint8_t *bytes) { + if (bytes) { + data.assign(bytes, bytes + numBytes); + } else { + data.resize(numBytes, 0x00); + } +} + +inline void Accessor::Sparse::PatchData(unsigned int elementSize) { + uint8_t *pIndices = indices->GetPointer(indicesByteOffset); + const unsigned int indexSize = int(ComponentTypeSize(indicesType)); + uint8_t *indicesEnd = pIndices + count * indexSize; + + uint8_t *pValues = values->GetPointer(valuesByteOffset); + while (pIndices != indicesEnd) { + size_t offset; + switch (indicesType) { + case ComponentType_UNSIGNED_BYTE: + offset = *pIndices; + break; + case ComponentType_UNSIGNED_SHORT: + offset = *reinterpret_cast(pIndices); + break; + case ComponentType_UNSIGNED_INT: + offset = *reinterpret_cast(pIndices); + break; + default: + // have fun with float and negative values from signed types as indices. + throw DeadlyImportError("Unsupported component type in index."); + } + + offset *= elementSize; + std::memcpy(data.data() + offset, pValues, elementSize); + + pValues += elementSize; + pIndices += indexSize; + } +} + +inline void Accessor::Read(Value &obj, Asset &r) { + + if (Value *bufferViewVal = FindUInt(obj, "bufferView")) { + bufferView = r.bufferViews.Retrieve(bufferViewVal->GetUint()); + } + + byteOffset = MemberOrDefault(obj, "byteOffset", size_t(0)); + componentType = MemberOrDefault(obj, "componentType", ComponentType_BYTE); + count = MemberOrDefault(obj, "count", size_t(0)); + + const char *typestr; + type = ReadMember(obj, "type", typestr) ? AttribType::FromString(typestr) : AttribType::SCALAR; + + if (Value *sparseValue = FindObject(obj, "sparse")) { + sparse.reset(new Sparse); + // count + ReadMember(*sparseValue, "count", sparse->count); + + // indices + if (Value *indicesValue = FindObject(*sparseValue, "indices")) { + //indices bufferView + Value *indiceViewID = FindUInt(*indicesValue, "bufferView"); + sparse->indices = r.bufferViews.Retrieve(indiceViewID->GetUint()); + //indices byteOffset + sparse->indicesByteOffset = MemberOrDefault(*indicesValue, "byteOffset", size_t(0)); + //indices componentType + sparse->indicesType = MemberOrDefault(*indicesValue, "componentType", ComponentType_BYTE); + //sparse->indices->Read(*indicesValue, r); + } + + // value + if (Value *valuesValue = FindObject(*sparseValue, "values")) { + //value bufferView + Value *valueViewID = FindUInt(*valuesValue, "bufferView"); + sparse->values = r.bufferViews.Retrieve(valueViewID->GetUint()); + //value byteOffset + sparse->valuesByteOffset = MemberOrDefault(*valuesValue, "byteOffset", size_t(0)); + //sparse->values->Read(*valuesValue, r); + } + + // indicesType + sparse->indicesType = MemberOrDefault(*sparseValue, "componentType", ComponentType_UNSIGNED_SHORT); + + const unsigned int elementSize = GetElementSize(); + const size_t dataSize = count * elementSize; + sparse->PopulateData(dataSize, bufferView ? bufferView->GetPointer(byteOffset) : 0); + sparse->PatchData(elementSize); + } +} + +inline unsigned int Accessor::GetNumComponents() { + return AttribType::GetNumComponents(type); +} + +inline unsigned int Accessor::GetBytesPerComponent() { + return int(ComponentTypeSize(componentType)); +} + +inline unsigned int Accessor::GetElementSize() { + return GetNumComponents() * GetBytesPerComponent(); +} + +inline uint8_t *Accessor::GetPointer() { + if (sparse) + return sparse->data.data(); -inline uint8_t *BufferViewClient::GetPointer() { if (!bufferView || !bufferView->buffer) return 0; uint8_t *basePtr = bufferView->buffer->GetPointer(); if (!basePtr) return 0; @@ -573,76 +698,6 @@ inline uint8_t *BufferViewClient::GetPointer() { return basePtr + offset; } -inline void BufferViewClient::Read(Value &obj, Asset &r) { - - if (Value *bufferViewVal = FindUInt(obj, "bufferView")) { - bufferView = r.bufferViews.Retrieve(bufferViewVal->GetUint()); - } - - byteOffset = MemberOrDefault(obj, "byteOffset", size_t(0)); -} - -// -// struct ComponentTypedBufferViewClient -// - -inline unsigned int ComponentTypedBufferViewClient::GetBytesPerComponent() { - return int(ComponentTypeSize(componentType)); -} - -inline void ComponentTypedBufferViewClient::Read(Value &obj, Asset &r) { - - BufferViewClient::Read(obj, r); - - componentType = MemberOrDefault(obj, "componentType", ComponentType_BYTE); -} - -// -// struct Accessor -// - -inline uint8_t *Accessor::GetPointer() { - if (!sparse) return BufferViewClient::GetPointer(); - - return sparse->data.data(); -} - -inline void Accessor::Read(Value &obj, Asset &r) { - - ComponentTypedBufferViewClient::Read(obj, r); - - count = MemberOrDefault(obj, "count", size_t(0)); - - const char *typestr; - type = ReadMember(obj, "type", typestr) ? AttribType::FromString(typestr) : AttribType::SCALAR; - - if (Value *sparseValue = FindObject(obj, "sparse")) { - sparse.reset(new Sparse); - ReadMember(*sparseValue, "count", sparse->count); - - if (Value *indicesValue = FindObject(*sparseValue, "indices")) { - sparse->indices.Read(*indicesValue, r); - } - - if (Value *valuesValue = FindObject(*sparseValue, "values")) { - sparse->values.Read(*valuesValue, r); - } - - const unsigned int elementSize = GetElementSize(); - const size_t dataSize = count * elementSize; - sparse->PopulateData(dataSize, BufferViewClient::GetPointer()); - sparse->PatchData(elementSize); - } -} - -inline unsigned int Accessor::GetNumComponents() { - return AttribType::GetNumComponents(type); -} - -inline unsigned int Accessor::GetElementSize() { - return GetNumComponents() * GetBytesPerComponent(); -} - namespace { inline void CopyData(size_t count, const uint8_t *src, size_t src_stride, @@ -663,12 +718,11 @@ inline void CopyData(size_t count, } } // namespace -template -void Accessor::ExtractData(T *&outData) -{ - uint8_t* data = GetPointer(); +template +void Accessor::ExtractData(T *&outData) { + uint8_t *data = GetPointer(); if (!data) { - throw DeadlyImportError("GLTF: data is NULL"); + throw DeadlyImportError("GLTF2: data is nullptr."); } const size_t elemSize = GetElementSize(); @@ -678,7 +732,6 @@ void Accessor::ExtractData(T *&outData) const size_t targetElemSize = sizeof(T); ai_assert(elemSize <= targetElemSize); - ai_assert(count * stride <= (bufferView ? bufferView->byteLength : sparse->data.size())); outData = new T[count]; @@ -705,7 +758,10 @@ inline void Accessor::WriteData(size_t _count, const void *src_buffer, size_t sr } inline Accessor::Indexer::Indexer(Accessor &acc) : - accessor(acc), data(acc.GetPointer()), elemSize(acc.GetElementSize()), stride(acc.bufferView && acc.bufferView->byteStride ? acc.bufferView->byteStride : elemSize) { + accessor(acc), + data(acc.GetPointer()), + elemSize(acc.GetElementSize()), + stride(acc.bufferView && acc.bufferView->byteStride ? acc.bufferView->byteStride : elemSize) { } //! Accesses the i-th value as defined by the accessor @@ -720,7 +776,9 @@ T Accessor::Indexer::GetValue(int i) { } inline Image::Image() : - width(0), height(0), mDataLength(0) { + width(0), + height(0), + mDataLength(0) { } inline void Image::Read(Value &obj, Asset &r) { @@ -958,8 +1016,8 @@ inline int Compare(const char *attr, const char (&str)[N]) { } #ifdef _WIN32 -# pragma warning(push) -# pragma warning(disable : 4706) +#pragma warning(push) +#pragma warning(disable : 4706) #endif // _WIN32 inline bool GetAttribVector(Mesh::Primitive &p, const char *attr, Mesh::AccessorList *&v, int &pos) { @@ -1079,11 +1137,11 @@ inline void Mesh::Read(Value &pJSON_Object, Asset &pAsset_Root) { } Value *extras = FindObject(pJSON_Object, "extras"); - if (nullptr != extras ) { - if (Value* curTargetNames = FindArray(*extras, "targetNames")) { + if (nullptr != extras) { + if (Value *curTargetNames = FindArray(*extras, "targetNames")) { this->targetNames.resize(curTargetNames->Size()); for (unsigned int i = 0; i < curTargetNames->Size(); ++i) { - Value& targetNameValue = (*curTargetNames)[i]; + Value &targetNameValue = (*curTargetNames)[i]; if (targetNameValue.IsString()) { this->targetNames[i] = targetNameValue.GetString(); } @@ -1149,6 +1207,47 @@ inline void Light::Read(Value &obj, Asset & /*r*/) { } } +inline CustomExtension ReadExtensions(const char *name, Value& obj) { + CustomExtension ret; + ret.name = name; + if (obj.IsObject()) { + ret.mValues.isPresent = true; + for (auto it = obj.MemberBegin(); it != obj.MemberEnd(); ++it) { + auto& val = it->value; + ret.mValues.value.push_back(ReadExtensions(it->name.GetString(), val)); + } + } + else if (obj.IsArray()) { + ret.mValues.value.reserve(obj.Size()); + ret.mValues.isPresent = true; + for (unsigned int i = 0; i < obj.Size(); ++i) + { + ret.mValues.value.push_back(ReadExtensions(name, obj[i])); + } + } + else if (obj.IsNumber()) { + if (obj.IsUint64()) { + ret.mUint64Value.value = obj.GetUint64(); + ret.mUint64Value.isPresent = true; + } else if (obj.IsInt64()) { + ret.mInt64Value.value = obj.GetInt64(); + ret.mInt64Value.isPresent = true; + } else if (obj.IsDouble()) { + ret.mDoubleValue.value = obj.GetDouble(); + ret.mDoubleValue.isPresent = true; + } + } + else if (obj.IsString()) { + ReadValue(obj, ret.mStringValue); + ret.mStringValue.isPresent = true; + } + else if (obj.IsBool()) { + ret.mBoolValue.value = obj.GetBool(); + ret.mBoolValue.isPresent = true; + } + return ret; +} + inline void Node::Read(Value &obj, Asset &r) { if (name.empty()) { name = id; @@ -1188,8 +1287,6 @@ inline void Node::Read(Value &obj, Asset &r) { } } - // Do not retrieve a skin here, just take a reference, to avoid infinite recursion - // Skins will be properly loaded later Value *curSkin = FindUInt(obj, "skin"); if (nullptr != curSkin) { this->skin = r.skins.Get(curSkin->GetUint()); @@ -1205,6 +1302,8 @@ inline void Node::Read(Value &obj, Asset &r) { Value *curExtensions = FindObject(obj, "extensions"); if (nullptr != curExtensions) { + this->extensions = ReadExtensions("extensions", *curExtensions); + if (r.extensionsUsed.KHR_lights_punctual) { if (Value *ext = FindObject(*curExtensions, "KHR_lights_punctual")) { Value *curLight = FindUInt(*ext, "light"); @@ -1597,7 +1696,7 @@ inline std::string Asset::FindUniqueID(const std::string &str, const char *suffi } #ifdef _WIN32 -# pragma warning(pop) +#pragma warning(pop) #endif // _WIN32 } // namespace glTF2 diff --git a/code/AssetLib/glTF2/glTF2AssetWriter.inl b/code/AssetLib/glTF2/glTF2AssetWriter.inl index 361af40cd..d5b478e35 100644 --- a/code/AssetLib/glTF2/glTF2AssetWriter.inl +++ b/code/AssetLib/glTF2/glTF2AssetWriter.inl @@ -468,6 +468,22 @@ namespace glTF2 { } obj.AddMember("primitives", primitives, w.mAl); + // targetNames + if (m.targetNames.size() > 0) { + Value extras; + extras.SetObject(); + Value targetNames; + targetNames.SetArray(); + targetNames.Reserve(unsigned(m.targetNames.size()), w.mAl); + for (unsigned int n = 0; n < m.targetNames.size(); ++n) { + std::string name = m.targetNames[n]; + Value tname; + tname.SetString(name.c_str(), w.mAl); + targetNames.PushBack(tname, w.mAl); + } + extras.AddMember("targetNames", targetNames, w.mAl); + obj.AddMember("extras", extras, w.mAl); + } } inline void Write(Value& obj, Node& n, AssetWriter& w) diff --git a/code/AssetLib/glTF2/glTF2Exporter.cpp b/code/AssetLib/glTF2/glTF2Exporter.cpp index 566f95e80..2359851f1 100644 --- a/code/AssetLib/glTF2/glTF2Exporter.cpp +++ b/code/AssetLib/glTF2/glTF2Exporter.cpp @@ -824,9 +824,14 @@ void glTF2Exporter::ExportMeshes() /*************** Targets for blendshapes ****************/ if (aim->mNumAnimMeshes > 0) { + bool bExportTargetNames = this->mProperties->HasPropertyBool("GLTF2_TARGETNAMES_EXP") && + this->mProperties->GetPropertyBool("GLTF2_TARGETNAMES_EXP"); + p.targets.resize(aim->mNumAnimMeshes); for (unsigned int am = 0; am < aim->mNumAnimMeshes; ++am) { aiAnimMesh *pAnimMesh = aim->mAnimMeshes[am]; + if (bExportTargetNames) + m->targetNames.push_back(pAnimMesh->mName.data); // position if (pAnimMesh->HasPositions()) { diff --git a/code/AssetLib/glTF2/glTF2Importer.cpp b/code/AssetLib/glTF2/glTF2Importer.cpp index 83f022e8f..4d740d8c1 100644 --- a/code/AssetLib/glTF2/glTF2Importer.cpp +++ b/code/AssetLib/glTF2/glTF2Importer.cpp @@ -416,6 +416,11 @@ void glTF2Importer::ImportMeshes(glTF2::Asset &r) { attr.color[c]->ExtractData(aim->mColors[c]); } for (size_t tc = 0; tc < attr.texcoord.size() && tc < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++tc) { + if (!attr.texcoord[tc]) { + DefaultLogger::get()->warn("Texture coordinate accessor not found or non-contiguous texture coordinate sets."); + continue; + } + if (attr.texcoord[tc]->count != aim->mNumVertices) { DefaultLogger::get()->warn("Texcoord stream size in mesh \"" + mesh.name + "\" does not match the vertex count"); @@ -842,6 +847,26 @@ static std::string GetNodeName(const Node &node) { return node.name.empty() ? node.id : node.name; } +void ParseExtensions(aiMetadata *metadata, const CustomExtension &extension) { + if (extension.mStringValue.isPresent) { + metadata->Add(extension.name.c_str(), aiString(extension.mStringValue.value)); + } else if (extension.mDoubleValue.isPresent) { + metadata->Add(extension.name.c_str(), extension.mDoubleValue.value); + } else if (extension.mUint64Value.isPresent) { + metadata->Add(extension.name.c_str(), extension.mUint64Value.value); + } else if (extension.mInt64Value.isPresent) { + metadata->Add(extension.name.c_str(), static_cast(extension.mInt64Value.value)); + } else if (extension.mBoolValue.isPresent) { + metadata->Add(extension.name.c_str(), extension.mBoolValue.value); + } else if (extension.mValues.isPresent) { + aiMetadata val; + for (size_t i = 0; i < extension.mValues.value.size(); ++i) { + ParseExtensions(&val, extension.mValues.value[i]); + } + metadata->Add(extension.name.c_str(), val); + } +} + aiNode *ImportNode(aiScene *pScene, glTF2::Asset &r, std::vector &meshOffsets, glTF2::Ref &ptr) { Node &node = *ptr; @@ -858,6 +883,11 @@ aiNode *ImportNode(aiScene *pScene, glTF2::Asset &r, std::vector & } } + if (node.extensions) { + ainode->mMetaData = new aiMetadata; + ParseExtensions(ainode->mMetaData, node.extensions); + } + GetNodeTransform(ainode->mTransformation, node); if (!node.meshes.empty()) { @@ -952,8 +982,13 @@ aiNode *ImportNode(aiScene *pScene, glTF2::Asset &r, std::vector & //range is optional - see https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_lights_punctual //it is added to meta data of parent node, because there is no other place to put it if (node.light->range.isPresent) { - ainode->mMetaData = aiMetadata::Alloc(1); - ainode->mMetaData->Set(0, "PBR_LightRange", node.light->range.value); + if (!ainode->mMetaData) { + ainode->mMetaData = aiMetadata::Alloc(1); + ainode->mMetaData->Set(0, "PBR_LightRange", node.light->range.value); + } + else { + ainode->mMetaData->Add("PBR_LightRange", node.light->range.value); + } } } diff --git a/code/CApi/AssimpCExport.cpp b/code/CApi/AssimpCExport.cpp index a6e7a304f..620bd5948 100644 --- a/code/CApi/AssimpCExport.cpp +++ b/code/CApi/AssimpCExport.cpp @@ -48,108 +48,96 @@ Assimp C export interface. See Exporter.cpp for some notes. #ifndef ASSIMP_BUILD_NO_EXPORT #include "CInterfaceIOWrapper.h" -#include #include "Common/ScenePrivate.h" +#include #include using namespace Assimp; // ------------------------------------------------------------------------------------------------ -ASSIMP_API size_t aiGetExportFormatCount(void) -{ +ASSIMP_API size_t aiGetExportFormatCount(void) { return Exporter().GetExportFormatCount(); } // ------------------------------------------------------------------------------------------------ -ASSIMP_API const aiExportFormatDesc* aiGetExportFormatDescription( size_t index) -{ +ASSIMP_API const aiExportFormatDesc *aiGetExportFormatDescription(size_t index) { // Note: this is valid as the index always pertains to a built-in exporter, // for which the returned structure is guaranteed to be of static storage duration. Exporter exporter; - const aiExportFormatDesc* orig( exporter.GetExportFormatDescription( index ) ); - if (NULL == orig) { - return NULL; + const aiExportFormatDesc *orig(exporter.GetExportFormatDescription(index)); + if (nullptr == orig) { + return nullptr; } aiExportFormatDesc *desc = new aiExportFormatDesc; - desc->description = new char[ strlen( orig->description ) + 1 ](); - ::memcpy( (char*) desc->description, orig->description, strlen( orig->description ) ); - desc->fileExtension = new char[ strlen( orig->fileExtension ) + 1 ](); - ::memcpy( ( char* ) desc->fileExtension, orig->fileExtension, strlen( orig->fileExtension ) ); - desc->id = new char[ strlen( orig->id ) + 1 ](); - ::memcpy( ( char* ) desc->id, orig->id, strlen( orig->id ) ); + desc->description = new char[strlen(orig->description) + 1](); + ::memcpy((char *)desc->description, orig->description, strlen(orig->description)); + desc->fileExtension = new char[strlen(orig->fileExtension) + 1](); + ::memcpy((char *)desc->fileExtension, orig->fileExtension, strlen(orig->fileExtension)); + desc->id = new char[strlen(orig->id) + 1](); + ::memcpy((char *)desc->id, orig->id, strlen(orig->id)); return desc; } // ------------------------------------------------------------------------------------------------ -ASSIMP_API void aiReleaseExportFormatDescription( const aiExportFormatDesc *desc ) { - if (NULL == desc) { +ASSIMP_API void aiReleaseExportFormatDescription(const aiExportFormatDesc *desc) { + if (nullptr == desc) { return; } - delete [] desc->description; - delete [] desc->fileExtension; - delete [] desc->id; + delete[] desc->description; + delete[] desc->fileExtension; + delete[] desc->id; delete desc; } // ------------------------------------------------------------------------------------------------ -ASSIMP_API void aiCopyScene(const aiScene* pIn, aiScene** pOut) -{ +ASSIMP_API void aiCopyScene(const aiScene *pIn, aiScene **pOut) { if (!pOut || !pIn) { return; } - SceneCombiner::CopyScene(pOut,pIn,true); + SceneCombiner::CopyScene(pOut, pIn, true); ScenePriv(*pOut)->mIsCopy = true; } - // ------------------------------------------------------------------------------------------------ -ASSIMP_API void aiFreeScene(const C_STRUCT aiScene* pIn) -{ +ASSIMP_API void aiFreeScene(const C_STRUCT aiScene *pIn) { // note: aiReleaseImport() is also able to delete scene copies, but in addition // it also handles scenes with import metadata. delete pIn; } - // ------------------------------------------------------------------------------------------------ -ASSIMP_API aiReturn aiExportScene( const aiScene* pScene, const char* pFormatId, const char* pFileName, unsigned int pPreprocessing ) -{ - return ::aiExportSceneEx(pScene,pFormatId,pFileName,NULL,pPreprocessing); +ASSIMP_API aiReturn aiExportScene(const aiScene *pScene, const char *pFormatId, const char *pFileName, unsigned int pPreprocessing) { + return ::aiExportSceneEx(pScene, pFormatId, pFileName, nullptr, pPreprocessing); } - // ------------------------------------------------------------------------------------------------ -ASSIMP_API aiReturn aiExportSceneEx( const aiScene* pScene, const char* pFormatId, const char* pFileName, aiFileIO* pIO, unsigned int pPreprocessing ) -{ +ASSIMP_API aiReturn aiExportSceneEx(const aiScene *pScene, const char *pFormatId, const char *pFileName, aiFileIO *pIO, unsigned int pPreprocessing) { Exporter exp; if (pIO) { exp.SetIOHandler(new CIOSystemWrapper(pIO)); } - return exp.Export(pScene,pFormatId,pFileName,pPreprocessing); + return exp.Export(pScene, pFormatId, pFileName, pPreprocessing); } - // ------------------------------------------------------------------------------------------------ -ASSIMP_API const C_STRUCT aiExportDataBlob* aiExportSceneToBlob( const aiScene* pScene, const char* pFormatId, unsigned int pPreprocessing ) -{ +ASSIMP_API const C_STRUCT aiExportDataBlob *aiExportSceneToBlob(const aiScene *pScene, const char *pFormatId, unsigned int pPreprocessing) { Exporter exp; - if (!exp.ExportToBlob(pScene,pFormatId,pPreprocessing)) { - return NULL; + if (!exp.ExportToBlob(pScene, pFormatId, pPreprocessing)) { + return nullptr; } - const aiExportDataBlob* blob = exp.GetOrphanedBlob(); + const aiExportDataBlob *blob = exp.GetOrphanedBlob(); ai_assert(blob); return blob; } // ------------------------------------------------------------------------------------------------ -ASSIMP_API C_STRUCT void aiReleaseExportBlob( const aiExportDataBlob* pData ) -{ +ASSIMP_API C_STRUCT void aiReleaseExportBlob(const aiExportDataBlob *pData) { delete pData; } diff --git a/code/CApi/CInterfaceIOWrapper.cpp b/code/CApi/CInterfaceIOWrapper.cpp index 9d8b79c5d..d5c6a2535 100644 --- a/code/CApi/CInterfaceIOWrapper.cpp +++ b/code/CApi/CInterfaceIOWrapper.cpp @@ -116,7 +116,7 @@ char CIOSystemWrapper::getOsSeparator() const { IOStream *CIOSystemWrapper::Open(const char *pFile, const char *pMode) { aiFile *p = mFileSystem->OpenProc(mFileSystem, pFile, pMode); if (!p) { - return NULL; + return nullptr; } return new CIOStreamWrapper(p, this); } diff --git a/code/CMakeLists.txt b/code/CMakeLists.txt index ea7f6717e..16d6b79dc 100644 --- a/code/CMakeLists.txt +++ b/code/CMakeLists.txt @@ -199,6 +199,7 @@ SET( Common_SRCS Common/simd.h Common/simd.cpp Common/material.cpp + Common/AssertHandler.cpp ) SOURCE_GROUP(Common FILES ${Common_SRCS}) diff --git a/code/Collada/ColladaExporter.cpp b/code/Collada/ColladaExporter.cpp deleted file mode 100644 index 05df6fc94..000000000 --- a/code/Collada/ColladaExporter.cpp +++ /dev/null @@ -1,1704 +0,0 @@ -/* -Open Asset Import Library (assimp) ----------------------------------------------------------------------- - -Copyright (c) 2006-2020, 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. - ----------------------------------------------------------------------- -*/ - -#ifndef ASSIMP_BUILD_NO_EXPORT -#ifndef ASSIMP_BUILD_NO_COLLADA_EXPORTER - -#include "ColladaExporter.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include -#include - -using namespace Assimp; - -namespace Assimp { - -// ------------------------------------------------------------------------------------------------ -// Worker function for exporting a scene to Collada. Prototyped and registered in Exporter.cpp -void ExportSceneCollada(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* /*pProperties*/) { - std::string path = DefaultIOSystem::absolutePath(std::string(pFile)); - std::string file = DefaultIOSystem::completeBaseName(std::string(pFile)); - - // invoke the exporter - ColladaExporter iDoTheExportThing( pScene, pIOSystem, path, file); - - if (iDoTheExportThing.mOutput.fail()) { - throw DeadlyExportError("output data creation failed. Most likely the file became too large: " + std::string(pFile)); - } - - // we're still here - export successfully completed. Write result to the given IOSYstem - std::unique_ptr outfile (pIOSystem->Open(pFile,"wt")); - if(outfile == NULL) { - throw DeadlyExportError("could not open output .dae file: " + std::string(pFile)); - } - - // XXX maybe use a small wrapper around IOStream that behaves like std::stringstream in order to avoid the extra copy. - outfile->Write( iDoTheExportThing.mOutput.str().c_str(), static_cast(iDoTheExportThing.mOutput.tellp()),1); -} - -} // end of namespace Assimp - -// ------------------------------------------------------------------------------------------------ -// Encodes a string into a valid XML ID using the xsd:ID schema qualifications. -static const std::string XMLIDEncode(const std::string& name) { - const char XML_ID_CHARS[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_-."; - const unsigned int XML_ID_CHARS_COUNT = sizeof(XML_ID_CHARS) / sizeof(char); - - if (name.length() == 0) { - return name; - } - - std::stringstream idEncoded; - - // xsd:ID must start with letter or underscore - if (!((name[0] >= 'A' && name[0] <= 'z') || name[0] == '_')) { - idEncoded << '_'; - } - - for (std::string::const_iterator it = name.begin(); it != name.end(); ++it) { - // xsd:ID can only contain letters, digits, underscores, hyphens and periods - if (strchr(XML_ID_CHARS, *it) != nullptr) { - idEncoded << *it; - } else { - // Select placeholder character based on invalid character to prevent name collisions - idEncoded << XML_ID_CHARS[(*it) % XML_ID_CHARS_COUNT]; - } - } - - return idEncoded.str(); -} - -// ------------------------------------------------------------------------------------------------ -// Constructor for a specific scene to export -ColladaExporter::ColladaExporter( const aiScene* pScene, IOSystem* pIOSystem, const std::string& path, const std::string& file) -: mIOSystem(pIOSystem) -, mPath(path) -, mFile(file) { - // make sure that all formatting happens using the standard, C locale and not the user's current locale - mOutput.imbue( std::locale("C") ); - mOutput.precision(ASSIMP_AI_REAL_TEXT_PRECISION); - - mScene = pScene; - mSceneOwned = false; - - // set up strings - endstr = "\n"; - - // start writing the file - WriteFile(); -} - -// ------------------------------------------------------------------------------------------------ -// Destructor -ColladaExporter::~ColladaExporter() { - if ( mSceneOwned ) { - delete mScene; - } -} - -// ------------------------------------------------------------------------------------------------ -// Starts writing the contents -void ColladaExporter::WriteFile() { - // write the DTD - mOutput << "" << endstr; - // COLLADA element start - mOutput << "" << endstr; - PushTag(); - - WriteTextures(); - WriteHeader(); - - WriteCamerasLibrary(); - WriteLightsLibrary(); - WriteMaterials(); - WriteGeometryLibrary(); - WriteControllerLibrary(); - - WriteSceneLibrary(); - - // customized, Writes the animation library - WriteAnimationsLibrary(); - - // useless Collada fu at the end, just in case we haven't had enough indirections, yet. - mOutput << startstr << "" << endstr; - PushTag(); - mOutput << startstr << "mRootNode->mName.C_Str()) + "\" />" << endstr; - PopTag(); - mOutput << startstr << "" << endstr; - PopTag(); - mOutput << "" << endstr; -} - -// ------------------------------------------------------------------------------------------------ -// Writes the asset header -void ColladaExporter::WriteHeader() { - static const ai_real epsilon = Math::getEpsilon(); - static const aiQuaternion x_rot(aiMatrix3x3( - 0, -1, 0, - 1, 0, 0, - 0, 0, 1)); - static const aiQuaternion y_rot(aiMatrix3x3( - 1, 0, 0, - 0, 1, 0, - 0, 0, 1)); - static const aiQuaternion z_rot(aiMatrix3x3( - 1, 0, 0, - 0, 0, 1, - 0, -1, 0)); - - static const unsigned int date_nb_chars = 20; - char date_str[date_nb_chars]; - std::time_t date = std::time(NULL); - std::strftime(date_str, date_nb_chars, "%Y-%m-%dT%H:%M:%S", std::localtime(&date)); - - aiVector3D scaling; - aiQuaternion rotation; - aiVector3D position; - mScene->mRootNode->mTransformation.Decompose(scaling, rotation, position); - rotation.Normalize(); - - bool add_root_node = false; - - ai_real scale = 1.0; - if(std::abs(scaling.x - scaling.y) <= epsilon && std::abs(scaling.x - scaling.z) <= epsilon && std::abs(scaling.y - scaling.z) <= epsilon) { - scale = (ai_real) ((((double) scaling.x) + ((double) scaling.y) + ((double) scaling.z)) / 3.0); - } else { - add_root_node = true; - } - - std::string up_axis = "Y_UP"; - if(rotation.Equal(x_rot, epsilon)) { - up_axis = "X_UP"; - } else if(rotation.Equal(y_rot, epsilon)) { - up_axis = "Y_UP"; - } else if(rotation.Equal(z_rot, epsilon)) { - up_axis = "Z_UP"; - } else { - add_root_node = true; - } - - if(! position.Equal(aiVector3D(0, 0, 0))) { - add_root_node = true; - } - - if(mScene->mRootNode->mNumChildren == 0) { - add_root_node = true; - } - - if(add_root_node) { - aiScene* scene; - SceneCombiner::CopyScene(&scene, mScene); - - aiNode* root = new aiNode("Scene"); - - root->mNumChildren = 1; - root->mChildren = new aiNode*[root->mNumChildren]; - - root->mChildren[0] = scene->mRootNode; - scene->mRootNode->mParent = root; - scene->mRootNode = root; - - mScene = scene; - mSceneOwned = true; - - up_axis = "Y_UP"; - scale = 1.0; - } - - mOutput << startstr << "" << endstr; - PushTag(); - mOutput << startstr << "" << endstr; - PushTag(); - - // If no Scene metadata, use root node metadata - aiMetadata* meta = mScene->mMetaData; - if (nullptr == meta) { - meta = mScene->mRootNode->mMetaData; - } - - aiString value; - if (!meta || !meta->Get("Author", value)) { - mOutput << startstr << "" << "Assimp" << "" << endstr; - } else { - mOutput << startstr << "" << XMLEscape(value.C_Str()) << "" << endstr; - } - - if (nullptr == meta || !meta->Get(AI_METADATA_SOURCE_GENERATOR, value)) { - mOutput << startstr << "" << "Assimp Exporter" << "" << endstr; - } else { - mOutput << startstr << "" << XMLEscape(value.C_Str()) << "" << endstr; - } - - if (meta) { - if (meta->Get("Comments", value)) { - mOutput << startstr << "" << XMLEscape(value.C_Str()) << "" << endstr; - } - if (meta->Get(AI_METADATA_SOURCE_COPYRIGHT, value)) { - mOutput << startstr << "" << XMLEscape(value.C_Str()) << "" << endstr; - } - if (meta->Get("SourceData", value)) { - mOutput << startstr << "" << XMLEscape(value.C_Str()) << "" << endstr; - } - } - - PopTag(); - mOutput << startstr << "" << endstr; - - if (nullptr == meta || !meta->Get("Created", value)) { - mOutput << startstr << "" << date_str << "" << endstr; - } else { - mOutput << startstr << "" << XMLEscape(value.C_Str()) << "" << endstr; - } - - // Modified date is always the date saved - mOutput << startstr << "" << date_str << "" << endstr; - - if (meta) { - if (meta->Get("Keywords", value)) { - mOutput << startstr << "" << XMLEscape(value.C_Str()) << "" << endstr; - } - if (meta->Get("Revision", value)) { - mOutput << startstr << "" << XMLEscape(value.C_Str()) << "" << endstr; - } - if (meta->Get("Subject", value)) { - mOutput << startstr << "" << XMLEscape(value.C_Str()) << "" << endstr; - } - if (meta->Get("Title", value)) { - mOutput << startstr << "" << XMLEscape(value.C_Str()) << "" << endstr; - } - } - - mOutput << startstr << "" << endstr; - mOutput << startstr << "" << up_axis << "" << endstr; - PopTag(); - mOutput << startstr << "" << endstr; -} - -// ------------------------------------------------------------------------------------------------ -// Write the embedded textures -void ColladaExporter::WriteTextures() { - static const unsigned int buffer_size = 1024; - char str[buffer_size]; - - if (mScene->HasTextures()) { - for(unsigned int i = 0; i < mScene->mNumTextures; i++) { - // It would be great to be able to create a directory in portable standard C++, but it's not the case, - // so we just write the textures in the current directory. - - aiTexture* texture = mScene->mTextures[i]; - if ( nullptr == texture ) { - continue; - } - - ASSIMP_itoa10(str, buffer_size, i + 1); - - std::string name = mFile + "_texture_" + (i < 1000 ? "0" : "") + (i < 100 ? "0" : "") + (i < 10 ? "0" : "") + str + "." + ((const char*) texture->achFormatHint); - - std::unique_ptr outfile(mIOSystem->Open(mPath + mIOSystem->getOsSeparator() + name, "wb")); - if(outfile == NULL) { - throw DeadlyExportError("could not open output texture file: " + mPath + name); - } - - if(texture->mHeight == 0) { - outfile->Write((void*) texture->pcData, texture->mWidth, 1); - } else { - Bitmap::Save(texture, outfile.get()); - } - - outfile->Flush(); - - textures.insert(std::make_pair(i, name)); - } - } -} - -// ------------------------------------------------------------------------------------------------ -// Write the embedded textures -void ColladaExporter::WriteCamerasLibrary() { - if(mScene->HasCameras()) { - - mOutput << startstr << "" << endstr; - PushTag(); - - for( size_t a = 0; a < mScene->mNumCameras; ++a) - WriteCamera( a); - - PopTag(); - mOutput << startstr << "" << endstr; - - } -} - -void ColladaExporter::WriteCamera(size_t pIndex){ - - const aiCamera *cam = mScene->mCameras[pIndex]; - const std::string cameraName = XMLEscape(cam->mName.C_Str()); - const std::string cameraId = XMLIDEncode(cam->mName.C_Str()); - - mOutput << startstr << "" << endstr; - PushTag(); - mOutput << startstr << "" << endstr; - PushTag(); - mOutput << startstr << "" << endstr; - PushTag(); - //assimp doesn't support the import of orthographic cameras! se we write - //always perspective - mOutput << startstr << "" << endstr; - PushTag(); - mOutput << startstr << ""<< - AI_RAD_TO_DEG(cam->mHorizontalFOV) - <<"" << endstr; - mOutput << startstr << "" - << cam->mAspect - << "" << endstr; - mOutput << startstr << "" - << cam->mClipPlaneNear - << "" << endstr; - mOutput << startstr << "" - << cam->mClipPlaneFar - << "" << endstr; - PopTag(); - mOutput << startstr << "" << endstr; - PopTag(); - mOutput << startstr << "" << endstr; - PopTag(); - mOutput << startstr << "" << endstr; - PopTag(); - mOutput << startstr << "" << endstr; - -} - - -// ------------------------------------------------------------------------------------------------ -// Write the embedded textures -void ColladaExporter::WriteLightsLibrary() { - if(mScene->HasLights()) { - - mOutput << startstr << "" << endstr; - PushTag(); - - for( size_t a = 0; a < mScene->mNumLights; ++a) - WriteLight( a); - - PopTag(); - mOutput << startstr << "" << endstr; - - } -} - -void ColladaExporter::WriteLight(size_t pIndex){ - - const aiLight *light = mScene->mLights[pIndex]; - const std::string lightName = XMLEscape(light->mName.C_Str()); - const std::string lightId = XMLIDEncode(light->mName.C_Str()); - - mOutput << startstr << "" << endstr; - PushTag(); - mOutput << startstr << "" << endstr; - PushTag(); - switch(light->mType){ - case aiLightSource_AMBIENT: - WriteAmbienttLight(light); - break; - case aiLightSource_DIRECTIONAL: - WriteDirectionalLight(light); - break; - case aiLightSource_POINT: - WritePointLight(light); - break; - case aiLightSource_SPOT: - WriteSpotLight(light); - break; - case aiLightSource_AREA: - case aiLightSource_UNDEFINED: - case _aiLightSource_Force32Bit: - break; - } - PopTag(); - mOutput << startstr << "" << endstr; - - PopTag(); - mOutput << startstr << "" << endstr; - -} - -void ColladaExporter::WritePointLight(const aiLight *const light){ - const aiColor3D &color= light->mColorDiffuse; - mOutput << startstr << "" << endstr; - PushTag(); - mOutput << startstr << "" - << color.r<<" "<" << endstr; - mOutput << startstr << "" - << light->mAttenuationConstant - <<"" << endstr; - mOutput << startstr << "" - << light->mAttenuationLinear - <<"" << endstr; - mOutput << startstr << "" - << light->mAttenuationQuadratic - <<"" << endstr; - - PopTag(); - mOutput << startstr << "" << endstr; - -} - -void ColladaExporter::WriteDirectionalLight(const aiLight *const light){ - const aiColor3D &color= light->mColorDiffuse; - mOutput << startstr << "" << endstr; - PushTag(); - mOutput << startstr << "" - << color.r<<" "<" << endstr; - - PopTag(); - mOutput << startstr << "" << endstr; - -} - -void ColladaExporter::WriteSpotLight(const aiLight *const light){ - - const aiColor3D &color= light->mColorDiffuse; - mOutput << startstr << "" << endstr; - PushTag(); - mOutput << startstr << "" - << color.r<<" "<" << endstr; - mOutput << startstr << "" - << light->mAttenuationConstant - <<"" << endstr; - mOutput << startstr << "" - << light->mAttenuationLinear - <<"" << endstr; - mOutput << startstr << "" - << light->mAttenuationQuadratic - <<"" << endstr; - - const ai_real fallOffAngle = AI_RAD_TO_DEG(light->mAngleInnerCone); - mOutput << startstr <<"" - << fallOffAngle - <<"" << endstr; - double temp = light->mAngleOuterCone-light->mAngleInnerCone; - - temp = std::cos(temp); - temp = std::log(temp)/std::log(0.1); - temp = 1/temp; - mOutput << startstr << "" - << temp - <<"" << endstr; - - - PopTag(); - mOutput << startstr << "" << endstr; - -} - -void ColladaExporter::WriteAmbienttLight(const aiLight *const light){ - - const aiColor3D &color= light->mColorAmbient; - mOutput << startstr << "" << endstr; - PushTag(); - mOutput << startstr << "" - << color.r<<" "<" << endstr; - - PopTag(); - mOutput << startstr << "" << endstr; -} - -// ------------------------------------------------------------------------------------------------ -// Reads a single surface entry from the given material keys -void ColladaExporter::ReadMaterialSurface( Surface& poSurface, const aiMaterial* pSrcMat, - aiTextureType pTexture, const char* pKey, size_t pType, size_t pIndex) { - if( pSrcMat->GetTextureCount( pTexture) > 0 ) { - aiString texfile; - unsigned int uvChannel = 0; - pSrcMat->GetTexture( pTexture, 0, &texfile, NULL, &uvChannel); - - std::string index_str(texfile.C_Str()); - - if(index_str.size() != 0 && index_str[0] == '*') { - unsigned int index; - - index_str = index_str.substr(1, std::string::npos); - - try { - index = (unsigned int) strtoul10_64(index_str.c_str()); - } catch(std::exception& error) { - throw DeadlyExportError(error.what()); - } - - std::map::const_iterator name = textures.find(index); - - if(name != textures.end()) { - poSurface.texture = name->second; - } else { - throw DeadlyExportError("could not find embedded texture at index " + index_str); - } - } else { - poSurface.texture = texfile.C_Str(); - } - - poSurface.channel = uvChannel; - poSurface.exist = true; - } else { - if( pKey ) - poSurface.exist = pSrcMat->Get( pKey, static_cast(pType), static_cast(pIndex), poSurface.color) == aiReturn_SUCCESS; - } -} - -static bool isalnum_C(char c) { - return ( nullptr != strchr("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",c) ); -} - -// ------------------------------------------------------------------------------------------------ -// Writes an image entry for the given surface -void ColladaExporter::WriteImageEntry( const Surface& pSurface, const std::string& pNameAdd) { - if( !pSurface.texture.empty() ) - { - mOutput << startstr << "" << endstr; - PushTag(); - mOutput << startstr << ""; - - // URL encode image file name first, then XML encode on top - std::stringstream imageUrlEncoded; - for( std::string::const_iterator it = pSurface.texture.begin(); it != pSurface.texture.end(); ++it ) - { - if( isalnum_C( (unsigned char) *it) || *it == ':' || *it == '_' || *it == '-' || *it == '.' || *it == '/' || *it == '\\' ) - imageUrlEncoded << *it; - else - imageUrlEncoded << '%' << std::hex << size_t( (unsigned char) *it) << std::dec; - } - mOutput << XMLEscape(imageUrlEncoded.str()); - mOutput << "" << endstr; - PopTag(); - mOutput << startstr << "" << endstr; - } -} - -// ------------------------------------------------------------------------------------------------ -// Writes a color-or-texture entry into an effect definition -void ColladaExporter::WriteTextureColorEntry( const Surface& pSurface, const std::string& pTypeName, const std::string& pImageName) -{ - if(pSurface.exist) { - mOutput << startstr << "<" << pTypeName << ">" << endstr; - PushTag(); - if( pSurface.texture.empty() ) - { - mOutput << startstr << "" << pSurface.color.r << " " << pSurface.color.g << " " << pSurface.color.b << " " << pSurface.color.a << "" << endstr; - } - else - { - mOutput << startstr << "" << endstr; - } - PopTag(); - mOutput << startstr << "" << endstr; - } -} - -// ------------------------------------------------------------------------------------------------ -// Writes the two parameters necessary for referencing a texture in an effect entry -void ColladaExporter::WriteTextureParamEntry( const Surface& pSurface, const std::string& pTypeName, const std::string& pMatName) -{ - // if surface is a texture, write out the sampler and the surface parameters necessary to reference the texture - if( !pSurface.texture.empty() ) - { - mOutput << startstr << "" << endstr; - PushTag(); - mOutput << startstr << "" << endstr; - PushTag(); - mOutput << startstr << "" << XMLIDEncode(pMatName) << "-" << pTypeName << "-image" << endstr; - PopTag(); - mOutput << startstr << "" << endstr; - PopTag(); - mOutput << startstr << "" << endstr; - - mOutput << startstr << "" << endstr; - PushTag(); - mOutput << startstr << "" << endstr; - PushTag(); - mOutput << startstr << "" << XMLIDEncode(pMatName) << "-" << pTypeName << "-surface" << endstr; - PopTag(); - mOutput << startstr << "" << endstr; - PopTag(); - mOutput << startstr << "" << endstr; - } -} - -// ------------------------------------------------------------------------------------------------ -// Writes a scalar property -void ColladaExporter::WriteFloatEntry( const Property& pProperty, const std::string& pTypeName) -{ - if(pProperty.exist) { - mOutput << startstr << "<" << pTypeName << ">" << endstr; - PushTag(); - mOutput << startstr << "" << pProperty.value << "" << endstr; - PopTag(); - mOutput << startstr << "" << endstr; - } -} - -// ------------------------------------------------------------------------------------------------ -// Writes the material setup -void ColladaExporter::WriteMaterials() -{ - materials.resize( mScene->mNumMaterials); - - /// collect all materials from the scene - size_t numTextures = 0; - for( size_t a = 0; a < mScene->mNumMaterials; ++a ) - { - const aiMaterial* mat = mScene->mMaterials[a]; - - aiString name; - if( mat->Get( AI_MATKEY_NAME, name) != aiReturn_SUCCESS ) { - name = "mat"; - materials[a].name = std::string( "m") + to_string(a) + name.C_Str(); - } else { - // try to use the material's name if no other material has already taken it, else append # - std::string testName = name.C_Str(); - size_t materialCountWithThisName = 0; - for( size_t i = 0; i < a; i ++ ) { - if( materials[i].name == testName ) { - materialCountWithThisName ++; - } - } - if( materialCountWithThisName == 0 ) { - materials[a].name = name.C_Str(); - } else { - materials[a].name = std::string(name.C_Str()) + to_string(materialCountWithThisName); - } - } - - aiShadingMode shading = aiShadingMode_Flat; - materials[a].shading_model = "phong"; - if(mat->Get( AI_MATKEY_SHADING_MODEL, shading) == aiReturn_SUCCESS) { - if(shading == aiShadingMode_Phong) { - materials[a].shading_model = "phong"; - } else if(shading == aiShadingMode_Blinn) { - materials[a].shading_model = "blinn"; - } else if(shading == aiShadingMode_NoShading) { - materials[a].shading_model = "constant"; - } else if(shading == aiShadingMode_Gouraud) { - materials[a].shading_model = "lambert"; - } - } - - ReadMaterialSurface( materials[a].ambient, mat, aiTextureType_AMBIENT, AI_MATKEY_COLOR_AMBIENT); - if( !materials[a].ambient.texture.empty() ) numTextures++; - ReadMaterialSurface( materials[a].diffuse, mat, aiTextureType_DIFFUSE, AI_MATKEY_COLOR_DIFFUSE); - if( !materials[a].diffuse.texture.empty() ) numTextures++; - ReadMaterialSurface( materials[a].specular, mat, aiTextureType_SPECULAR, AI_MATKEY_COLOR_SPECULAR); - if( !materials[a].specular.texture.empty() ) numTextures++; - ReadMaterialSurface( materials[a].emissive, mat, aiTextureType_EMISSIVE, AI_MATKEY_COLOR_EMISSIVE); - if( !materials[a].emissive.texture.empty() ) numTextures++; - ReadMaterialSurface( materials[a].reflective, mat, aiTextureType_REFLECTION, AI_MATKEY_COLOR_REFLECTIVE); - if( !materials[a].reflective.texture.empty() ) numTextures++; - ReadMaterialSurface( materials[a].transparent, mat, aiTextureType_OPACITY, AI_MATKEY_COLOR_TRANSPARENT); - if( !materials[a].transparent.texture.empty() ) numTextures++; - ReadMaterialSurface( materials[a].normal, mat, aiTextureType_NORMALS, NULL, 0, 0); - if( !materials[a].normal.texture.empty() ) numTextures++; - - materials[a].shininess.exist = mat->Get( AI_MATKEY_SHININESS, materials[a].shininess.value) == aiReturn_SUCCESS; - materials[a].transparency.exist = mat->Get( AI_MATKEY_OPACITY, materials[a].transparency.value) == aiReturn_SUCCESS; - materials[a].index_refraction.exist = mat->Get( AI_MATKEY_REFRACTI, materials[a].index_refraction.value) == aiReturn_SUCCESS; - } - - // output textures if present - if( numTextures > 0 ) - { - mOutput << startstr << "" << endstr; - PushTag(); - for( std::vector::const_iterator it = materials.begin(); it != materials.end(); ++it ) - { - const Material& mat = *it; - WriteImageEntry( mat.ambient, mat.name + "-ambient-image"); - WriteImageEntry( mat.diffuse, mat.name + "-diffuse-image"); - WriteImageEntry( mat.specular, mat.name + "-specular-image"); - WriteImageEntry( mat.emissive, mat.name + "-emission-image"); - WriteImageEntry( mat.reflective, mat.name + "-reflective-image"); - WriteImageEntry( mat.transparent, mat.name + "-transparent-image"); - WriteImageEntry( mat.normal, mat.name + "-normal-image"); - } - PopTag(); - mOutput << startstr << "" << endstr; - } - - // output effects - those are the actual carriers of information - if( !materials.empty() ) - { - mOutput << startstr << "" << endstr; - PushTag(); - for( std::vector::const_iterator it = materials.begin(); it != materials.end(); ++it ) - { - const Material& mat = *it; - // this is so ridiculous it must be right - mOutput << startstr << "" << endstr; - PushTag(); - mOutput << startstr << "" << endstr; - PushTag(); - - // write sampler- and surface params for the texture entries - WriteTextureParamEntry( mat.emissive, "emission", mat.name); - WriteTextureParamEntry( mat.ambient, "ambient", mat.name); - WriteTextureParamEntry( mat.diffuse, "diffuse", mat.name); - WriteTextureParamEntry( mat.specular, "specular", mat.name); - WriteTextureParamEntry( mat.reflective, "reflective", mat.name); - WriteTextureParamEntry( mat.transparent, "transparent", mat.name); - WriteTextureParamEntry( mat.normal, "normal", mat.name); - - mOutput << startstr << "" << endstr; - PushTag(); - mOutput << startstr << "<" << mat.shading_model << ">" << endstr; - PushTag(); - - WriteTextureColorEntry( mat.emissive, "emission", mat.name + "-emission-sampler"); - WriteTextureColorEntry( mat.ambient, "ambient", mat.name + "-ambient-sampler"); - WriteTextureColorEntry( mat.diffuse, "diffuse", mat.name + "-diffuse-sampler"); - WriteTextureColorEntry( mat.specular, "specular", mat.name + "-specular-sampler"); - WriteFloatEntry(mat.shininess, "shininess"); - WriteTextureColorEntry( mat.reflective, "reflective", mat.name + "-reflective-sampler"); - WriteTextureColorEntry( mat.transparent, "transparent", mat.name + "-transparent-sampler"); - WriteFloatEntry(mat.transparency, "transparency"); - WriteFloatEntry(mat.index_refraction, "index_of_refraction"); - - if(! mat.normal.texture.empty()) { - WriteTextureColorEntry( mat.normal, "bump", mat.name + "-normal-sampler"); - } - - PopTag(); - mOutput << startstr << "" << endstr; - PopTag(); - mOutput << startstr << "" << endstr; - PopTag(); - mOutput << startstr << "" << endstr; - PopTag(); - mOutput << startstr << "" << endstr; - } - PopTag(); - mOutput << startstr << "" << endstr; - - // write materials - they're just effect references - mOutput << startstr << "" << endstr; - PushTag(); - for( std::vector::const_iterator it = materials.begin(); it != materials.end(); ++it ) - { - const Material& mat = *it; - mOutput << startstr << "" << endstr; - PushTag(); - mOutput << startstr << "" << endstr; - PopTag(); - mOutput << startstr << "" << endstr; - } - PopTag(); - mOutput << startstr << "" << endstr; - } -} - -// ------------------------------------------------------------------------------------------------ -// Writes the controller library -void ColladaExporter::WriteControllerLibrary() -{ - mOutput << startstr << "" << endstr; - PushTag(); - - for( size_t a = 0; a < mScene->mNumMeshes; ++a) { - WriteController( a); - } - - PopTag(); - mOutput << startstr << "" << endstr; -} - -// ------------------------------------------------------------------------------------------------ -// Writes a skin controller of the given mesh -void ColladaExporter::WriteController( size_t pIndex) -{ - const aiMesh* mesh = mScene->mMeshes[pIndex]; - const std::string idstr = mesh->mName.length == 0 ? GetMeshId(pIndex) : mesh->mName.C_Str(); - const std::string idstrEscaped = XMLIDEncode(idstr); - - if ( mesh->mNumFaces == 0 || mesh->mNumVertices == 0 ) - return; - - if ( mesh->mNumBones == 0 ) - return; - - mOutput << startstr << ""<< endstr; - PushTag(); - - mOutput << startstr << "" << endstr; - PushTag(); - - // bind pose matrix - mOutput << startstr << "" << endstr; - PushTag(); - - // I think it is identity in general cases. - aiMatrix4x4 mat; - mOutput << startstr << mat.a1 << " " << mat.a2 << " " << mat.a3 << " " << mat.a4 << endstr; - mOutput << startstr << mat.b1 << " " << mat.b2 << " " << mat.b3 << " " << mat.b4 << endstr; - mOutput << startstr << mat.c1 << " " << mat.c2 << " " << mat.c3 << " " << mat.c4 << endstr; - mOutput << startstr << mat.d1 << " " << mat.d2 << " " << mat.d3 << " " << mat.d4 << endstr; - - PopTag(); - mOutput << startstr << "" << endstr; - - mOutput << startstr << "" << endstr; - PushTag(); - - mOutput << startstr << "mNumBones << "\">"; - - for( size_t i = 0; i < mesh->mNumBones; ++i ) - mOutput << XMLIDEncode(mesh->mBones[i]->mName.C_Str()) << " "; - - mOutput << "" << endstr; - - mOutput << startstr << "" << endstr; - PushTag(); - - mOutput << startstr << "mNumBones << "\" stride=\"" << 1 << "\">" << endstr; - PushTag(); - - mOutput << startstr << "" << endstr; - - PopTag(); - mOutput << startstr << "" << endstr; - - PopTag(); - mOutput << startstr << "" << endstr; - - PopTag(); - mOutput << startstr << "" << endstr; - - std::vector bind_poses; - bind_poses.reserve(mesh->mNumBones * 16); - for(unsigned int i = 0; i < mesh->mNumBones; ++i) - for( unsigned int j = 0; j < 4; ++j) - bind_poses.insert(bind_poses.end(), mesh->mBones[i]->mOffsetMatrix[j], mesh->mBones[i]->mOffsetMatrix[j] + 4); - - WriteFloatArray( idstr + "-skin-bind_poses", FloatType_Mat4x4, (const ai_real*) bind_poses.data(), bind_poses.size() / 16); - - bind_poses.clear(); - - std::vector skin_weights; - skin_weights.reserve(mesh->mNumVertices * mesh->mNumBones); - for( size_t i = 0; i < mesh->mNumBones; ++i) - for( size_t j = 0; j < mesh->mBones[i]->mNumWeights; ++j) - skin_weights.push_back(mesh->mBones[i]->mWeights[j].mWeight); - - WriteFloatArray( idstr + "-skin-weights", FloatType_Weight, (const ai_real*) skin_weights.data(), skin_weights.size()); - - skin_weights.clear(); - - mOutput << startstr << "" << endstr; - PushTag(); - - mOutput << startstr << "" << endstr; - mOutput << startstr << "" << endstr; - - PopTag(); - mOutput << startstr << "" << endstr; - - mOutput << startstr << "mNumVertices << "\">" << endstr; - PushTag(); - - mOutput << startstr << "" << endstr; - mOutput << startstr << "" << endstr; - - mOutput << startstr << ""; - - std::vector num_influences(mesh->mNumVertices, (ai_uint)0); - for( size_t i = 0; i < mesh->mNumBones; ++i) - for( size_t j = 0; j < mesh->mBones[i]->mNumWeights; ++j) - ++num_influences[mesh->mBones[i]->mWeights[j].mVertexId]; - - for( size_t i = 0; i < mesh->mNumVertices; ++i) - mOutput << num_influences[i] << " "; - - mOutput << "" << endstr; - - mOutput << startstr << ""; - - ai_uint joint_weight_indices_length = 0; - std::vector accum_influences; - accum_influences.reserve(num_influences.size()); - for( size_t i = 0; i < num_influences.size(); ++i) - { - accum_influences.push_back(joint_weight_indices_length); - joint_weight_indices_length += num_influences[i]; - } - - ai_uint weight_index = 0; - std::vector joint_weight_indices(2 * joint_weight_indices_length, (ai_int)-1); - for( unsigned int i = 0; i < mesh->mNumBones; ++i) - for( unsigned j = 0; j < mesh->mBones[i]->mNumWeights; ++j) - { - unsigned int vId = mesh->mBones[i]->mWeights[j].mVertexId; - for( ai_uint k = 0; k < num_influences[vId]; ++k) - { - if (joint_weight_indices[2 * (accum_influences[vId] + k)] == -1) - { - joint_weight_indices[2 * (accum_influences[vId] + k)] = i; - joint_weight_indices[2 * (accum_influences[vId] + k) + 1] = weight_index; - break; - } - } - ++weight_index; - } - - for( size_t i = 0; i < joint_weight_indices.size(); ++i) - mOutput << joint_weight_indices[i] << " "; - - num_influences.clear(); - accum_influences.clear(); - joint_weight_indices.clear(); - - mOutput << "" << endstr; - - PopTag(); - mOutput << startstr << "" << endstr; - - PopTag(); - mOutput << startstr << "" << endstr; - - PopTag(); - mOutput << startstr << "" << endstr; -} - -// ------------------------------------------------------------------------------------------------ -// Writes the geometry library -void ColladaExporter::WriteGeometryLibrary() -{ - mOutput << startstr << "" << endstr; - PushTag(); - - for( size_t a = 0; a < mScene->mNumMeshes; ++a) - WriteGeometry( a); - - PopTag(); - mOutput << startstr << "" << endstr; -} - -// ------------------------------------------------------------------------------------------------ -// Writes the given mesh -void ColladaExporter::WriteGeometry( size_t pIndex) -{ - const aiMesh* mesh = mScene->mMeshes[pIndex]; - const std::string idstr = mesh->mName.length == 0 ? GetMeshId(pIndex) : mesh->mName.C_Str(); - const std::string geometryName = XMLEscape(idstr); - const std::string geometryId = XMLIDEncode(idstr); - - if ( mesh->mNumFaces == 0 || mesh->mNumVertices == 0 ) - return; - - // opening tag - mOutput << startstr << "" << endstr; - PushTag(); - - mOutput << startstr << "" << endstr; - PushTag(); - - // Positions - WriteFloatArray( idstr + "-positions", FloatType_Vector, (ai_real*) mesh->mVertices, mesh->mNumVertices); - // Normals, if any - if( mesh->HasNormals() ) - WriteFloatArray( idstr + "-normals", FloatType_Vector, (ai_real*) mesh->mNormals, mesh->mNumVertices); - - // texture coords - for( size_t a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a) - { - if( mesh->HasTextureCoords(static_cast(a)) ) - { - WriteFloatArray( idstr + "-tex" + to_string(a), mesh->mNumUVComponents[a] == 3 ? FloatType_TexCoord3 : FloatType_TexCoord2, - (ai_real*) mesh->mTextureCoords[a], mesh->mNumVertices); - } - } - - // vertex colors - for( size_t a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a) - { - if( mesh->HasVertexColors(static_cast(a)) ) - WriteFloatArray( idstr + "-color" + to_string(a), FloatType_Color, (ai_real*) mesh->mColors[a], mesh->mNumVertices); - } - - // assemble vertex structure - // Only write input for POSITION since we will write other as shared inputs in polygon definition - mOutput << startstr << "" << endstr; - PushTag(); - mOutput << startstr << "" << endstr; - PopTag(); - mOutput << startstr << "" << endstr; - - // count the number of lines, triangles and polygon meshes - int countLines = 0; - int countPoly = 0; - for( size_t a = 0; a < mesh->mNumFaces; ++a ) - { - if (mesh->mFaces[a].mNumIndices == 2) countLines++; - else if (mesh->mFaces[a].mNumIndices >= 3) countPoly++; - } - - // lines - if (countLines) - { - mOutput << startstr << "" << endstr; - PushTag(); - mOutput << startstr << "" << endstr; - if( mesh->HasNormals() ) - mOutput << startstr << "" << endstr; - for( size_t a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a ) - { - if( mesh->HasTextureCoords(static_cast(a)) ) - mOutput << startstr << "" << endstr; - } - for( size_t a = 0; a < AI_MAX_NUMBER_OF_COLOR_SETS; ++a ) - { - if( mesh->HasVertexColors(static_cast(a) ) ) - mOutput << startstr << "" << endstr; - } - - mOutput << startstr << "

"; - for( size_t a = 0; a < mesh->mNumFaces; ++a ) - { - const aiFace& face = mesh->mFaces[a]; - if (face.mNumIndices != 2) continue; - for( size_t b = 0; b < face.mNumIndices; ++b ) - mOutput << face.mIndices[b] << " "; - } - mOutput << "

" << endstr; - PopTag(); - mOutput << startstr << "" << endstr; - } - - // triangle - don't use it, because compatibility problems - - // polygons - if (countPoly) - { - mOutput << startstr << "" << endstr; - PushTag(); - mOutput << startstr << "" << endstr; - if( mesh->HasNormals() ) - mOutput << startstr << "" << endstr; - for( size_t a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a ) - { - if( mesh->HasTextureCoords(static_cast(a)) ) - mOutput << startstr << "" << endstr; - } - for( size_t a = 0; a < AI_MAX_NUMBER_OF_COLOR_SETS; ++a ) - { - if( mesh->HasVertexColors(static_cast(a) ) ) - mOutput << startstr << "" << endstr; - } - - mOutput << startstr << ""; - for( size_t a = 0; a < mesh->mNumFaces; ++a ) - { - if (mesh->mFaces[a].mNumIndices < 3) continue; - mOutput << mesh->mFaces[a].mNumIndices << " "; - } - mOutput << "" << endstr; - - mOutput << startstr << "

"; - for( size_t a = 0; a < mesh->mNumFaces; ++a ) - { - const aiFace& face = mesh->mFaces[a]; - if (face.mNumIndices < 3) continue; - for( size_t b = 0; b < face.mNumIndices; ++b ) - mOutput << face.mIndices[b] << " "; - } - mOutput << "

" << endstr; - PopTag(); - mOutput << startstr << "
" << endstr; - } - - // closing tags - PopTag(); - mOutput << startstr << "
" << endstr; - PopTag(); - mOutput << startstr << "" << endstr; -} - -// ------------------------------------------------------------------------------------------------ -// Writes a float array of the given type -void ColladaExporter::WriteFloatArray( const std::string& pIdString, FloatDataType pType, const ai_real* pData, size_t pElementCount) -{ - size_t floatsPerElement = 0; - switch( pType ) - { - case FloatType_Vector: floatsPerElement = 3; break; - case FloatType_TexCoord2: floatsPerElement = 2; break; - case FloatType_TexCoord3: floatsPerElement = 3; break; - case FloatType_Color: floatsPerElement = 3; break; - case FloatType_Mat4x4: floatsPerElement = 16; break; - case FloatType_Weight: floatsPerElement = 1; break; - case FloatType_Time: floatsPerElement = 1; break; - default: - return; - } - - std::string arrayId = XMLIDEncode(pIdString) + "-array"; - - mOutput << startstr << "" << endstr; - PushTag(); - - // source array - mOutput << startstr << " "; - PushTag(); - - if( pType == FloatType_TexCoord2 ) - { - for( size_t a = 0; a < pElementCount; ++a ) - { - mOutput << pData[a*3+0] << " "; - mOutput << pData[a*3+1] << " "; - } - } - else if( pType == FloatType_Color ) - { - for( size_t a = 0; a < pElementCount; ++a ) - { - mOutput << pData[a*4+0] << " "; - mOutput << pData[a*4+1] << " "; - mOutput << pData[a*4+2] << " "; - } - } - else - { - for( size_t a = 0; a < pElementCount * floatsPerElement; ++a ) - mOutput << pData[a] << " "; - } - mOutput << "" << endstr; - PopTag(); - - // the usual Collada fun. Let's bloat it even more! - mOutput << startstr << "" << endstr; - PushTag(); - mOutput << startstr << "" << endstr; - PushTag(); - - switch( pType ) - { - case FloatType_Vector: - mOutput << startstr << "" << endstr; - mOutput << startstr << "" << endstr; - mOutput << startstr << "" << endstr; - break; - - case FloatType_TexCoord2: - mOutput << startstr << "" << endstr; - mOutput << startstr << "" << endstr; - break; - - case FloatType_TexCoord3: - mOutput << startstr << "" << endstr; - mOutput << startstr << "" << endstr; - mOutput << startstr << "" << endstr; - break; - - case FloatType_Color: - mOutput << startstr << "" << endstr; - mOutput << startstr << "" << endstr; - mOutput << startstr << "" << endstr; - break; - - case FloatType_Mat4x4: - mOutput << startstr << "" << endstr; - break; - - case FloatType_Weight: - mOutput << startstr << "" << endstr; - break; - - // customized, add animation related - case FloatType_Time: - mOutput << startstr << "" << endstr; - break; - - } - - PopTag(); - mOutput << startstr << "" << endstr; - PopTag(); - mOutput << startstr << "" << endstr; - PopTag(); - mOutput << startstr << "" << endstr; -} - -// ------------------------------------------------------------------------------------------------ -// Writes the scene library -void ColladaExporter::WriteSceneLibrary() -{ - const std::string sceneName = XMLEscape(mScene->mRootNode->mName.C_Str()); - const std::string sceneId = XMLIDEncode(mScene->mRootNode->mName.C_Str()); - - mOutput << startstr << "" << endstr; - PushTag(); - mOutput << startstr << "" << endstr; - PushTag(); - - // start recursive write at the root node - for( size_t a = 0; a < mScene->mRootNode->mNumChildren; ++a ) - WriteNode( mScene, mScene->mRootNode->mChildren[a]); - - PopTag(); - mOutput << startstr << "" << endstr; - PopTag(); - mOutput << startstr << "" << endstr; -} -// ------------------------------------------------------------------------------------------------ -void ColladaExporter::WriteAnimationLibrary(size_t pIndex) -{ - static const float kSecondsFromMilliseconds = .001f; - - const aiAnimation * anim = mScene->mAnimations[pIndex]; - - if ( anim->mNumChannels == 0 && anim->mNumMeshChannels == 0 && anim->mNumMorphMeshChannels ==0 ) { - return; - } - - const std::string animation_name_escaped = XMLEscape( anim->mName.C_Str() ); - std::string idstr = anim->mName.C_Str(); - std::string ending = std::string( "AnimId" ) + to_string(pIndex); - if (idstr.length() >= ending.length()) { - if (0 != idstr.compare (idstr.length() - ending.length(), ending.length(), ending)) { - idstr = idstr + ending; - } - } else { - idstr = idstr + ending; - } - - const std::string idstrEscaped = XMLIDEncode(idstr); - - mOutput << startstr << "" << endstr; - PushTag(); - - std::string cur_node_idstr; - for (size_t a = 0; a < anim->mNumChannels; ++a) { - const aiNodeAnim * nodeAnim = anim->mChannels[a]; - - // sanity check - if (nodeAnim->mNumPositionKeys != nodeAnim->mNumScalingKeys || nodeAnim->mNumPositionKeys != nodeAnim->mNumRotationKeys) { - continue; - } - - { - cur_node_idstr.clear(); - cur_node_idstr += nodeAnim->mNodeName.data; - cur_node_idstr += std::string("_matrix-input"); - - std::vector frames; - for( size_t i = 0; i < nodeAnim->mNumPositionKeys; ++i) { - frames.push_back(static_cast(nodeAnim->mPositionKeys[i].mTime) * kSecondsFromMilliseconds); - } - - WriteFloatArray(cur_node_idstr, FloatType_Time, (const ai_real *)frames.data(), frames.size()); - frames.clear(); - } - - { - cur_node_idstr.clear(); - - cur_node_idstr += nodeAnim->mNodeName.data; - cur_node_idstr += std::string("_matrix-output"); - - std::vector keyframes; - keyframes.reserve(nodeAnim->mNumPositionKeys * 16); - for( size_t i = 0; i < nodeAnim->mNumPositionKeys; ++i) { - aiVector3D Scaling = nodeAnim->mScalingKeys[i].mValue; - aiMatrix4x4 ScalingM; // identity - ScalingM[0][0] = Scaling.x; ScalingM[1][1] = Scaling.y; ScalingM[2][2] = Scaling.z; - - aiQuaternion RotationQ = nodeAnim->mRotationKeys[i].mValue; - aiMatrix4x4 s = aiMatrix4x4( RotationQ.GetMatrix() ); - aiMatrix4x4 RotationM(s.a1, s.a2, s.a3, 0, s.b1, s.b2, s.b3, 0, s.c1, s.c2, s.c3, 0, 0, 0, 0, 1); - - aiVector3D Translation = nodeAnim->mPositionKeys[i].mValue; - aiMatrix4x4 TranslationM; // identity - TranslationM[0][3] = Translation.x; TranslationM[1][3] = Translation.y; TranslationM[2][3] = Translation.z; - - // Combine the above transformations - aiMatrix4x4 mat = TranslationM * RotationM * ScalingM; - - for( unsigned int j = 0; j < 4; ++j) { - keyframes.insert(keyframes.end(), mat[j], mat[j] + 4); - } - } - - WriteFloatArray(cur_node_idstr, FloatType_Mat4x4, (const ai_real *)keyframes.data(), keyframes.size() / 16); - } - - { - std::vector names; - for ( size_t i = 0; i < nodeAnim->mNumPositionKeys; ++i) { - if ( nodeAnim->mPreState == aiAnimBehaviour_DEFAULT - || nodeAnim->mPreState == aiAnimBehaviour_LINEAR - || nodeAnim->mPreState == aiAnimBehaviour_REPEAT - ) { - names.push_back( "LINEAR" ); - } else if (nodeAnim->mPostState == aiAnimBehaviour_CONSTANT) { - names.push_back( "STEP" ); - } - } - - const std::string cur_node_idstr2 = nodeAnim->mNodeName.data + std::string("_matrix-interpolation"); - std::string arrayId = XMLIDEncode(cur_node_idstr2) + "-array"; - - mOutput << startstr << "" << endstr; - PushTag(); - - // source array - mOutput << startstr << " "; - for( size_t aa = 0; aa < names.size(); ++aa ) { - mOutput << names[aa] << " "; - } - mOutput << "" << endstr; - - mOutput << startstr << "" << endstr; - PushTag(); - - mOutput << startstr << "" << endstr; - PushTag(); - - mOutput << startstr << "" << endstr; - - PopTag(); - mOutput << startstr << "" << endstr; - - PopTag(); - mOutput << startstr << "" << endstr; - - PopTag(); - mOutput << startstr << "" << endstr; - } - } - - for (size_t a = 0; a < anim->mNumChannels; ++a) { - const aiNodeAnim * nodeAnim = anim->mChannels[a]; - - { - // samplers - const std::string node_idstr = nodeAnim->mNodeName.data + std::string("_matrix-sampler"); - mOutput << startstr << "" << endstr; - PushTag(); - - mOutput << startstr << "mNodeName.data + std::string("_matrix-input") ) << "\"/>" << endstr; - mOutput << startstr << "mNodeName.data + std::string("_matrix-output") ) << "\"/>" << endstr; - mOutput << startstr << "mNodeName.data + std::string("_matrix-interpolation") ) << "\"/>" << endstr; - - PopTag(); - mOutput << startstr << "" << endstr; - } - } - - for (size_t a = 0; a < anim->mNumChannels; ++a) { - const aiNodeAnim * nodeAnim = anim->mChannels[a]; - - { - // channels - mOutput << startstr << "mNodeName.data + std::string("_matrix-sampler") ) << "\" target=\"" << XMLIDEncode(nodeAnim->mNodeName.data) << "/matrix\"/>" << endstr; - } - } - - PopTag(); - mOutput << startstr << "" << endstr; - -} -// ------------------------------------------------------------------------------------------------ -void ColladaExporter::WriteAnimationsLibrary() -{ - if ( mScene->mNumAnimations > 0 ) { - mOutput << startstr << "" << endstr; - PushTag(); - - // start recursive write at the root node - for( size_t a = 0; a < mScene->mNumAnimations; ++a) - WriteAnimationLibrary( a ); - - PopTag(); - mOutput << startstr << "" << endstr; - } -} -// ------------------------------------------------------------------------------------------------ -// Helper to find a bone by name in the scene -aiBone* findBone( const aiScene* scene, const char * name) { - for (size_t m=0; mmNumMeshes; m++) { - aiMesh * mesh = scene->mMeshes[m]; - for (size_t b=0; bmNumBones; b++) { - aiBone * bone = mesh->mBones[b]; - if (0 == strcmp(name, bone->mName.C_Str())) { - return bone; - } - } - } - return NULL; -} - -// ------------------------------------------------------------------------------------------------ -const aiNode * findBoneNode( const aiNode* aNode, const aiBone* bone) -{ - if ( aNode && bone && aNode->mName == bone->mName ) { - return aNode; - } - - if ( aNode && bone ) { - for (unsigned int i=0; i < aNode->mNumChildren; ++i) { - aiNode * aChild = aNode->mChildren[i]; - const aiNode * foundFromChild = 0; - if ( aChild ) { - foundFromChild = findBoneNode( aChild, bone ); - if ( foundFromChild ) return foundFromChild; - } - } - } - - return NULL; -} - -const aiNode * findSkeletonRootNode( const aiScene* scene, const aiMesh * mesh) -{ - std::set topParentBoneNodes; - if ( mesh && mesh->mNumBones > 0 ) { - for (unsigned int i=0; i < mesh->mNumBones; ++i) { - aiBone * bone = mesh->mBones[i]; - - const aiNode * node = findBoneNode( scene->mRootNode, bone); - if ( node ) { - while ( node->mParent && findBone(scene, node->mParent->mName.C_Str() ) != 0 ) { - node = node->mParent; - } - topParentBoneNodes.insert( node ); - } - } - } - - if ( !topParentBoneNodes.empty() ) { - const aiNode * parentBoneNode = *topParentBoneNodes.begin(); - if ( topParentBoneNodes.size() == 1 ) { - return parentBoneNode; - } else { - for (auto it : topParentBoneNodes) { - if ( it->mParent ) return it->mParent; - } - return parentBoneNode; - } - } - - return NULL; -} - -// ------------------------------------------------------------------------------------------------ -// Recursively writes the given node -void ColladaExporter::WriteNode( const aiScene* pScene, aiNode* pNode) -{ - // the node must have a name - if (pNode->mName.length == 0) - { - std::stringstream ss; - ss << "Node_" << pNode; - pNode->mName.Set(ss.str()); - } - - // If the node is associated with a bone, it is a joint node (JOINT) - // otherwise it is a normal node (NODE) - const char * node_type; - bool is_joint, is_skeleton_root = false; - if (nullptr == findBone(pScene, pNode->mName.C_Str())) { - node_type = "NODE"; - is_joint = false; - } else { - node_type = "JOINT"; - is_joint = true; - if (!pNode->mParent || nullptr == findBone(pScene, pNode->mParent->mName.C_Str())) { - is_skeleton_root = true; - } - } - - const std::string node_id = XMLIDEncode(pNode->mName.data); - const std::string node_name = XMLEscape(pNode->mName.data); - mOutput << startstr << "" << endstr; - PushTag(); - - // write transformation - we can directly put the matrix there - // TODO: (thom) decompose into scale - rot - quad to allow addressing it by animations afterwards - aiMatrix4x4 mat = pNode->mTransformation; - - // If this node is a Camera node, the camera coordinate system needs to be multiplied in. - // When importing from Collada, the mLookAt is set to 0, 0, -1, and the node transform is unchanged. - // When importing from a different format, mLookAt is set to 0, 0, 1. Therefore, the local camera - // coordinate system must be changed to matche the Collada specification. - for (size_t i = 0; imNumCameras; i++){ - if (mScene->mCameras[i]->mName == pNode->mName){ - aiMatrix4x4 sourceView; - mScene->mCameras[i]->GetCameraMatrix(sourceView); - - aiMatrix4x4 colladaView; - colladaView.a1 = colladaView.c3 = -1; // move into -z space. - mat *= (sourceView * colladaView); - break; - } - } - - // customized, sid should be 'matrix' to match with loader code. - //mOutput << startstr << ""; - mOutput << startstr << ""; - - mOutput << mat.a1 << " " << mat.a2 << " " << mat.a3 << " " << mat.a4 << " "; - mOutput << mat.b1 << " " << mat.b2 << " " << mat.b3 << " " << mat.b4 << " "; - mOutput << mat.c1 << " " << mat.c2 << " " << mat.c3 << " " << mat.c4 << " "; - mOutput << mat.d1 << " " << mat.d2 << " " << mat.d3 << " " << mat.d4; - mOutput << "" << endstr; - - if(pNode->mNumMeshes==0){ - //check if it is a camera node - for(size_t i=0; imNumCameras; i++){ - if(mScene->mCameras[i]->mName == pNode->mName){ - mOutput << startstr <<"" << endstr; - break; - } - } - //check if it is a light node - for(size_t i=0; imNumLights; i++){ - if(mScene->mLights[i]->mName == pNode->mName){ - mOutput << startstr <<"" << endstr; - break; - } - } - - }else - // instance every geometry - for( size_t a = 0; a < pNode->mNumMeshes; ++a ) - { - const aiMesh* mesh = mScene->mMeshes[pNode->mMeshes[a]]; - // do not instantiate mesh if empty. I wonder how this could happen - if( mesh->mNumFaces == 0 || mesh->mNumVertices == 0 ) - continue; - - const std::string meshName = mesh->mName.length == 0 ? GetMeshId(pNode->mMeshes[a]) : mesh->mName.C_Str(); - - if( mesh->mNumBones == 0 ) - { - mOutput << startstr << "" << endstr; - PushTag(); - } - else - { - mOutput << startstr - << "" - << endstr; - PushTag(); - - // note! this mFoundSkeletonRootNodeID some how affects animation, it makes the mesh attaches to armature skeleton root node. - // use the first bone to find skeleton root - const aiNode * skeletonRootBoneNode = findSkeletonRootNode( pScene, mesh ); - if ( skeletonRootBoneNode ) { - mFoundSkeletonRootNodeID = XMLIDEncode( skeletonRootBoneNode->mName.C_Str() ); - } - mOutput << startstr << "#" << mFoundSkeletonRootNodeID << "" << endstr; - } - mOutput << startstr << "" << endstr; - PushTag(); - mOutput << startstr << "" << endstr; - PushTag(); - mOutput << startstr << "mMaterialIndex].name) << "\">" << endstr; - PushTag(); - for( size_t aa = 0; aa < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++aa ) - { - if( mesh->HasTextureCoords( static_cast(aa) ) ) - // semantic as in - // input_semantic as in - // input_set as in - mOutput << startstr << "" << endstr; - } - PopTag(); - mOutput << startstr << "" << endstr; - PopTag(); - mOutput << startstr << "" << endstr; - PopTag(); - mOutput << startstr << "" << endstr; - - PopTag(); - if( mesh->mNumBones == 0) - mOutput << startstr << "" << endstr; - else - mOutput << startstr << "" << endstr; - } - - // recurse into subnodes - for( size_t a = 0; a < pNode->mNumChildren; ++a ) - WriteNode( pScene, pNode->mChildren[a]); - - PopTag(); - mOutput << startstr << "" << endstr; -} - -#endif -#endif diff --git a/code/Common/AssertHandler.cpp b/code/Common/AssertHandler.cpp new file mode 100644 index 000000000..63b64f828 --- /dev/null +++ b/code/Common/AssertHandler.cpp @@ -0,0 +1,72 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2020, 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 AssertHandler.cpp + * @brief Implementation of assert handling logic. + */ + +#include "AssertHandler.h" + +#include +#include + +void Assimp::defaultAiAssertHandler(const char* failedExpression, const char* file, int line) +{ + std::cerr << "ai_assert failure in " << file << "(" << line << "): " << failedExpression << std::endl; + std::abort(); +} + +namespace +{ + Assimp::AiAssertHandler s_handler = Assimp::defaultAiAssertHandler; +} + +void Assimp::setAiAssertHandler(AiAssertHandler handler) +{ + s_handler = handler; +} + +void Assimp::aiAssertViolation(const char* failedExpression, const char* file, int line) +{ + s_handler(failedExpression, file, line); +} diff --git a/code/Common/AssertHandler.h b/code/Common/AssertHandler.h new file mode 100644 index 000000000..2515f0bf2 --- /dev/null +++ b/code/Common/AssertHandler.h @@ -0,0 +1,75 @@ +/* +Open Asset Import Library (assimp) +---------------------------------------------------------------------- + +Copyright (c) 2006-2020, 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 Provides facilities to replace the default assert handler. */ + +#ifndef INCLUDED_AI_ASSERTHANDLER_H +#define INCLUDED_AI_ASSERTHANDLER_H + +#include +#include + +namespace Assimp +{ + // --------------------------------------------------------------------------- + /** Signature of functions which handle assert violations. + */ + using AiAssertHandler = void (*)(const char* failedExpression, const char* file, int line); + + // --------------------------------------------------------------------------- + /** Set the assert handler. + */ + ASSIMP_API void setAiAssertHandler(AiAssertHandler handler); + + // --------------------------------------------------------------------------- + /** The assert handler which is set by default. + * + * This issues a message to stderr and calls abort. + */ + ASSIMP_API void defaultAiAssertHandler(const char* failedExpression, const char* file, int line); + + // --------------------------------------------------------------------------- + /** Dispatches an assert violation to the assert handler. + */ + ASSIMP_API void aiAssertViolation(const char* failedExpression, const char* file, int line); +} // end of namespace Assimp + +#endif // INCLUDED_AI_ASSERTHANDLER_H \ No newline at end of file diff --git a/code/Common/Assimp.cpp b/code/Common/Assimp.cpp index 86ddb92c1..33de72e0f 100644 --- a/code/Common/Assimp.cpp +++ b/code/Common/Assimp.cpp @@ -113,7 +113,7 @@ class LogToCallbackRedirector : public LogStream { public: explicit LogToCallbackRedirector(const aiLogStream &s) : stream(s) { - ai_assert(NULL != s.callback); + ai_assert(nullptr != s.callback); } ~LogToCallbackRedirector() { @@ -154,20 +154,20 @@ void ReportSceneNotFoundError() { // ------------------------------------------------------------------------------------------------ // Reads the given file and returns its content. const aiScene *aiImportFile(const char *pFile, unsigned int pFlags) { - return aiImportFileEx(pFile, pFlags, NULL); + return aiImportFileEx(pFile, pFlags, nullptr); } // ------------------------------------------------------------------------------------------------ const aiScene *aiImportFileEx(const char *pFile, unsigned int pFlags, aiFileIO *pFS) { - return aiImportFileExWithProperties(pFile, pFlags, pFS, NULL); + return aiImportFileExWithProperties(pFile, pFlags, pFS, nullptr); } // ------------------------------------------------------------------------------------------------ const aiScene *aiImportFileExWithProperties(const char *pFile, unsigned int pFlags, aiFileIO *pFS, const aiPropertyStore *props) { - ai_assert(NULL != pFile); + ai_assert(nullptr != pFile); - const aiScene *scene = NULL; + const aiScene *scene = nullptr; ASSIMP_BEGIN_EXCEPTION_REGION(); // create an Importer for this file @@ -200,7 +200,7 @@ const aiScene *aiImportFileExWithProperties(const char *pFile, unsigned int pFla delete imp; } - // return imported data. If the import failed the pointer is NULL anyways + // return imported data. If the import failed the pointer is nullptr anyways ASSIMP_END_EXCEPTION_REGION(const aiScene *); return scene; @@ -212,7 +212,7 @@ const aiScene *aiImportFileFromMemory( unsigned int pLength, unsigned int pFlags, const char *pHint) { - return aiImportFileFromMemoryWithProperties(pBuffer, pLength, pFlags, pHint, NULL); + return aiImportFileFromMemoryWithProperties(pBuffer, pLength, pFlags, pHint, nullptr); } // ------------------------------------------------------------------------------------------------ @@ -222,10 +222,10 @@ const aiScene *aiImportFileFromMemoryWithProperties( unsigned int pFlags, const char *pHint, const aiPropertyStore *props) { - ai_assert(NULL != pBuffer); + ai_assert(nullptr != pBuffer); ai_assert(0 != pLength); - const aiScene *scene = NULL; + const aiScene *scene = nullptr; ASSIMP_BEGIN_EXCEPTION_REGION(); // create an Importer for this file @@ -253,7 +253,7 @@ const aiScene *aiImportFileFromMemoryWithProperties( gLastErrorString = imp->GetErrorString(); delete imp; } - // return imported data. If the import failed the pointer is NULL anyways + // return imported data. If the import failed the pointer is nullptr anyways ASSIMP_END_EXCEPTION_REGION(const aiScene *); return scene; } @@ -285,7 +285,7 @@ void aiReleaseImport(const aiScene *pScene) { // ------------------------------------------------------------------------------------------------ ASSIMP_API const aiScene *aiApplyPostProcessing(const aiScene *pScene, unsigned int pFlags) { - const aiScene *sc = NULL; + const aiScene *sc = nullptr; ASSIMP_BEGIN_EXCEPTION_REGION(); @@ -293,14 +293,14 @@ ASSIMP_API const aiScene *aiApplyPostProcessing(const aiScene *pScene, const ScenePrivateData *priv = ScenePriv(pScene); if (!priv || !priv->mOrigImporter) { ReportSceneNotFoundError(); - return NULL; + return nullptr; } sc = priv->mOrigImporter->ApplyPostProcessing(pFlags); if (!sc) { aiReleaseImport(pScene); - return NULL; + return nullptr; } ASSIMP_END_EXCEPTION_REGION(const aiScene *); @@ -311,22 +311,22 @@ ASSIMP_API const aiScene *aiApplyPostProcessing(const aiScene *pScene, ASSIMP_API const aiScene *aiApplyCustomizedPostProcessing(const aiScene *scene, BaseProcess *process, bool requestValidation) { - const aiScene *sc(NULL); + const aiScene *sc(nullptr); ASSIMP_BEGIN_EXCEPTION_REGION(); // find the importer associated with this data const ScenePrivateData *priv = ScenePriv(scene); - if (NULL == priv || NULL == priv->mOrigImporter) { + if (nullptr == priv || nullptr == priv->mOrigImporter) { ReportSceneNotFoundError(); - return NULL; + return nullptr; } sc = priv->mOrigImporter->ApplyCustomizedPostProcessing(process, requestValidation); if (!sc) { aiReleaseImport(scene); - return NULL; + return nullptr; } ASSIMP_END_EXCEPTION_REGION(const aiScene *); @@ -336,8 +336,8 @@ ASSIMP_API const aiScene *aiApplyCustomizedPostProcessing(const aiScene *scene, // ------------------------------------------------------------------------------------------------ void CallbackToLogRedirector(const char *msg, char *dt) { - ai_assert(NULL != msg); - ai_assert(NULL != dt); + ai_assert(nullptr != msg); + ai_assert(nullptr != dt); LogStream *s = (LogStream *)dt; s->write(msg); @@ -350,8 +350,8 @@ ASSIMP_API aiLogStream aiGetPredefinedLogStream(aiDefaultLogStream pStream, cons ASSIMP_BEGIN_EXCEPTION_REGION(); LogStream *stream = LogStream::createDefaultStream(pStream, file); if (!stream) { - sout.callback = NULL; - sout.user = NULL; + sout.callback = nullptr; + sout.user = nullptr; } else { sout.callback = &CallbackToLogRedirector; sout.user = (char *)stream; @@ -373,7 +373,7 @@ ASSIMP_API void aiAttachLogStream(const aiLogStream *stream) { gActiveLogStreams[*stream] = lg; if (DefaultLogger::isNullLogger()) { - DefaultLogger::create(NULL, (gVerboseLogging == AI_TRUE ? Logger::VERBOSE : Logger::NORMAL)); + DefaultLogger::create(nullptr, (gVerboseLogging == AI_TRUE ? Logger::VERBOSE : Logger::NORMAL)); } DefaultLogger::get()->attachStream(lg); ASSIMP_END_EXCEPTION_REGION(void); @@ -392,7 +392,7 @@ ASSIMP_API aiReturn aiDetachLogStream(const aiLogStream *stream) { if (it == gActiveLogStreams.end()) { return AI_FAILURE; } - DefaultLogger::get()->detachStream( it->second ); + DefaultLogger::get()->detachStream(it->second); delete it->second; gActiveLogStreams.erase(it); @@ -411,12 +411,12 @@ ASSIMP_API void aiDetachAllLogStreams(void) { std::lock_guard lock(gLogStreamMutex); #endif Logger *logger(DefaultLogger::get()); - if (NULL == logger) { + if (nullptr == logger) { return; } for (LogStreamMap::iterator it = gActiveLogStreams.begin(); it != gActiveLogStreams.end(); ++it) { - logger->detachStream( it->second ); + logger->detachStream(it->second); delete it->second; } gActiveLogStreams.clear(); @@ -454,7 +454,7 @@ size_t aiGetImportFormatCount(void) { // ------------------------------------------------------------------------------------------------ // Returns the error text of the last failed import process. aiBool aiIsExtensionSupported(const char *szExtension) { - ai_assert(NULL != szExtension); + ai_assert(nullptr != szExtension); aiBool candoit = AI_FALSE; ASSIMP_BEGIN_EXCEPTION_REGION(); @@ -469,7 +469,7 @@ aiBool aiIsExtensionSupported(const char *szExtension) { // ------------------------------------------------------------------------------------------------ // Get a list of all file extensions supported by ASSIMP void aiGetExtensionList(aiString *szOut) { - ai_assert(NULL != szOut); + ai_assert(nullptr != szOut); ASSIMP_BEGIN_EXCEPTION_REGION(); // FIXME: no need to create a temporary Importer instance just for that .. @@ -553,8 +553,8 @@ ASSIMP_API void aiSetImportPropertyMatrix(aiPropertyStore *p, const char *szName // ------------------------------------------------------------------------------------------------ // Rotation matrix to quaternion ASSIMP_API void aiCreateQuaternionFromMatrix(aiQuaternion *quat, const aiMatrix3x3 *mat) { - ai_assert(NULL != quat); - ai_assert(NULL != mat); + ai_assert(nullptr != quat); + ai_assert(nullptr != mat); *quat = aiQuaternion(*mat); } @@ -563,23 +563,23 @@ ASSIMP_API void aiCreateQuaternionFromMatrix(aiQuaternion *quat, const aiMatrix3 ASSIMP_API void aiDecomposeMatrix(const aiMatrix4x4 *mat, aiVector3D *scaling, aiQuaternion *rotation, aiVector3D *position) { - ai_assert(NULL != rotation); - ai_assert(NULL != position); - ai_assert(NULL != scaling); - ai_assert(NULL != mat); + ai_assert(nullptr != rotation); + ai_assert(nullptr != position); + ai_assert(nullptr != scaling); + ai_assert(nullptr != mat); mat->Decompose(*scaling, *rotation, *position); } // ------------------------------------------------------------------------------------------------ // Matrix transpose ASSIMP_API void aiTransposeMatrix3(aiMatrix3x3 *mat) { - ai_assert(NULL != mat); + ai_assert(nullptr != mat); mat->Transpose(); } // ------------------------------------------------------------------------------------------------ ASSIMP_API void aiTransposeMatrix4(aiMatrix4x4 *mat) { - ai_assert(NULL != mat); + ai_assert(nullptr != mat); mat->Transpose(); } @@ -587,16 +587,16 @@ ASSIMP_API void aiTransposeMatrix4(aiMatrix4x4 *mat) { // Vector transformation ASSIMP_API void aiTransformVecByMatrix3(aiVector3D *vec, const aiMatrix3x3 *mat) { - ai_assert(NULL != mat); - ai_assert(NULL != vec); + ai_assert(nullptr != mat); + ai_assert(nullptr != vec); *vec *= (*mat); } // ------------------------------------------------------------------------------------------------ ASSIMP_API void aiTransformVecByMatrix4(aiVector3D *vec, const aiMatrix4x4 *mat) { - ai_assert(NULL != mat); - ai_assert(NULL != vec); + ai_assert(nullptr != mat); + ai_assert(nullptr != vec); *vec *= (*mat); } @@ -606,8 +606,8 @@ ASSIMP_API void aiTransformVecByMatrix4(aiVector3D *vec, ASSIMP_API void aiMultiplyMatrix4( aiMatrix4x4 *dst, const aiMatrix4x4 *src) { - ai_assert(NULL != dst); - ai_assert(NULL != src); + ai_assert(nullptr != dst); + ai_assert(nullptr != src); *dst = (*dst) * (*src); } @@ -615,8 +615,8 @@ ASSIMP_API void aiMultiplyMatrix4( ASSIMP_API void aiMultiplyMatrix3( aiMatrix3x3 *dst, const aiMatrix3x3 *src) { - ai_assert(NULL != dst); - ai_assert(NULL != src); + ai_assert(nullptr != dst); + ai_assert(nullptr != src); *dst = (*dst) * (*src); } @@ -624,23 +624,23 @@ ASSIMP_API void aiMultiplyMatrix3( // Matrix identity ASSIMP_API void aiIdentityMatrix3( aiMatrix3x3 *mat) { - ai_assert(NULL != mat); + ai_assert(nullptr != mat); *mat = aiMatrix3x3(); } // ------------------------------------------------------------------------------------------------ ASSIMP_API void aiIdentityMatrix4( aiMatrix4x4 *mat) { - ai_assert(NULL != mat); + ai_assert(nullptr != mat); *mat = aiMatrix4x4(); } // ------------------------------------------------------------------------------------------------ ASSIMP_API C_STRUCT const aiImporterDesc *aiGetImporterDesc(const char *extension) { - if (NULL == extension) { - return NULL; + if (nullptr == extension) { + return nullptr; } - const aiImporterDesc *desc(NULL); + const aiImporterDesc *desc(nullptr); std::vector out; GetImporterInstanceList(out); for (size_t i = 0; i < out.size(); ++i) { @@ -659,8 +659,8 @@ ASSIMP_API C_STRUCT const aiImporterDesc *aiGetImporterDesc(const char *extensio ASSIMP_API int aiVector2AreEqual( const C_STRUCT aiVector2D *a, const C_STRUCT aiVector2D *b) { - ai_assert(NULL != a); - ai_assert(NULL != b); + ai_assert(nullptr != a); + ai_assert(nullptr != b); return *a == *b; } @@ -669,8 +669,8 @@ ASSIMP_API int aiVector2AreEqualEpsilon( const C_STRUCT aiVector2D *a, const C_STRUCT aiVector2D *b, const float epsilon) { - ai_assert(NULL != a); - ai_assert(NULL != b); + ai_assert(nullptr != a); + ai_assert(nullptr != b); return a->Equal(*b, epsilon); } @@ -678,8 +678,8 @@ ASSIMP_API int aiVector2AreEqualEpsilon( ASSIMP_API void aiVector2Add( C_STRUCT aiVector2D *dst, const C_STRUCT aiVector2D *src) { - ai_assert(NULL != dst); - ai_assert(NULL != src); + ai_assert(nullptr != dst); + ai_assert(nullptr != src); *dst = *dst + *src; } @@ -687,8 +687,8 @@ ASSIMP_API void aiVector2Add( ASSIMP_API void aiVector2Subtract( C_STRUCT aiVector2D *dst, const C_STRUCT aiVector2D *src) { - ai_assert(NULL != dst); - ai_assert(NULL != src); + ai_assert(nullptr != dst); + ai_assert(nullptr != src); *dst = *dst - *src; } @@ -696,7 +696,7 @@ ASSIMP_API void aiVector2Subtract( ASSIMP_API void aiVector2Scale( C_STRUCT aiVector2D *dst, const float s) { - ai_assert(NULL != dst); + ai_assert(nullptr != dst); *dst *= s; } @@ -704,8 +704,8 @@ ASSIMP_API void aiVector2Scale( ASSIMP_API void aiVector2SymMul( C_STRUCT aiVector2D *dst, const C_STRUCT aiVector2D *other) { - ai_assert(NULL != dst); - ai_assert(NULL != other); + ai_assert(nullptr != dst); + ai_assert(nullptr != other); *dst = dst->SymMul(*other); } @@ -713,7 +713,7 @@ ASSIMP_API void aiVector2SymMul( ASSIMP_API void aiVector2DivideByScalar( C_STRUCT aiVector2D *dst, const float s) { - ai_assert(NULL != dst); + ai_assert(nullptr != dst); *dst /= s; } @@ -721,29 +721,29 @@ ASSIMP_API void aiVector2DivideByScalar( ASSIMP_API void aiVector2DivideByVector( C_STRUCT aiVector2D *dst, C_STRUCT aiVector2D *v) { - ai_assert(NULL != dst); - ai_assert(NULL != v); + ai_assert(nullptr != dst); + ai_assert(nullptr != v); *dst = *dst / *v; } // ------------------------------------------------------------------------------------------------ ASSIMP_API float aiVector2Length( const C_STRUCT aiVector2D *v) { - ai_assert(NULL != v); + ai_assert(nullptr != v); return v->Length(); } // ------------------------------------------------------------------------------------------------ ASSIMP_API float aiVector2SquareLength( const C_STRUCT aiVector2D *v) { - ai_assert(NULL != v); + ai_assert(nullptr != v); return v->SquareLength(); } // ------------------------------------------------------------------------------------------------ ASSIMP_API void aiVector2Negate( C_STRUCT aiVector2D *dst) { - ai_assert(NULL != dst); + ai_assert(nullptr != dst); *dst = -(*dst); } @@ -751,15 +751,15 @@ ASSIMP_API void aiVector2Negate( ASSIMP_API float aiVector2DotProduct( const C_STRUCT aiVector2D *a, const C_STRUCT aiVector2D *b) { - ai_assert(NULL != a); - ai_assert(NULL != b); + ai_assert(nullptr != a); + ai_assert(nullptr != b); return (*a) * (*b); } // ------------------------------------------------------------------------------------------------ ASSIMP_API void aiVector2Normalize( C_STRUCT aiVector2D *v) { - ai_assert(NULL != v); + ai_assert(nullptr != v); v->Normalize(); } @@ -767,8 +767,8 @@ ASSIMP_API void aiVector2Normalize( ASSIMP_API int aiVector3AreEqual( const C_STRUCT aiVector3D *a, const C_STRUCT aiVector3D *b) { - ai_assert(NULL != a); - ai_assert(NULL != b); + ai_assert(nullptr != a); + ai_assert(nullptr != b); return *a == *b; } @@ -777,8 +777,8 @@ ASSIMP_API int aiVector3AreEqualEpsilon( const C_STRUCT aiVector3D *a, const C_STRUCT aiVector3D *b, const float epsilon) { - ai_assert(NULL != a); - ai_assert(NULL != b); + ai_assert(nullptr != a); + ai_assert(nullptr != b); return a->Equal(*b, epsilon); } @@ -786,8 +786,8 @@ ASSIMP_API int aiVector3AreEqualEpsilon( ASSIMP_API int aiVector3LessThan( const C_STRUCT aiVector3D *a, const C_STRUCT aiVector3D *b) { - ai_assert(NULL != a); - ai_assert(NULL != b); + ai_assert(nullptr != a); + ai_assert(nullptr != b); return *a < *b; } @@ -795,8 +795,8 @@ ASSIMP_API int aiVector3LessThan( ASSIMP_API void aiVector3Add( C_STRUCT aiVector3D *dst, const C_STRUCT aiVector3D *src) { - ai_assert(NULL != dst); - ai_assert(NULL != src); + ai_assert(nullptr != dst); + ai_assert(nullptr != src); *dst = *dst + *src; } @@ -804,8 +804,8 @@ ASSIMP_API void aiVector3Add( ASSIMP_API void aiVector3Subtract( C_STRUCT aiVector3D *dst, const C_STRUCT aiVector3D *src) { - ai_assert(NULL != dst); - ai_assert(NULL != src); + ai_assert(nullptr != dst); + ai_assert(nullptr != src); *dst = *dst - *src; } @@ -813,7 +813,7 @@ ASSIMP_API void aiVector3Subtract( ASSIMP_API void aiVector3Scale( C_STRUCT aiVector3D *dst, const float s) { - ai_assert(NULL != dst); + ai_assert(nullptr != dst); *dst *= s; } @@ -821,15 +821,15 @@ ASSIMP_API void aiVector3Scale( ASSIMP_API void aiVector3SymMul( C_STRUCT aiVector3D *dst, const C_STRUCT aiVector3D *other) { - ai_assert(NULL != dst); - ai_assert(NULL != other); + ai_assert(nullptr != dst); + ai_assert(nullptr != other); *dst = dst->SymMul(*other); } // ------------------------------------------------------------------------------------------------ ASSIMP_API void aiVector3DivideByScalar( C_STRUCT aiVector3D *dst, const float s) { - ai_assert(NULL != dst); + ai_assert(nullptr != dst); *dst /= s; } @@ -837,29 +837,29 @@ ASSIMP_API void aiVector3DivideByScalar( ASSIMP_API void aiVector3DivideByVector( C_STRUCT aiVector3D *dst, C_STRUCT aiVector3D *v) { - ai_assert(NULL != dst); - ai_assert(NULL != v); + ai_assert(nullptr != dst); + ai_assert(nullptr != v); *dst = *dst / *v; } // ------------------------------------------------------------------------------------------------ ASSIMP_API float aiVector3Length( const C_STRUCT aiVector3D *v) { - ai_assert(NULL != v); + ai_assert(nullptr != v); return v->Length(); } // ------------------------------------------------------------------------------------------------ ASSIMP_API float aiVector3SquareLength( const C_STRUCT aiVector3D *v) { - ai_assert(NULL != v); + ai_assert(nullptr != v); return v->SquareLength(); } // ------------------------------------------------------------------------------------------------ ASSIMP_API void aiVector3Negate( C_STRUCT aiVector3D *dst) { - ai_assert(NULL != dst); + ai_assert(nullptr != dst); *dst = -(*dst); } @@ -867,8 +867,8 @@ ASSIMP_API void aiVector3Negate( ASSIMP_API float aiVector3DotProduct( const C_STRUCT aiVector3D *a, const C_STRUCT aiVector3D *b) { - ai_assert(NULL != a); - ai_assert(NULL != b); + ai_assert(nullptr != a); + ai_assert(nullptr != b); return (*a) * (*b); } @@ -877,23 +877,23 @@ ASSIMP_API void aiVector3CrossProduct( C_STRUCT aiVector3D *dst, const C_STRUCT aiVector3D *a, const C_STRUCT aiVector3D *b) { - ai_assert(NULL != dst); - ai_assert(NULL != a); - ai_assert(NULL != b); + ai_assert(nullptr != dst); + ai_assert(nullptr != a); + ai_assert(nullptr != b); *dst = *a ^ *b; } // ------------------------------------------------------------------------------------------------ ASSIMP_API void aiVector3Normalize( C_STRUCT aiVector3D *v) { - ai_assert(NULL != v); + ai_assert(nullptr != v); v->Normalize(); } // ------------------------------------------------------------------------------------------------ ASSIMP_API void aiVector3NormalizeSafe( C_STRUCT aiVector3D *v) { - ai_assert(NULL != v); + ai_assert(nullptr != v); v->NormalizeSafe(); } @@ -901,8 +901,8 @@ ASSIMP_API void aiVector3NormalizeSafe( ASSIMP_API void aiVector3RotateByQuaternion( C_STRUCT aiVector3D *v, const C_STRUCT aiQuaternion *q) { - ai_assert(NULL != v); - ai_assert(NULL != q); + ai_assert(nullptr != v); + ai_assert(nullptr != q); *v = q->Rotate(*v); } @@ -910,8 +910,8 @@ ASSIMP_API void aiVector3RotateByQuaternion( ASSIMP_API void aiMatrix3FromMatrix4( C_STRUCT aiMatrix3x3 *dst, const C_STRUCT aiMatrix4x4 *mat) { - ai_assert(NULL != dst); - ai_assert(NULL != mat); + ai_assert(nullptr != dst); + ai_assert(nullptr != mat); *dst = aiMatrix3x3(*mat); } @@ -919,8 +919,8 @@ ASSIMP_API void aiMatrix3FromMatrix4( ASSIMP_API void aiMatrix3FromQuaternion( C_STRUCT aiMatrix3x3 *mat, const C_STRUCT aiQuaternion *q) { - ai_assert(NULL != mat); - ai_assert(NULL != q); + ai_assert(nullptr != mat); + ai_assert(nullptr != q); *mat = q->GetMatrix(); } @@ -928,8 +928,8 @@ ASSIMP_API void aiMatrix3FromQuaternion( ASSIMP_API int aiMatrix3AreEqual( const C_STRUCT aiMatrix3x3 *a, const C_STRUCT aiMatrix3x3 *b) { - ai_assert(NULL != a); - ai_assert(NULL != b); + ai_assert(nullptr != a); + ai_assert(nullptr != b); return *a == *b; } @@ -938,20 +938,20 @@ ASSIMP_API int aiMatrix3AreEqualEpsilon( const C_STRUCT aiMatrix3x3 *a, const C_STRUCT aiMatrix3x3 *b, const float epsilon) { - ai_assert(NULL != a); - ai_assert(NULL != b); + ai_assert(nullptr != a); + ai_assert(nullptr != b); return a->Equal(*b, epsilon); } // ------------------------------------------------------------------------------------------------ ASSIMP_API void aiMatrix3Inverse(C_STRUCT aiMatrix3x3 *mat) { - ai_assert(NULL != mat); + ai_assert(nullptr != mat); mat->Inverse(); } // ------------------------------------------------------------------------------------------------ ASSIMP_API float aiMatrix3Determinant(const C_STRUCT aiMatrix3x3 *mat) { - ai_assert(NULL != mat); + ai_assert(nullptr != mat); return mat->Determinant(); } @@ -959,7 +959,7 @@ ASSIMP_API float aiMatrix3Determinant(const C_STRUCT aiMatrix3x3 *mat) { ASSIMP_API void aiMatrix3RotationZ( C_STRUCT aiMatrix3x3 *mat, const float angle) { - ai_assert(NULL != mat); + ai_assert(nullptr != mat); aiMatrix3x3::RotationZ(angle, *mat); } @@ -968,8 +968,8 @@ ASSIMP_API void aiMatrix3FromRotationAroundAxis( C_STRUCT aiMatrix3x3 *mat, const C_STRUCT aiVector3D *axis, const float angle) { - ai_assert(NULL != mat); - ai_assert(NULL != axis); + ai_assert(nullptr != mat); + ai_assert(nullptr != axis); aiMatrix3x3::Rotation(angle, *axis, *mat); } @@ -977,8 +977,8 @@ ASSIMP_API void aiMatrix3FromRotationAroundAxis( ASSIMP_API void aiMatrix3Translation( C_STRUCT aiMatrix3x3 *mat, const C_STRUCT aiVector2D *translation) { - ai_assert(NULL != mat); - ai_assert(NULL != translation); + ai_assert(nullptr != mat); + ai_assert(nullptr != translation); aiMatrix3x3::Translation(*translation, *mat); } @@ -987,9 +987,9 @@ ASSIMP_API void aiMatrix3FromTo( C_STRUCT aiMatrix3x3 *mat, const C_STRUCT aiVector3D *from, const C_STRUCT aiVector3D *to) { - ai_assert(NULL != mat); - ai_assert(NULL != from); - ai_assert(NULL != to); + ai_assert(nullptr != mat); + ai_assert(nullptr != from); + ai_assert(nullptr != to); aiMatrix3x3::FromToMatrix(*from, *to, *mat); } @@ -997,8 +997,8 @@ ASSIMP_API void aiMatrix3FromTo( ASSIMP_API void aiMatrix4FromMatrix3( C_STRUCT aiMatrix4x4 *dst, const C_STRUCT aiMatrix3x3 *mat) { - ai_assert(NULL != dst); - ai_assert(NULL != mat); + ai_assert(nullptr != dst); + ai_assert(nullptr != mat); *dst = aiMatrix4x4(*mat); } @@ -1008,10 +1008,10 @@ ASSIMP_API void aiMatrix4FromScalingQuaternionPosition( const C_STRUCT aiVector3D *scaling, const C_STRUCT aiQuaternion *rotation, const C_STRUCT aiVector3D *position) { - ai_assert(NULL != mat); - ai_assert(NULL != scaling); - ai_assert(NULL != rotation); - ai_assert(NULL != position); + ai_assert(nullptr != mat); + ai_assert(nullptr != scaling); + ai_assert(nullptr != rotation); + ai_assert(nullptr != position); *mat = aiMatrix4x4(*scaling, *rotation, *position); } @@ -1019,8 +1019,8 @@ ASSIMP_API void aiMatrix4FromScalingQuaternionPosition( ASSIMP_API void aiMatrix4Add( C_STRUCT aiMatrix4x4 *dst, const C_STRUCT aiMatrix4x4 *src) { - ai_assert(NULL != dst); - ai_assert(NULL != src); + ai_assert(nullptr != dst); + ai_assert(nullptr != src); *dst = *dst + *src; } @@ -1028,8 +1028,8 @@ ASSIMP_API void aiMatrix4Add( ASSIMP_API int aiMatrix4AreEqual( const C_STRUCT aiMatrix4x4 *a, const C_STRUCT aiMatrix4x4 *b) { - ai_assert(NULL != a); - ai_assert(NULL != b); + ai_assert(nullptr != a); + ai_assert(nullptr != b); return *a == *b; } @@ -1038,26 +1038,26 @@ ASSIMP_API int aiMatrix4AreEqualEpsilon( const C_STRUCT aiMatrix4x4 *a, const C_STRUCT aiMatrix4x4 *b, const float epsilon) { - ai_assert(NULL != a); - ai_assert(NULL != b); + ai_assert(nullptr != a); + ai_assert(nullptr != b); return a->Equal(*b, epsilon); } // ------------------------------------------------------------------------------------------------ ASSIMP_API void aiMatrix4Inverse(C_STRUCT aiMatrix4x4 *mat) { - ai_assert(NULL != mat); + ai_assert(nullptr != mat); mat->Inverse(); } // ------------------------------------------------------------------------------------------------ ASSIMP_API float aiMatrix4Determinant(const C_STRUCT aiMatrix4x4 *mat) { - ai_assert(NULL != mat); + ai_assert(nullptr != mat); return mat->Determinant(); } // ------------------------------------------------------------------------------------------------ ASSIMP_API int aiMatrix4IsIdentity(const C_STRUCT aiMatrix4x4 *mat) { - ai_assert(NULL != mat); + ai_assert(nullptr != mat); return mat->IsIdentity(); } @@ -1067,10 +1067,10 @@ ASSIMP_API void aiMatrix4DecomposeIntoScalingEulerAnglesPosition( C_STRUCT aiVector3D *scaling, C_STRUCT aiVector3D *rotation, C_STRUCT aiVector3D *position) { - ai_assert(NULL != mat); - ai_assert(NULL != scaling); - ai_assert(NULL != rotation); - ai_assert(NULL != position); + ai_assert(nullptr != mat); + ai_assert(nullptr != scaling); + ai_assert(nullptr != rotation); + ai_assert(nullptr != position); mat->Decompose(*scaling, *rotation, *position); } @@ -1081,11 +1081,11 @@ ASSIMP_API void aiMatrix4DecomposeIntoScalingAxisAnglePosition( C_STRUCT aiVector3D *axis, float *angle, C_STRUCT aiVector3D *position) { - ai_assert(NULL != mat); - ai_assert(NULL != scaling); - ai_assert(NULL != axis); - ai_assert(NULL != angle); - ai_assert(NULL != position); + ai_assert(nullptr != mat); + ai_assert(nullptr != scaling); + ai_assert(nullptr != axis); + ai_assert(nullptr != angle); + ai_assert(nullptr != position); mat->Decompose(*scaling, *axis, *angle, *position); } @@ -1094,9 +1094,9 @@ ASSIMP_API void aiMatrix4DecomposeNoScaling( const C_STRUCT aiMatrix4x4 *mat, C_STRUCT aiQuaternion *rotation, C_STRUCT aiVector3D *position) { - ai_assert(NULL != mat); - ai_assert(NULL != rotation); - ai_assert(NULL != position); + ai_assert(nullptr != mat); + ai_assert(nullptr != rotation); + ai_assert(nullptr != position); mat->DecomposeNoScaling(*rotation, *position); } @@ -1104,7 +1104,7 @@ ASSIMP_API void aiMatrix4DecomposeNoScaling( ASSIMP_API void aiMatrix4FromEulerAngles( C_STRUCT aiMatrix4x4 *mat, float x, float y, float z) { - ai_assert(NULL != mat); + ai_assert(nullptr != mat); mat->FromEulerAnglesXYZ(x, y, z); } @@ -1112,7 +1112,7 @@ ASSIMP_API void aiMatrix4FromEulerAngles( ASSIMP_API void aiMatrix4RotationX( C_STRUCT aiMatrix4x4 *mat, const float angle) { - ai_assert(NULL != mat); + ai_assert(nullptr != mat); aiMatrix4x4::RotationX(angle, *mat); } @@ -1128,7 +1128,7 @@ ASSIMP_API void aiMatrix4RotationY( ASSIMP_API void aiMatrix4RotationZ( C_STRUCT aiMatrix4x4 *mat, const float angle) { - ai_assert(NULL != mat); + ai_assert(nullptr != mat); aiMatrix4x4::RotationZ(angle, *mat); } @@ -1137,8 +1137,8 @@ ASSIMP_API void aiMatrix4FromRotationAroundAxis( C_STRUCT aiMatrix4x4 *mat, const C_STRUCT aiVector3D *axis, const float angle) { - ai_assert(NULL != mat); - ai_assert(NULL != axis); + ai_assert(nullptr != mat); + ai_assert(nullptr != axis); aiMatrix4x4::Rotation(angle, *axis, *mat); } @@ -1146,8 +1146,8 @@ ASSIMP_API void aiMatrix4FromRotationAroundAxis( ASSIMP_API void aiMatrix4Translation( C_STRUCT aiMatrix4x4 *mat, const C_STRUCT aiVector3D *translation) { - ai_assert(NULL != mat); - ai_assert(NULL != translation); + ai_assert(nullptr != mat); + ai_assert(nullptr != translation); aiMatrix4x4::Translation(*translation, *mat); } @@ -1155,8 +1155,8 @@ ASSIMP_API void aiMatrix4Translation( ASSIMP_API void aiMatrix4Scaling( C_STRUCT aiMatrix4x4 *mat, const C_STRUCT aiVector3D *scaling) { - ai_assert(NULL != mat); - ai_assert(NULL != scaling); + ai_assert(nullptr != mat); + ai_assert(nullptr != scaling); aiMatrix4x4::Scaling(*scaling, *mat); } @@ -1165,9 +1165,9 @@ ASSIMP_API void aiMatrix4FromTo( C_STRUCT aiMatrix4x4 *mat, const C_STRUCT aiVector3D *from, const C_STRUCT aiVector3D *to) { - ai_assert(NULL != mat); - ai_assert(NULL != from); - ai_assert(NULL != to); + ai_assert(nullptr != mat); + ai_assert(nullptr != from); + ai_assert(nullptr != to); aiMatrix4x4::FromToMatrix(*from, *to, *mat); } @@ -1175,7 +1175,7 @@ ASSIMP_API void aiMatrix4FromTo( ASSIMP_API void aiQuaternionFromEulerAngles( C_STRUCT aiQuaternion *q, float x, float y, float z) { - ai_assert(NULL != q); + ai_assert(nullptr != q); *q = aiQuaternion(x, y, z); } @@ -1184,8 +1184,8 @@ ASSIMP_API void aiQuaternionFromAxisAngle( C_STRUCT aiQuaternion *q, const C_STRUCT aiVector3D *axis, const float angle) { - ai_assert(NULL != q); - ai_assert(NULL != axis); + ai_assert(nullptr != q); + ai_assert(nullptr != axis); *q = aiQuaternion(*axis, angle); } @@ -1193,8 +1193,8 @@ ASSIMP_API void aiQuaternionFromAxisAngle( ASSIMP_API void aiQuaternionFromNormalizedQuaternion( C_STRUCT aiQuaternion *q, const C_STRUCT aiVector3D *normalized) { - ai_assert(NULL != q); - ai_assert(NULL != normalized); + ai_assert(nullptr != q); + ai_assert(nullptr != normalized); *q = aiQuaternion(*normalized); } @@ -1202,8 +1202,8 @@ ASSIMP_API void aiQuaternionFromNormalizedQuaternion( ASSIMP_API int aiQuaternionAreEqual( const C_STRUCT aiQuaternion *a, const C_STRUCT aiQuaternion *b) { - ai_assert(NULL != a); - ai_assert(NULL != b); + ai_assert(nullptr != a); + ai_assert(nullptr != b); return *a == *b; } @@ -1212,22 +1212,22 @@ ASSIMP_API int aiQuaternionAreEqualEpsilon( const C_STRUCT aiQuaternion *a, const C_STRUCT aiQuaternion *b, const float epsilon) { - ai_assert(NULL != a); - ai_assert(NULL != b); + ai_assert(nullptr != a); + ai_assert(nullptr != b); return a->Equal(*b, epsilon); } // ------------------------------------------------------------------------------------------------ ASSIMP_API void aiQuaternionNormalize( C_STRUCT aiQuaternion *q) { - ai_assert(NULL != q); + ai_assert(nullptr != q); q->Normalize(); } // ------------------------------------------------------------------------------------------------ ASSIMP_API void aiQuaternionConjugate( C_STRUCT aiQuaternion *q) { - ai_assert(NULL != q); + ai_assert(nullptr != q); q->Conjugate(); } @@ -1235,8 +1235,8 @@ ASSIMP_API void aiQuaternionConjugate( ASSIMP_API void aiQuaternionMultiply( C_STRUCT aiQuaternion *dst, const C_STRUCT aiQuaternion *q) { - ai_assert(NULL != dst); - ai_assert(NULL != q); + ai_assert(nullptr != dst); + ai_assert(nullptr != q); *dst = (*dst) * (*q); } @@ -1246,8 +1246,8 @@ ASSIMP_API void aiQuaternionInterpolate( const C_STRUCT aiQuaternion *start, const C_STRUCT aiQuaternion *end, const float factor) { - ai_assert(NULL != dst); - ai_assert(NULL != start); - ai_assert(NULL != end); + ai_assert(nullptr != dst); + ai_assert(nullptr != start); + ai_assert(nullptr != end); aiQuaternion::Interpolate(*dst, *start, *end, factor); } diff --git a/code/Common/BaseImporter.cpp b/code/Common/BaseImporter.cpp index 71049a996..47ff05f2f 100644 --- a/code/Common/BaseImporter.cpp +++ b/code/Common/BaseImporter.cpp @@ -45,28 +45,28 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * @brief Implementation of BaseImporter */ -#include -#include #include "FileSystemFilter.h" #include "Importer.h" +#include #include +#include +#include +#include #include #include -#include -#include +#include #include #include #include #include -#include using namespace Assimp; // ------------------------------------------------------------------------------------------------ // Constructor to be privately used by Importer BaseImporter::BaseImporter() AI_NO_EXCEPT -: m_progress() { + : m_progress() { /** * Assimp Importer * unit conversions available @@ -89,8 +89,7 @@ BaseImporter::~BaseImporter() { // nothing to do here } -void BaseImporter::UpdateImporterScale( Importer* pImp ) -{ +void BaseImporter::UpdateImporterScale(Importer *pImp) { ai_assert(pImp != nullptr); ai_assert(importerScale != 0.0); ai_assert(fileScale != 0.0); @@ -98,15 +97,14 @@ void BaseImporter::UpdateImporterScale( Importer* pImp ) double activeScale = importerScale * fileScale; // Set active scaling - pImp->SetPropertyFloat( AI_CONFIG_APP_SCALE_KEY, static_cast( activeScale) ); + pImp->SetPropertyFloat(AI_CONFIG_APP_SCALE_KEY, static_cast(activeScale)); - ASSIMP_LOG_DEBUG_F("UpdateImporterScale scale set: %f", activeScale ); + ASSIMP_LOG_DEBUG_F("UpdateImporterScale scale set: %f", activeScale); } // ------------------------------------------------------------------------------------------------ // Imports the given file and returns the imported data. -aiScene* BaseImporter::ReadFile(Importer* pImp, const std::string& pFile, IOSystem* pIOHandler) { - +aiScene *BaseImporter::ReadFile(Importer *pImp, const std::string &pFile, IOSystem *pIOHandler) { m_progress = pImp->GetProgressHandler(); if (nullptr == m_progress) { @@ -116,25 +114,23 @@ aiScene* BaseImporter::ReadFile(Importer* pImp, const std::string& pFile, IOSyst ai_assert(m_progress); // Gather configuration properties for this run - SetupProperties( pImp ); + SetupProperties(pImp); // Construct a file system filter to improve our success ratio at reading external files - FileSystemFilter filter(pFile,pIOHandler); + FileSystemFilter filter(pFile, pIOHandler); // create a scene object to hold the data std::unique_ptr sc(new aiScene()); // dispatch importing - try - { - InternReadFile( pFile, sc.get(), &filter); + try { + InternReadFile(pFile, sc.get(), &filter); // Calculate import scale hook - required because pImp not available anywhere else // passes scale into ScaleProcess UpdateImporterScale(pImp); - - } catch( const std::exception& err ) { + } catch (const std::exception &err) { // extract error description m_ErrorText = err.what(); ASSIMP_LOG_ERROR(m_ErrorText); @@ -146,69 +142,66 @@ aiScene* BaseImporter::ReadFile(Importer* pImp, const std::string& pFile, IOSyst } // ------------------------------------------------------------------------------------------------ -void BaseImporter::SetupProperties(const Importer* ) -{ +void BaseImporter::SetupProperties(const Importer *) { // the default implementation does nothing } // ------------------------------------------------------------------------------------------------ -void BaseImporter::GetExtensionList(std::set& extensions) { - const aiImporterDesc* desc = GetInfo(); +void BaseImporter::GetExtensionList(std::set &extensions) { + const aiImporterDesc *desc = GetInfo(); ai_assert(desc != nullptr); - const char* ext = desc->mFileExtensions; - ai_assert(ext != nullptr ); + const char *ext = desc->mFileExtensions; + ai_assert(ext != nullptr); - const char* last = ext; + const char *last = ext; do { if (!*ext || *ext == ' ') { - extensions.insert(std::string(last,ext-last)); - ai_assert(ext-last > 0); + extensions.insert(std::string(last, ext - last)); + ai_assert(ext - last > 0); last = ext; - while(*last == ' ') { + while (*last == ' ') { ++last; } } - } - while(*ext++); + } while (*ext++); } // ------------------------------------------------------------------------------------------------ -/*static*/ bool BaseImporter::SearchFileHeaderForToken( IOSystem* pIOHandler, - const std::string& pFile, - const char** tokens, - unsigned int numTokens, - unsigned int searchBytes /* = 200 */, - bool tokensSol /* false */, - bool noAlphaBeforeTokens /* false */) -{ - ai_assert( nullptr != tokens ); - ai_assert( 0 != numTokens ); - ai_assert( 0 != searchBytes); +/*static*/ bool BaseImporter::SearchFileHeaderForToken(IOSystem *pIOHandler, + const std::string &pFile, + const char **tokens, + unsigned int numTokens, + unsigned int searchBytes /* = 200 */, + bool tokensSol /* false */, + bool noAlphaBeforeTokens /* false */) { + ai_assert(nullptr != tokens); + ai_assert(0 != numTokens); + ai_assert(0 != searchBytes); - if ( nullptr == pIOHandler ) { + if (nullptr == pIOHandler) { return false; } - std::unique_ptr pStream (pIOHandler->Open(pFile)); + std::unique_ptr pStream(pIOHandler->Open(pFile)); if (pStream) { // read 200 characters from the file - std::unique_ptr _buffer (new char[searchBytes+1 /* for the '\0' */]); - char *buffer( _buffer.get() ); - const size_t read( pStream->Read(buffer,1,searchBytes) ); - if( 0 == read ) { + std::unique_ptr _buffer(new char[searchBytes + 1 /* for the '\0' */]); + char *buffer(_buffer.get()); + const size_t read(pStream->Read(buffer, 1, searchBytes)); + if (0 == read) { return false; } - for( size_t i = 0; i < read; ++i ) { - buffer[ i ] = static_cast( ::tolower( buffer[ i ] ) ); + for (size_t i = 0; i < read; ++i) { + buffer[i] = static_cast(::tolower(buffer[i])); } // It is not a proper handling of unicode files here ... // ehm ... but it works in most cases. - char* cur = buffer,*cur2 = buffer,*end = &buffer[read]; - while (cur != end) { - if( *cur ) { + char *cur = buffer, *cur2 = buffer, *end = &buffer[read]; + while (cur != end) { + if (*cur) { *cur2++ = *cur; } ++cur; @@ -216,17 +209,17 @@ void BaseImporter::GetExtensionList(std::set& extensions) { *cur2 = '\0'; std::string token; - for (unsigned int i = 0; i < numTokens; ++i ) { - ai_assert( nullptr != tokens[i] ); - const size_t len( strlen( tokens[ i ] ) ); + for (unsigned int i = 0; i < numTokens; ++i) { + ai_assert(nullptr != tokens[i]); + const size_t len(strlen(tokens[i])); token.clear(); - const char *ptr( tokens[ i ] ); - for ( size_t tokIdx = 0; tokIdx < len; ++tokIdx ) { - token.push_back( static_cast( tolower( *ptr ) ) ); + const char *ptr(tokens[i]); + for (size_t tokIdx = 0; tokIdx < len; ++tokIdx) { + token.push_back(static_cast(tolower(*ptr))); ++ptr; } - const char* r = strstr( buffer, token.c_str() ); - if( !r ) { + const char *r = strstr(buffer, token.c_str()); + if (!r) { continue; } // We need to make sure that we didn't accidentially identify the end of another token as our token, @@ -237,7 +230,7 @@ void BaseImporter::GetExtensionList(std::set& extensions) { // We got a match, either we don't care where it is, or it happens to // be in the beginning of the file / line if (!tokensSol || r == buffer || r[-1] == '\r' || r[-1] == '\n') { - ASSIMP_LOG_DEBUG_F( "Found positive match for header keyword: ", tokens[i] ); + ASSIMP_LOG_DEBUG_F("Found positive match for header keyword: ", tokens[i]); return true; } } @@ -248,26 +241,25 @@ void BaseImporter::GetExtensionList(std::set& extensions) { // ------------------------------------------------------------------------------------------------ // Simple check for file extension -/*static*/ bool BaseImporter::SimpleExtensionCheck (const std::string& pFile, - const char* ext0, - const char* ext1, - const char* ext2) -{ +/*static*/ bool BaseImporter::SimpleExtensionCheck(const std::string &pFile, + const char *ext0, + const char *ext1, + const char *ext2) { std::string::size_type pos = pFile.find_last_of('.'); // no file extension - can't read - if( pos == std::string::npos) + if (pos == std::string::npos) return false; - const char* ext_real = & pFile[ pos+1 ]; - if( !ASSIMP_stricmp(ext_real,ext0) ) + const char *ext_real = &pFile[pos + 1]; + if (!ASSIMP_stricmp(ext_real, ext0)) return true; // check for other, optional, file extensions - if (ext1 && !ASSIMP_stricmp(ext_real,ext1)) + if (ext1 && !ASSIMP_stricmp(ext_real, ext1)) return true; - if (ext2 && !ASSIMP_stricmp(ext_real,ext2)) + if (ext2 && !ASSIMP_stricmp(ext_real, ext2)) return true; return false; @@ -275,7 +267,7 @@ void BaseImporter::GetExtensionList(std::set& extensions) { // ------------------------------------------------------------------------------------------------ // Get file extension from path -std::string BaseImporter::GetExtension( const std::string& file ) { +std::string BaseImporter::GetExtension(const std::string &file) { std::string::size_type pos = file.find_last_of('.'); // no file extension at all @@ -284,34 +276,33 @@ std::string BaseImporter::GetExtension( const std::string& file ) { } // thanks to Andy Maloney for the hint - std::string ret = file.substr( pos + 1 ); - std::transform( ret.begin(), ret.end(), ret.begin(), ToLower); + std::string ret = file.substr(pos + 1); + std::transform(ret.begin(), ret.end(), ret.begin(), ToLower); return ret; } // ------------------------------------------------------------------------------------------------ // Check for magic bytes at the beginning of the file. -/* static */ bool BaseImporter::CheckMagicToken(IOSystem* pIOHandler, const std::string& pFile, - const void* _magic, unsigned int num, unsigned int offset, unsigned int size) -{ - ai_assert( size <= 16 ); - ai_assert( _magic ); +/* static */ bool BaseImporter::CheckMagicToken(IOSystem *pIOHandler, const std::string &pFile, + const void *_magic, unsigned int num, unsigned int offset, unsigned int size) { + ai_assert(size <= 16); + ai_assert(_magic); if (!pIOHandler) { return false; } union { - const char* magic; - const uint16_t* magic_u16; - const uint32_t* magic_u32; + const char *magic; + const uint16_t *magic_u16; + const uint32_t *magic_u32; }; - magic = reinterpret_cast(_magic); - std::unique_ptr pStream (pIOHandler->Open(pFile)); + magic = reinterpret_cast(_magic); + std::unique_ptr pStream(pIOHandler->Open(pFile)); if (pStream) { // skip to offset - pStream->Seek(offset,aiOrigin_SET); + pStream->Seek(offset, aiOrigin_SET); // read 'size' characters from the file union { @@ -319,7 +310,7 @@ std::string BaseImporter::GetExtension( const std::string& file ) { uint16_t data_u16[8]; uint32_t data_u32[4]; }; - if(size != pStream->Read(data,1,size)) { + if (size != pStream->Read(data, 1, size)) { return false; } @@ -333,17 +324,15 @@ std::string BaseImporter::GetExtension( const std::string& file ) { if (data_u16[0] == *magic_u16 || data_u16[0] == rev) { return true; } - } - else if (4 == size) { + } else if (4 == size) { uint32_t rev = *magic_u32; ByteSwap::Swap(&rev); if (data_u32[0] == *magic_u32 || data_u32[0] == rev) { return true; } - } - else { + } else { // any length ... just compare - if(!memcmp(magic,data,size)) { + if (!memcmp(magic, data, size)) { return true; } } @@ -354,61 +343,59 @@ std::string BaseImporter::GetExtension( const std::string& file ) { } #ifdef ASSIMP_USE_HUNTER -# include +#include #else -# include "../contrib/utf8cpp/source/utf8.h" +#include "../contrib/utf8cpp/source/utf8.h" #endif // ------------------------------------------------------------------------------------------------ // Convert to UTF8 data -void BaseImporter::ConvertToUTF8(std::vector& data) -{ +void BaseImporter::ConvertToUTF8(std::vector &data) { //ConversionResult result; - if(data.size() < 8) { + if (data.size() < 8) { throw DeadlyImportError("File is too small"); } // UTF 8 with BOM - if((uint8_t)data[0] == 0xEF && (uint8_t)data[1] == 0xBB && (uint8_t)data[2] == 0xBF) { + if ((uint8_t)data[0] == 0xEF && (uint8_t)data[1] == 0xBB && (uint8_t)data[2] == 0xBF) { ASSIMP_LOG_DEBUG("Found UTF-8 BOM ..."); - std::copy(data.begin()+3,data.end(),data.begin()); - data.resize(data.size()-3); + std::copy(data.begin() + 3, data.end(), data.begin()); + data.resize(data.size() - 3); return; } - - + // UTF 32 BE with BOM - if(*((uint32_t*)&data.front()) == 0xFFFE0000) { + if (*((uint32_t *)&data.front()) == 0xFFFE0000) { // swap the endianness .. - for(uint32_t* p = (uint32_t*)&data.front(), *end = (uint32_t*)&data.back(); p <= end; ++p) { + for (uint32_t *p = (uint32_t *)&data.front(), *end = (uint32_t *)&data.back(); p <= end; ++p) { AI_SWAP4P(p); } } // UTF 32 LE with BOM - if(*((uint32_t*)&data.front()) == 0x0000FFFE) { + if (*((uint32_t *)&data.front()) == 0x0000FFFE) { ASSIMP_LOG_DEBUG("Found UTF-32 BOM ..."); std::vector output; - int *ptr = (int*)&data[ 0 ]; - int *end = ptr + ( data.size() / sizeof(int) ) +1; - utf8::utf32to8( ptr, end, back_inserter(output)); + int *ptr = (int *)&data[0]; + int *end = ptr + (data.size() / sizeof(int)) + 1; + utf8::utf32to8(ptr, end, back_inserter(output)); return; } // UTF 16 BE with BOM - if(*((uint16_t*)&data.front()) == 0xFFFE) { + if (*((uint16_t *)&data.front()) == 0xFFFE) { // swap the endianness .. - for(uint16_t* p = (uint16_t*)&data.front(), *end = (uint16_t*)&data.back(); p <= end; ++p) { + for (uint16_t *p = (uint16_t *)&data.front(), *end = (uint16_t *)&data.back(); p <= end; ++p) { ByteSwap::Swap2(p); } } // UTF 16 LE with BOM - if(*((uint16_t*)&data.front()) == 0xFEFF) { + if (*((uint16_t *)&data.front()) == 0xFEFF) { ASSIMP_LOG_DEBUG("Found UTF-16 BOM ..."); std::vector output; @@ -419,23 +406,22 @@ void BaseImporter::ConvertToUTF8(std::vector& data) // ------------------------------------------------------------------------------------------------ // Convert to UTF8 data to ISO-8859-1 -void BaseImporter::ConvertUTF8toISO8859_1(std::string& data) -{ +void BaseImporter::ConvertUTF8toISO8859_1(std::string &data) { size_t size = data.size(); size_t i = 0, j = 0; - while(i < size) { - if ((unsigned char) data[i] < (size_t) 0x80) { + while (i < size) { + if ((unsigned char)data[i] < (size_t)0x80) { data[j] = data[i]; - } else if(i < size - 1) { - if((unsigned char) data[i] == 0xC2) { + } else if (i < size - 1) { + if ((unsigned char)data[i] == 0xC2) { data[j] = data[++i]; - } else if((unsigned char) data[i] == 0xC3) { - data[j] = ((unsigned char) data[++i] + 0x40); + } else if ((unsigned char)data[i] == 0xC3) { + data[j] = ((unsigned char)data[++i] + 0x40); } else { std::stringstream stream; stream << "UTF8 code " << std::hex << data[i] << data[i + 1] << " can not be converted into ISA-8859-1."; - ASSIMP_LOG_ERROR( stream.str() ); + ASSIMP_LOG_ERROR(stream.str()); data[j++] = data[i++]; data[j] = data[i]; @@ -446,30 +432,30 @@ void BaseImporter::ConvertUTF8toISO8859_1(std::string& data) data[j] = data[i]; } - i++; j++; + i++; + j++; } data.resize(j); } // ------------------------------------------------------------------------------------------------ -void BaseImporter::TextFileToBuffer(IOStream* stream, - std::vector& data, - TextFileMode mode) -{ +void BaseImporter::TextFileToBuffer(IOStream *stream, + std::vector &data, + TextFileMode mode) { ai_assert(nullptr != stream); const size_t fileSize = stream->FileSize(); if (mode == FORBID_EMPTY) { - if(!fileSize) { + if (!fileSize) { throw DeadlyImportError("File is empty"); } } - data.reserve(fileSize+1); + data.reserve(fileSize + 1); data.resize(fileSize); - if(fileSize > 0) { - if(fileSize != stream->Read( &data[0], 1, fileSize)) { + if (fileSize > 0) { + if (fileSize != stream->Read(&data[0], 1, fileSize)) { throw DeadlyImportError("File read error"); } @@ -482,58 +468,55 @@ void BaseImporter::TextFileToBuffer(IOStream* stream, // ------------------------------------------------------------------------------------------------ namespace Assimp { - // Represents an import request - struct LoadRequest { - LoadRequest(const std::string& _file, unsigned int _flags,const BatchLoader::PropertyMap* _map, unsigned int _id) - : file(_file) - , flags(_flags) - , refCnt(1) - , scene(NULL) - , loaded(false) - , id(_id) { - if ( _map ) { - map = *_map; - } +// Represents an import request +struct LoadRequest { + LoadRequest(const std::string &_file, unsigned int _flags, const BatchLoader::PropertyMap *_map, unsigned int _id) : + file(_file), + flags(_flags), + refCnt(1), + scene(nullptr), + loaded(false), + id(_id) { + if (_map) { + map = *_map; } + } - bool operator== ( const std::string& f ) const { - return file == f; - } + bool operator==(const std::string &f) const { + return file == f; + } - const std::string file; - unsigned int flags; - unsigned int refCnt; - aiScene *scene; - bool loaded; - BatchLoader::PropertyMap map; - unsigned int id; - }; -} + const std::string file; + unsigned int flags; + unsigned int refCnt; + aiScene *scene; + bool loaded; + BatchLoader::PropertyMap map; + unsigned int id; +}; +} // namespace Assimp // ------------------------------------------------------------------------------------------------ // BatchLoader::pimpl data structure struct Assimp::BatchData { - BatchData( IOSystem* pIO, bool validate ) - : pIOSystem( pIO ) - , pImporter( nullptr ) - , next_id(0xffff) - , validate( validate ) { - ai_assert( nullptr != pIO ); - + BatchData(IOSystem *pIO, bool validate) : + pIOSystem(pIO), pImporter(nullptr), next_id(0xffff), validate(validate) { + ai_assert(nullptr != pIO); + pImporter = new Importer(); - pImporter->SetIOHandler( pIO ); + pImporter->SetIOHandler(pIO); } ~BatchData() { - pImporter->SetIOHandler( nullptr ); /* get pointer back into our possession */ + pImporter->SetIOHandler(nullptr); /* get pointer back into our possession */ delete pImporter; } // IO system to be used for all imports - IOSystem* pIOSystem; + IOSystem *pIOSystem; // Importer used to load all meshes - Importer* pImporter; + Importer *pImporter; // List of all imports std::list requests; @@ -551,24 +534,23 @@ struct Assimp::BatchData { typedef std::list::iterator LoadReqIt; // ------------------------------------------------------------------------------------------------ -BatchLoader::BatchLoader(IOSystem* pIO, bool validate ) { +BatchLoader::BatchLoader(IOSystem *pIO, bool validate) { ai_assert(nullptr != pIO); - m_data = new BatchData( pIO, validate ); + m_data = new BatchData(pIO, validate); } // ------------------------------------------------------------------------------------------------ -BatchLoader::~BatchLoader() -{ +BatchLoader::~BatchLoader() { // delete all scenes what have not been polled by the user - for ( LoadReqIt it = m_data->requests.begin();it != m_data->requests.end(); ++it) { + for (LoadReqIt it = m_data->requests.begin(); it != m_data->requests.end(); ++it) { delete (*it).scene; } delete m_data; } // ------------------------------------------------------------------------------------------------ -void BatchLoader::setValidation( bool enabled ) { +void BatchLoader::setValidation(bool enabled) { m_data->validate = enabled; } @@ -578,21 +560,19 @@ bool BatchLoader::getValidation() const { } // ------------------------------------------------------------------------------------------------ -unsigned int BatchLoader::AddLoadRequest(const std::string& file, - unsigned int steps /*= 0*/, const PropertyMap* map /*= NULL*/) -{ +unsigned int BatchLoader::AddLoadRequest(const std::string &file, + unsigned int steps /*= 0*/, const PropertyMap *map /*= nullptr*/) { ai_assert(!file.empty()); // check whether we have this loading request already - for ( LoadReqIt it = m_data->requests.begin();it != m_data->requests.end(); ++it) { + for (LoadReqIt it = m_data->requests.begin(); it != m_data->requests.end(); ++it) { // Call IOSystem's path comparison function here - if ( m_data->pIOSystem->ComparePaths((*it).file,file)) { + if (m_data->pIOSystem->ComparePaths((*it).file, file)) { if (map) { - if ( !( ( *it ).map == *map ) ) { + if (!((*it).map == *map)) { continue; } - } - else if ( !( *it ).map.empty() ) { + } else if (!(*it).map.empty()) { continue; } @@ -607,12 +587,11 @@ unsigned int BatchLoader::AddLoadRequest(const std::string& file, } // ------------------------------------------------------------------------------------------------ -aiScene* BatchLoader::GetImport( unsigned int which ) -{ - for ( LoadReqIt it = m_data->requests.begin();it != m_data->requests.end(); ++it) { - if ((*it).id == which && (*it).loaded) { - aiScene* sc = (*it).scene; - if (!(--(*it).refCnt)) { +aiScene *BatchLoader::GetImport(unsigned int which) { + for (LoadReqIt it = m_data->requests.begin(); it != m_data->requests.end(); ++it) { + if ((*it).id == which && (*it).loaded) { + aiScene *sc = (*it).scene; + if (!(--(*it).refCnt)) { m_data->requests.erase(it); } return sc; @@ -621,32 +600,28 @@ aiScene* BatchLoader::GetImport( unsigned int which ) return nullptr; } - - // ------------------------------------------------------------------------------------------------ -void BatchLoader::LoadAll() -{ +void BatchLoader::LoadAll() { // no threaded implementation for the moment - for ( LoadReqIt it = m_data->requests.begin();it != m_data->requests.end(); ++it) { + for (LoadReqIt it = m_data->requests.begin(); it != m_data->requests.end(); ++it) { // force validation in debug builds unsigned int pp = (*it).flags; - if ( m_data->validate ) { + if (m_data->validate) { pp |= aiProcess_ValidateDataStructure; } // setup config properties if necessary - ImporterPimpl* pimpl = m_data->pImporter->Pimpl(); - pimpl->mFloatProperties = (*it).map.floats; - pimpl->mIntProperties = (*it).map.ints; + ImporterPimpl *pimpl = m_data->pImporter->Pimpl(); + pimpl->mFloatProperties = (*it).map.floats; + pimpl->mIntProperties = (*it).map.ints; pimpl->mStringProperties = (*it).map.strings; pimpl->mMatrixProperties = (*it).map.matrices; - if (!DefaultLogger::isNullLogger()) - { + if (!DefaultLogger::isNullLogger()) { ASSIMP_LOG_INFO("%%% BEGIN EXTERNAL FILE %%%"); ASSIMP_LOG_INFO_F("File: ", (*it).file); } - m_data->pImporter->ReadFile((*it).file,pp); + m_data->pImporter->ReadFile((*it).file, pp); (*it).scene = m_data->pImporter->GetOrphanedScene(); (*it).loaded = true; diff --git a/code/Common/BaseProcess.h b/code/Common/BaseProcess.h index bf1f2586f..b7a9b18fa 100644 --- a/code/Common/BaseProcess.h +++ b/code/Common/BaseProcess.h @@ -126,7 +126,7 @@ public: bool GetProperty(const char *name, T *&out) const { THeapData *t = (THeapData *)GetPropertyInternal(name); if (!t) { - out = NULL; + out = nullptr; return false; } out = t->data; @@ -202,7 +202,7 @@ public: // ------------------------------------------------------------------- /** Executes the post processing step on the given imported data. * The function deletes the scene if the postprocess step fails ( - * the object pointer will be set to NULL). + * the object pointer will be set to nullptr). * @param pImp Importer instance (pImp->mScene must be valid) */ void ExecuteOnScene(Importer *pImp); @@ -225,7 +225,7 @@ public: // ------------------------------------------------------------------- /** Assign a new SharedPostProcessInfo to the step. This object * allows multiple postprocess steps to share data. - * @param sh May be NULL + * @param sh May be nullptr */ inline void SetSharedData(SharedPostProcessInfo *sh) { shared = sh; diff --git a/code/Common/Bitmap.cpp b/code/Common/Bitmap.cpp index 7d8225704..772fd7455 100644 --- a/code/Common/Bitmap.cpp +++ b/code/Common/Bitmap.cpp @@ -47,109 +47,109 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * Used for file formats which embed their textures into the model file. */ - #include +#include #include #include -#include namespace Assimp { - void Bitmap::Save(aiTexture* texture, IOStream* file) { - if(file != NULL) { - Header header; - DIB dib; +void Bitmap::Save(aiTexture *texture, IOStream *file) { + if (file != nullptr) { + Header header; + DIB dib; - dib.size = DIB::dib_size; - dib.width = texture->mWidth; - dib.height = texture->mHeight; - dib.planes = 1; - dib.bits_per_pixel = 8 * mBytesPerPixel; - dib.compression = 0; - dib.image_size = (((dib.width * mBytesPerPixel) + 3) & 0x0000FFFC) * dib.height; - dib.x_resolution = 0; - dib.y_resolution = 0; - dib.nb_colors = 0; - dib.nb_important_colors = 0; + dib.size = DIB::dib_size; + dib.width = texture->mWidth; + dib.height = texture->mHeight; + dib.planes = 1; + dib.bits_per_pixel = 8 * mBytesPerPixel; + dib.compression = 0; + dib.image_size = (((dib.width * mBytesPerPixel) + 3) & 0x0000FFFC) * dib.height; + dib.x_resolution = 0; + dib.y_resolution = 0; + dib.nb_colors = 0; + dib.nb_important_colors = 0; - header.type = 0x4D42; // 'BM' - header.offset = Header::header_size + DIB::dib_size; - header.size = header.offset + dib.image_size; - header.reserved1 = 0; - header.reserved2 = 0; + header.type = 0x4D42; // 'BM' + header.offset = Header::header_size + DIB::dib_size; + header.size = header.offset + dib.image_size; + header.reserved1 = 0; + header.reserved2 = 0; - WriteHeader(header, file); - WriteDIB(dib, file); - WriteData(texture, file); - } + WriteHeader(header, file); + WriteDIB(dib, file); + WriteData(texture, file); } - - template - inline - std::size_t Copy(uint8_t* data, const T &field) { -#ifdef AI_BUILD_BIG_ENDIAN - T field_swapped=AI_BE(field); - std::memcpy(data, &field_swapped, sizeof(field)); return sizeof(field); -#else - std::memcpy(data, &AI_BE(field), sizeof(field)); return sizeof(field); -#endif - } - - void Bitmap::WriteHeader(Header& header, IOStream* file) { - uint8_t data[Header::header_size]; - - std::size_t offset = 0; - - offset += Copy(&data[offset], header.type); - offset += Copy(&data[offset], header.size); - offset += Copy(&data[offset], header.reserved1); - offset += Copy(&data[offset], header.reserved2); - Copy(&data[offset], header.offset); - - file->Write(data, Header::header_size, 1); - } - - void Bitmap::WriteDIB(DIB& dib, IOStream* file) { - uint8_t data[DIB::dib_size]; - - std::size_t offset = 0; - - offset += Copy(&data[offset], dib.size); - offset += Copy(&data[offset], dib.width); - offset += Copy(&data[offset], dib.height); - offset += Copy(&data[offset], dib.planes); - offset += Copy(&data[offset], dib.bits_per_pixel); - offset += Copy(&data[offset], dib.compression); - offset += Copy(&data[offset], dib.image_size); - offset += Copy(&data[offset], dib.x_resolution); - offset += Copy(&data[offset], dib.y_resolution); - offset += Copy(&data[offset], dib.nb_colors); - Copy(&data[offset], dib.nb_important_colors); - - file->Write(data, DIB::dib_size, 1); - } - - void Bitmap::WriteData(aiTexture* texture, IOStream* file) { - static const std::size_t padding_offset = 4; - static const uint8_t padding_data[padding_offset] = {0x0, 0x0, 0x0, 0x0}; - - unsigned int padding = (padding_offset - ((mBytesPerPixel * texture->mWidth) % padding_offset)) % padding_offset; - uint8_t pixel[mBytesPerPixel]; - - for(std::size_t i = 0; i < texture->mHeight; ++i) { - for(std::size_t j = 0; j < texture->mWidth; ++j) { - const aiTexel& texel = texture->pcData[(texture->mHeight - i - 1) * texture->mWidth + j]; // Bitmap files are stored in bottom-up format - - pixel[0] = texel.r; - pixel[1] = texel.g; - pixel[2] = texel.b; - pixel[3] = texel.a; - - file->Write(pixel, mBytesPerPixel, 1); - } - - file->Write(padding_data, padding, 1); - } - } - } + +template +inline std::size_t Copy(uint8_t *data, const T &field) { +#ifdef AI_BUILD_BIG_ENDIAN + T field_swapped = AI_BE(field); + std::memcpy(data, &field_swapped, sizeof(field)); + return sizeof(field); +#else + std::memcpy(data, &AI_BE(field), sizeof(field)); + return sizeof(field); +#endif +} + +void Bitmap::WriteHeader(Header &header, IOStream *file) { + uint8_t data[Header::header_size]; + + std::size_t offset = 0; + + offset += Copy(&data[offset], header.type); + offset += Copy(&data[offset], header.size); + offset += Copy(&data[offset], header.reserved1); + offset += Copy(&data[offset], header.reserved2); + Copy(&data[offset], header.offset); + + file->Write(data, Header::header_size, 1); +} + +void Bitmap::WriteDIB(DIB &dib, IOStream *file) { + uint8_t data[DIB::dib_size]; + + std::size_t offset = 0; + + offset += Copy(&data[offset], dib.size); + offset += Copy(&data[offset], dib.width); + offset += Copy(&data[offset], dib.height); + offset += Copy(&data[offset], dib.planes); + offset += Copy(&data[offset], dib.bits_per_pixel); + offset += Copy(&data[offset], dib.compression); + offset += Copy(&data[offset], dib.image_size); + offset += Copy(&data[offset], dib.x_resolution); + offset += Copy(&data[offset], dib.y_resolution); + offset += Copy(&data[offset], dib.nb_colors); + Copy(&data[offset], dib.nb_important_colors); + + file->Write(data, DIB::dib_size, 1); +} + +void Bitmap::WriteData(aiTexture *texture, IOStream *file) { + static const std::size_t padding_offset = 4; + static const uint8_t padding_data[padding_offset] = { 0x0, 0x0, 0x0, 0x0 }; + + unsigned int padding = (padding_offset - ((mBytesPerPixel * texture->mWidth) % padding_offset)) % padding_offset; + uint8_t pixel[mBytesPerPixel]; + + for (std::size_t i = 0; i < texture->mHeight; ++i) { + for (std::size_t j = 0; j < texture->mWidth; ++j) { + const aiTexel &texel = texture->pcData[(texture->mHeight - i - 1) * texture->mWidth + j]; // Bitmap files are stored in bottom-up format + + pixel[0] = texel.r; + pixel[1] = texel.g; + pixel[2] = texel.b; + pixel[3] = texel.a; + + file->Write(pixel, mBytesPerPixel, 1); + } + + file->Write(padding_data, padding, 1); + } +} + +} // namespace Assimp diff --git a/code/Common/CreateAnimMesh.cpp b/code/Common/CreateAnimMesh.cpp index 7317dc45b..05472529d 100644 --- a/code/Common/CreateAnimMesh.cpp +++ b/code/Common/CreateAnimMesh.cpp @@ -70,7 +70,7 @@ aiAnimMesh *aiCreateAnimMesh(const aiMesh *mesh) animesh->mColors[i] = new aiColor4D[animesh->mNumVertices]; std::memcpy(animesh->mColors[i], mesh->mColors[i], mesh->mNumVertices * sizeof(aiColor4D)); } else { - animesh->mColors[i] = NULL; + animesh->mColors[i] = nullptr; } } @@ -79,7 +79,7 @@ aiAnimMesh *aiCreateAnimMesh(const aiMesh *mesh) animesh->mTextureCoords[i] = new aiVector3D[animesh->mNumVertices]; std::memcpy(animesh->mTextureCoords[i], mesh->mTextureCoords[i], mesh->mNumVertices * sizeof(aiVector3D)); } else { - animesh->mTextureCoords[i] = NULL; + animesh->mTextureCoords[i] = nullptr; } } return animesh; diff --git a/code/Common/DefaultIOStream.cpp b/code/Common/DefaultIOStream.cpp index 63b44d861..65edd1bdd 100644 --- a/code/Common/DefaultIOStream.cpp +++ b/code/Common/DefaultIOStream.cpp @@ -44,46 +44,39 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * @brief Default File I/O implementation for #Importer */ - -#include #include -#include +#include #include +#include using namespace Assimp; -namespace -{ - template - size_t select_ftell(FILE* file) - { - return ::ftell(file); - } - - template - int select_fseek(FILE* file, int64_t offset, int origin) - { - return ::fseek(file, static_cast(offset), origin); - } - -#if defined _WIN32 && (!defined __GNUC__ || __MSVCRT_VERSION__ >= 0x0601) - template<> - size_t select_ftell<8>(FILE* file) - { - return (size_t)::_ftelli64(file); - } - - template<> - int select_fseek<8>(FILE* file, int64_t offset, int origin) - { - return ::_fseeki64(file, offset, origin); - } -#endif +namespace { +template +size_t select_ftell(FILE *file) { + return ::ftell(file); } +template +int select_fseek(FILE *file, int64_t offset, int origin) { + return ::fseek(file, static_cast(offset), origin); +} + +#if defined _WIN32 && (!defined __GNUC__ || __MSVCRT_VERSION__ >= 0x0601) +template <> +size_t select_ftell<8>(FILE *file) { + return (size_t)::_ftelli64(file); +} + +template <> +int select_fseek<8>(FILE *file, int64_t offset, int origin) { + return ::_fseeki64(file, offset, origin); +} +#endif +} // namespace + // ---------------------------------------------------------------------------------- -DefaultIOStream::~DefaultIOStream() -{ +DefaultIOStream::~DefaultIOStream() { if (mFile) { ::fclose(mFile); mFile = nullptr; @@ -91,57 +84,59 @@ DefaultIOStream::~DefaultIOStream() } // ---------------------------------------------------------------------------------- -size_t DefaultIOStream::Read(void* pvBuffer, - size_t pSize, - size_t pCount) -{ - ai_assert(NULL != pvBuffer && 0 != pSize && 0 != pCount); +size_t DefaultIOStream::Read(void *pvBuffer, + size_t pSize, + size_t pCount) { + ai_assert(nullptr != pvBuffer); + ai_assert(0 != pSize); + ai_assert(0 != pCount); + return (mFile ? ::fread(pvBuffer, pSize, pCount, mFile) : 0); } // ---------------------------------------------------------------------------------- -size_t DefaultIOStream::Write(const void* pvBuffer, - size_t pSize, - size_t pCount) -{ - ai_assert(NULL != pvBuffer && 0 != pSize && 0 != pCount); +size_t DefaultIOStream::Write(const void *pvBuffer, + size_t pSize, + size_t pCount) { + ai_assert(nullptr != pvBuffer); + ai_assert(0 != pSize); + ai_assert(0 != pCount); + return (mFile ? ::fwrite(pvBuffer, pSize, pCount, mFile) : 0); } // ---------------------------------------------------------------------------------- aiReturn DefaultIOStream::Seek(size_t pOffset, - aiOrigin pOrigin) -{ + aiOrigin pOrigin) { if (!mFile) { return AI_FAILURE; } // Just to check whether our enum maps one to one with the CRT constants static_assert(aiOrigin_CUR == SEEK_CUR && - aiOrigin_END == SEEK_END && aiOrigin_SET == SEEK_SET, "aiOrigin_CUR == SEEK_CUR && \ + aiOrigin_END == SEEK_END && aiOrigin_SET == SEEK_SET, + "aiOrigin_CUR == SEEK_CUR && \ aiOrigin_END == SEEK_END && aiOrigin_SET == SEEK_SET"); // do the seek - return (0 == select_fseek(mFile, (int64_t)pOffset,(int)pOrigin) ? AI_SUCCESS : AI_FAILURE); + return (0 == select_fseek(mFile, (int64_t)pOffset, (int)pOrigin) ? AI_SUCCESS : AI_FAILURE); } // ---------------------------------------------------------------------------------- -size_t DefaultIOStream::Tell() const -{ +size_t DefaultIOStream::Tell() const { if (!mFile) { return 0; } - return select_ftell(mFile); + return select_ftell(mFile); } // ---------------------------------------------------------------------------------- -size_t DefaultIOStream::FileSize() const -{ - if (! mFile || mFilename.empty()) { +size_t DefaultIOStream::FileSize() const { + if (!mFile || mFilename.empty()) { return 0; } - if (SIZE_MAX == mCachedSize ) { + if (SIZE_MAX == mCachedSize) { // Although fseek/ftell would allow us to reuse the existing file handle here, // it is generally unsafe because: @@ -154,27 +149,26 @@ size_t DefaultIOStream::FileSize() const #if defined _WIN32 && (!defined __GNUC__ || __MSVCRT_VERSION__ >= 0x0601) struct __stat64 fileStat; //using fileno + fstat avoids having to handle the filename - int err = _fstat64( _fileno(mFile), &fileStat ); + int err = _fstat64(_fileno(mFile), &fileStat); if (0 != err) return 0; - mCachedSize = (size_t) (fileStat.st_size); + mCachedSize = (size_t)(fileStat.st_size); #elif defined __GNUC__ || defined __APPLE__ || defined __MACH__ || defined __FreeBSD__ struct stat fileStat; - int err = stat(mFilename.c_str(), &fileStat ); + int err = stat(mFilename.c_str(), &fileStat); if (0 != err) return 0; const unsigned long long cachedSize = fileStat.st_size; - mCachedSize = static_cast< size_t >( cachedSize ); + mCachedSize = static_cast(cachedSize); #else -# error "Unknown platform" +#error "Unknown platform" #endif } return mCachedSize; } // ---------------------------------------------------------------------------------- -void DefaultIOStream::Flush() -{ +void DefaultIOStream::Flush() { if (mFile) { ::fflush(mFile); } diff --git a/code/Common/DefaultLogger.cpp b/code/Common/DefaultLogger.cpp index 6b2f9252b..8c946e8fd 100644 --- a/code/Common/DefaultLogger.cpp +++ b/code/Common/DefaultLogger.cpp @@ -46,25 +46,25 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ // Default log streams -#include "Win32DebugLogStream.h" -#include "StdOStreamLogStream.h" #include "FileLogStream.h" +#include "StdOStreamLogStream.h" +#include "Win32DebugLogStream.h" #include #include -#include -#include #include -#include #include +#include +#include +#include #ifndef ASSIMP_BUILD_SINGLETHREADED -# include -# include - std::mutex loggerMutex; +#include +#include +std::mutex loggerMutex; #endif -namespace Assimp { +namespace Assimp { // ---------------------------------------------------------------------------------- NullLogger DefaultLogger::s_pNullLogger; @@ -75,13 +75,13 @@ static const unsigned int SeverityAll = Logger::Info | Logger::Err | Logger::War // ---------------------------------------------------------------------------------- // Represents a log-stream + its error severity struct LogStreamInfo { - unsigned int m_uiErrorSeverity; - LogStream *m_pStream; + unsigned int m_uiErrorSeverity; + LogStream *m_pStream; // Constructor - LogStreamInfo( unsigned int uiErrorSev, LogStream *pStream ) : - m_uiErrorSeverity( uiErrorSev ), - m_pStream( pStream ) { + LogStreamInfo(unsigned int uiErrorSev, LogStream *pStream) : + m_uiErrorSeverity(uiErrorSev), + m_pStream(pStream) { // empty } @@ -93,12 +93,10 @@ struct LogStreamInfo { // ---------------------------------------------------------------------------------- // Construct a default log stream -LogStream* LogStream::createDefaultStream(aiDefaultLogStream streams, - const char* name /*= "AssimpLog.txt"*/, - IOSystem* io /*= NULL*/) -{ - switch (streams) - { +LogStream *LogStream::createDefaultStream(aiDefaultLogStream streams, + const char *name /*= "AssimpLog.txt"*/, + IOSystem *io /*= nullptr*/) { + switch (streams) { // This is a platform-specific feature case aiDefaultLogStream_DEBUGGER: #ifdef WIN32 @@ -113,11 +111,10 @@ LogStream* LogStream::createDefaultStream(aiDefaultLogStream streams, case aiDefaultLogStream_STDOUT: return new StdOStreamLogStream(std::cout); case aiDefaultLogStream_FILE: - return (name && *name ? new FileLogStream(name,io) : nullptr ); + return (name && *name ? new FileLogStream(name, io) : nullptr); default: // We don't know this default log stream, so raise an assertion ai_assert(false); - }; // For compilers without dead code path detection @@ -126,52 +123,52 @@ LogStream* LogStream::createDefaultStream(aiDefaultLogStream streams, // ---------------------------------------------------------------------------------- // Creates the only singleton instance -Logger *DefaultLogger::create(const char* name /*= "AssimpLog.txt"*/, - LogSeverity severity /*= NORMAL*/, - unsigned int defStreams /*= aiDefaultLogStream_DEBUGGER | aiDefaultLogStream_FILE*/, - IOSystem* io /*= NULL*/) { +Logger *DefaultLogger::create(const char *name /*= "AssimpLog.txt"*/, + LogSeverity severity /*= NORMAL*/, + unsigned int defStreams /*= aiDefaultLogStream_DEBUGGER | aiDefaultLogStream_FILE*/, + IOSystem *io /*= nullptr*/) { // enter the mutex here to avoid concurrency problems #ifndef ASSIMP_BUILD_SINGLETHREADED std::lock_guard lock(loggerMutex); #endif - if ( m_pLogger && !isNullLogger() ) { + if (m_pLogger && !isNullLogger()) { delete m_pLogger; } - m_pLogger = new DefaultLogger( severity ); + m_pLogger = new DefaultLogger(severity); // Attach default log streams // Stream the log to the MSVC debugger? - if ( defStreams & aiDefaultLogStream_DEBUGGER ) { - m_pLogger->attachStream( LogStream::createDefaultStream( aiDefaultLogStream_DEBUGGER ) ); + if (defStreams & aiDefaultLogStream_DEBUGGER) { + m_pLogger->attachStream(LogStream::createDefaultStream(aiDefaultLogStream_DEBUGGER)); } // Stream the log to COUT? - if ( defStreams & aiDefaultLogStream_STDOUT ) { - m_pLogger->attachStream( LogStream::createDefaultStream( aiDefaultLogStream_STDOUT ) ); + if (defStreams & aiDefaultLogStream_STDOUT) { + m_pLogger->attachStream(LogStream::createDefaultStream(aiDefaultLogStream_STDOUT)); } // Stream the log to CERR? - if ( defStreams & aiDefaultLogStream_STDERR ) { - m_pLogger->attachStream( LogStream::createDefaultStream( aiDefaultLogStream_STDERR ) ); + if (defStreams & aiDefaultLogStream_STDERR) { + m_pLogger->attachStream(LogStream::createDefaultStream(aiDefaultLogStream_STDERR)); } // Stream the log to a file - if ( defStreams & aiDefaultLogStream_FILE && name && *name ) { - m_pLogger->attachStream( LogStream::createDefaultStream( aiDefaultLogStream_FILE, name, io ) ); + if (defStreams & aiDefaultLogStream_FILE && name && *name) { + m_pLogger->attachStream(LogStream::createDefaultStream(aiDefaultLogStream_FILE, name, io)); } return m_pLogger; } // ---------------------------------------------------------------------------------- -void Logger::debug(const char* message) { +void Logger::debug(const char *message) { // SECURITY FIX: otherwise it's easy to produce overruns since // sometimes importers will include data from the input file // (i.e. node names) in their messages. - if (strlen(message)>MAX_LOG_MESSAGE_LENGTH) { + if (strlen(message) > MAX_LOG_MESSAGE_LENGTH) { return; } return OnDebug(message); @@ -180,55 +177,55 @@ void Logger::debug(const char* message) { // ---------------------------------------------------------------------------------- void Logger::verboseDebug(const char *message) { - // SECURITY FIX: otherwise it's easy to produce overruns since - // sometimes importers will include data from the input file - // (i.e. node names) in their messages. - if (strlen(message) > MAX_LOG_MESSAGE_LENGTH) { - return; - } - return OnVerboseDebug(message); + // SECURITY FIX: otherwise it's easy to produce overruns since + // sometimes importers will include data from the input file + // (i.e. node names) in their messages. + if (strlen(message) > MAX_LOG_MESSAGE_LENGTH) { + return; + } + return OnVerboseDebug(message); } // ---------------------------------------------------------------------------------- -void Logger::info(const char* message) { +void Logger::info(const char *message) { // SECURITY FIX: see above - if (strlen(message)>MAX_LOG_MESSAGE_LENGTH) { + if (strlen(message) > MAX_LOG_MESSAGE_LENGTH) { return; } return OnInfo(message); } // ---------------------------------------------------------------------------------- -void Logger::warn(const char* message) { +void Logger::warn(const char *message) { // SECURITY FIX: see above - if (strlen(message)>MAX_LOG_MESSAGE_LENGTH) { + if (strlen(message) > MAX_LOG_MESSAGE_LENGTH) { return; } return OnWarn(message); } // ---------------------------------------------------------------------------------- -void Logger::error(const char* message) { +void Logger::error(const char *message) { // SECURITY FIX: see above - if (strlen(message)>MAX_LOG_MESSAGE_LENGTH) { + if (strlen(message) > MAX_LOG_MESSAGE_LENGTH) { return; } return OnError(message); } // ---------------------------------------------------------------------------------- -void DefaultLogger::set( Logger *logger ) { +void DefaultLogger::set(Logger *logger) { // enter the mutex here to avoid concurrency problems #ifndef ASSIMP_BUILD_SINGLETHREADED std::lock_guard lock(loggerMutex); #endif - if ( nullptr == logger ) { + if (nullptr == logger) { logger = &s_pNullLogger; } - if ( nullptr != m_pLogger && !isNullLogger() ) { + if (nullptr != m_pLogger && !isNullLogger()) { delete m_pLogger; } @@ -253,116 +250,115 @@ void DefaultLogger::kill() { std::lock_guard lock(loggerMutex); #endif - if ( m_pLogger == &s_pNullLogger ) { - return; - } + if (m_pLogger == &s_pNullLogger) { + return; + } delete m_pLogger; m_pLogger = &s_pNullLogger; } // ---------------------------------------------------------------------------------- // Debug message -void DefaultLogger::OnDebug( const char* message ) { - if ( m_Severity < Logger::DEBUG ) { +void DefaultLogger::OnDebug(const char *message) { + if (m_Severity < Logger::DEBUG) { return; } - static const size_t Size = MAX_LOG_MESSAGE_LENGTH + 16; - char msg[Size]; - ai_snprintf(msg, Size, "Debug, T%u: %s", GetThreadID(), message); + static const size_t Size = MAX_LOG_MESSAGE_LENGTH + 16; + char msg[Size]; + ai_snprintf(msg, Size, "Debug, T%u: %s", GetThreadID(), message); - WriteToStreams( msg, Logger::Debugging ); + WriteToStreams(msg, Logger::Debugging); } // Verbose debug message void DefaultLogger::OnVerboseDebug(const char *message) { - if (m_Severity < Logger::VERBOSE) { - return; - } + if (m_Severity < Logger::VERBOSE) { + return; + } - static const size_t Size = MAX_LOG_MESSAGE_LENGTH + 16; - char msg[Size]; - ai_snprintf(msg, Size, "Debug, T%u: %s", GetThreadID(), message); + static const size_t Size = MAX_LOG_MESSAGE_LENGTH + 16; + char msg[Size]; + ai_snprintf(msg, Size, "Debug, T%u: %s", GetThreadID(), message); - WriteToStreams(msg, Logger::Debugging); + WriteToStreams(msg, Logger::Debugging); } // ---------------------------------------------------------------------------------- // Logs an info -void DefaultLogger::OnInfo( const char* message ){ - static const size_t Size = MAX_LOG_MESSAGE_LENGTH + 16; - char msg[Size]; - ai_snprintf(msg, Size, "Info, T%u: %s", GetThreadID(), message ); +void DefaultLogger::OnInfo(const char *message) { + static const size_t Size = MAX_LOG_MESSAGE_LENGTH + 16; + char msg[Size]; + ai_snprintf(msg, Size, "Info, T%u: %s", GetThreadID(), message); - WriteToStreams( msg , Logger::Info ); + WriteToStreams(msg, Logger::Info); } // ---------------------------------------------------------------------------------- // Logs a warning -void DefaultLogger::OnWarn( const char* message ) { - static const size_t Size = MAX_LOG_MESSAGE_LENGTH + 16; - char msg[Size]; - ai_snprintf(msg, Size, "Warn, T%u: %s", GetThreadID(), message ); +void DefaultLogger::OnWarn(const char *message) { + static const size_t Size = MAX_LOG_MESSAGE_LENGTH + 16; + char msg[Size]; + ai_snprintf(msg, Size, "Warn, T%u: %s", GetThreadID(), message); - WriteToStreams( msg, Logger::Warn ); + WriteToStreams(msg, Logger::Warn); } // ---------------------------------------------------------------------------------- // Logs an error -void DefaultLogger::OnError( const char* message ) { - static const size_t Size = MAX_LOG_MESSAGE_LENGTH + 16; - char msg[ Size ]; - ai_snprintf(msg, Size, "Error, T%u: %s", GetThreadID(), message ); +void DefaultLogger::OnError(const char *message) { + static const size_t Size = MAX_LOG_MESSAGE_LENGTH + 16; + char msg[Size]; + ai_snprintf(msg, Size, "Error, T%u: %s", GetThreadID(), message); - WriteToStreams( msg, Logger::Err ); + WriteToStreams(msg, Logger::Err); } // ---------------------------------------------------------------------------------- // Will attach a new stream -bool DefaultLogger::attachStream( LogStream *pStream, unsigned int severity ) { - if ( nullptr == pStream ) { +bool DefaultLogger::attachStream(LogStream *pStream, unsigned int severity) { + if (nullptr == pStream) { return false; } - if (0 == severity) { + if (0 == severity) { severity = Logger::Info | Logger::Err | Logger::Warn | Logger::Debugging; } - for ( StreamIt it = m_StreamArray.begin(); - it != m_StreamArray.end(); - ++it ) - { - if ( (*it)->m_pStream == pStream ) { + for (StreamIt it = m_StreamArray.begin(); + it != m_StreamArray.end(); + ++it) { + if ((*it)->m_pStream == pStream) { (*it)->m_uiErrorSeverity |= severity; return true; } } - LogStreamInfo *pInfo = new LogStreamInfo( severity, pStream ); - m_StreamArray.push_back( pInfo ); + LogStreamInfo *pInfo = new LogStreamInfo(severity, pStream); + m_StreamArray.push_back(pInfo); return true; } // ---------------------------------------------------------------------------------- // Detach a stream -bool DefaultLogger::detachStream( LogStream *pStream, unsigned int severity ) { - if ( nullptr == pStream ) { +bool DefaultLogger::detachStream(LogStream *pStream, unsigned int severity) { + if (nullptr == pStream) { return false; } - if (0 == severity) { + if (0 == severity) { severity = SeverityAll; } - bool res( false ); - for ( StreamIt it = m_StreamArray.begin(); it != m_StreamArray.end(); ++it ) { - if ( (*it)->m_pStream == pStream ) { + bool res(false); + for (StreamIt it = m_StreamArray.begin(); it != m_StreamArray.end(); ++it) { + if ((*it)->m_pStream == pStream) { (*it)->m_uiErrorSeverity &= ~severity; - if ( (*it)->m_uiErrorSeverity == 0 ) { + if ((*it)->m_uiErrorSeverity == 0) { // don't delete the underlying stream 'cause the caller gains ownership again (**it).m_pStream = nullptr; delete *it; - m_StreamArray.erase( it ); + m_StreamArray.erase(it); res = true; break; } @@ -374,17 +370,15 @@ bool DefaultLogger::detachStream( LogStream *pStream, unsigned int severity ) { // ---------------------------------------------------------------------------------- // Constructor -DefaultLogger::DefaultLogger(LogSeverity severity) - : Logger ( severity ) - , noRepeatMsg (false) - , lastLen( 0 ) { +DefaultLogger::DefaultLogger(LogSeverity severity) : + Logger(severity), noRepeatMsg(false), lastLen(0) { lastMsg[0] = '\0'; } // ---------------------------------------------------------------------------------- // Destructor DefaultLogger::~DefaultLogger() { - for ( StreamIt it = m_StreamArray.begin(); it != m_StreamArray.end(); ++it ) { + for (StreamIt it = m_StreamArray.begin(); it != m_StreamArray.end(); ++it) { // also frees the underlying stream, we are its owner. delete *it; } @@ -392,43 +386,37 @@ DefaultLogger::~DefaultLogger() { // ---------------------------------------------------------------------------------- // Writes message to stream -void DefaultLogger::WriteToStreams(const char *message, ErrorSeverity ErrorSev ) { +void DefaultLogger::WriteToStreams(const char *message, ErrorSeverity ErrorSev) { ai_assert(nullptr != message); // Check whether this is a repeated message - if (! ::strncmp( message,lastMsg, lastLen-1)) - { - if (!noRepeatMsg) - { + if (!::strncmp(message, lastMsg, lastLen - 1)) { + if (!noRepeatMsg) { noRepeatMsg = true; message = "Skipping one or more lines with the same contents\n"; - } - else return; - } - else - { + } else + return; + } else { // append a new-line character to the message to be printed lastLen = ::strlen(message); - ::memcpy(lastMsg,message,lastLen+1); - ::strcat(lastMsg+lastLen,"\n"); + ::memcpy(lastMsg, message, lastLen + 1); + ::strcat(lastMsg + lastLen, "\n"); message = lastMsg; noRepeatMsg = false; ++lastLen; } - for ( ConstStreamIt it = m_StreamArray.begin(); - it != m_StreamArray.end(); - ++it) - { - if ( ErrorSev & (*it)->m_uiErrorSeverity ) - (*it)->m_pStream->write( message); + for (ConstStreamIt it = m_StreamArray.begin(); + it != m_StreamArray.end(); + ++it) { + if (ErrorSev & (*it)->m_uiErrorSeverity) + (*it)->m_pStream->write(message); } } // ---------------------------------------------------------------------------------- // Returns thread id, if not supported only a zero will be returned. -unsigned int DefaultLogger::GetThreadID() -{ +unsigned int DefaultLogger::GetThreadID() { // fixme: we can get this value via std::threads // std::this_thread::get_id().hash() returns a (big) size_t, not sure if this is useful in this case. #ifdef WIN32 @@ -440,4 +428,4 @@ unsigned int DefaultLogger::GetThreadID() // ---------------------------------------------------------------------------------- -} // !namespace Assimp +} // namespace Assimp diff --git a/code/Common/Exporter.cpp b/code/Common/Exporter.cpp index c34457be5..58fc01d91 100644 --- a/code/Common/Exporter.cpp +++ b/code/Common/Exporter.cpp @@ -475,7 +475,7 @@ aiReturn Exporter::Export( const aiScene* pScene, const char* pFormatId, const c proc.Execute(scenecopy.get()); } - ExportProperties emptyProperties; // Never pass NULL ExportProperties so Exporters don't have to worry. + ExportProperties emptyProperties; // Never pass nullptr ExportProperties so Exporters don't have to worry. ExportProperties* pProp = pProperties ? (ExportProperties*)pProperties : &emptyProperties; pProp->SetPropertyBool("bJoinIdenticalVertices", pp & aiProcess_JoinIdenticalVertices); exp.mExportFunction(pPath,pimpl->mIOSystem.get(),scenecopy.get(), pProp); diff --git a/code/Common/FileLogStream.h b/code/Common/FileLogStream.h index ecff03a7e..f6b4520ae 100644 --- a/code/Common/FileLogStream.h +++ b/code/Common/FileLogStream.h @@ -43,23 +43,21 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef ASSIMP_FILELOGSTREAM_H_INC #define ASSIMP_FILELOGSTREAM_H_INC -#include -#include #include +#include +#include -namespace Assimp { +namespace Assimp { // ---------------------------------------------------------------------------------- /** @class FileLogStream * @brief Logstream to write into a file. */ -class FileLogStream : - public LogStream -{ +class FileLogStream : public LogStream { public: - FileLogStream( const char* file, IOSystem* io = NULL ); + FileLogStream(const char *file, IOSystem *io = nullptr); ~FileLogStream(); - void write( const char* message ); + void write(const char *message); private: IOStream *m_pStream; @@ -67,41 +65,36 @@ private: // ---------------------------------------------------------------------------------- // Constructor -inline FileLogStream::FileLogStream( const char* file, IOSystem* io ) : - m_pStream(NULL) -{ - if ( !file || 0 == *file ) +inline FileLogStream::FileLogStream(const char *file, IOSystem *io) : + m_pStream(nullptr) { + if (!file || 0 == *file) return; // If no IOSystem is specified: take a default one - if (!io) - { + if (!io) { DefaultIOSystem FileSystem; - m_pStream = FileSystem.Open( file, "wt"); - } - else m_pStream = io->Open( file, "wt" ); + m_pStream = FileSystem.Open(file, "wt"); + } else + m_pStream = io->Open(file, "wt"); } // ---------------------------------------------------------------------------------- // Destructor -inline FileLogStream::~FileLogStream() -{ +inline FileLogStream::~FileLogStream() { // The virtual d'tor should destroy the underlying file delete m_pStream; } // ---------------------------------------------------------------------------------- // Write method -inline void FileLogStream::write( const char* message ) -{ - if (m_pStream != NULL) - { +inline void FileLogStream::write(const char *message) { + if (m_pStream != nullptr) { m_pStream->Write(message, sizeof(char), ::strlen(message)); m_pStream->Flush(); } } // ---------------------------------------------------------------------------------- -} // !Namespace Assimp +} // namespace Assimp #endif // !! ASSIMP_FILELOGSTREAM_H_INC diff --git a/code/Common/Importer.cpp b/code/Common/Importer.cpp index a59ec9812..a46d39b48 100644 --- a/code/Common/Importer.cpp +++ b/code/Common/Importer.cpp @@ -249,7 +249,7 @@ aiReturn Importer::RegisterLoader(BaseImporter* pImp) { // Unregister a custom loader plugin aiReturn Importer::UnregisterLoader(BaseImporter* pImp) { if(!pImp) { - // unregistering a NULL importer is no problem for us ... really! + // unregistering a nullptr importer is no problem for us ... really! return AI_SUCCESS; } @@ -272,7 +272,7 @@ aiReturn Importer::UnregisterLoader(BaseImporter* pImp) { // Unregister a custom loader plugin aiReturn Importer::UnregisterPPStep(BaseProcess* pImp) { if(!pImp) { - // unregistering a NULL ppstep is no problem for us ... really! + // unregistering a nullptr ppstep is no problem for us ... really! return AI_SUCCESS; } @@ -593,7 +593,7 @@ const aiScene* Importer::ReadFile( const char* _pFile, unsigned int pFlags) { return nullptr; } - std::unique_ptr profiler(GetPropertyInteger(AI_CONFIG_GLOB_MEASURE_TIME,0)?new Profiler():NULL); + std::unique_ptr profiler(GetPropertyInteger(AI_CONFIG_GLOB_MEASURE_TIME, 0) ? new Profiler() : nullptr); if (profiler) { profiler->BeginRegion("total"); } @@ -775,7 +775,7 @@ const aiScene* Importer::ApplyPostProcessing(unsigned int pFlags) { } #endif // ! DEBUG - std::unique_ptr profiler(GetPropertyInteger(AI_CONFIG_GLOB_MEASURE_TIME,0)?new Profiler():NULL); + std::unique_ptr profiler(GetPropertyInteger(AI_CONFIG_GLOB_MEASURE_TIME, 0) ? new Profiler() : nullptr); for( unsigned int a = 0; a < pimpl->mPostProcessingSteps.size(); a++) { BaseProcess* process = pimpl->mPostProcessingSteps[a]; pimpl->mProgressHandler->UpdatePostProcess(static_cast(a), static_cast(pimpl->mPostProcessingSteps.size()) ); @@ -841,7 +841,7 @@ const aiScene* Importer::ApplyCustomizedPostProcessing( BaseProcess *rootProcess } // If no flags are given, return the current scene with no further action - if ( NULL == rootProcess ) { + if (nullptr == rootProcess) { return pimpl->mScene; } @@ -873,7 +873,7 @@ const aiScene* Importer::ApplyCustomizedPostProcessing( BaseProcess *rootProcess } #endif // ! DEBUG - std::unique_ptr profiler( GetPropertyInteger( AI_CONFIG_GLOB_MEASURE_TIME, 0 ) ? new Profiler() : NULL ); + std::unique_ptr profiler(GetPropertyInteger(AI_CONFIG_GLOB_MEASURE_TIME, 0) ? new Profiler() : nullptr); if ( profiler ) { profiler->BeginRegion( "postprocess" ); diff --git a/code/Common/Importer.h b/code/Common/Importer.h index c31f67caa..eaf42e9c5 100644 --- a/code/Common/Importer.h +++ b/code/Common/Importer.h @@ -94,7 +94,7 @@ public: /** Post processing steps we can apply at the imported data. */ std::vector< BaseProcess* > mPostProcessingSteps; - /** The imported data, if ReadFile() was successful, NULL otherwise. */ + /** The imported data, if ReadFile() was successful, nullptr otherwise. */ aiScene* mScene; /** The error description, if there was one. */ @@ -216,7 +216,7 @@ public: unsigned int AddLoadRequest ( const std::string& file, unsigned int steps = 0, - const PropertyMap* map = NULL + const PropertyMap *map = nullptr ); // ------------------------------------------------------------------- @@ -226,7 +226,7 @@ public: * can be called several times, too. * * @param which LRWC returned by AddLoadRequest(). - * @return NULL if there is no scene with this file name + * @return nullptr if there is no scene with this file name * in the queue of the scene hasn't been loaded yet. */ aiScene* GetImport( unsigned int which diff --git a/code/Common/RemoveComments.cpp b/code/Common/RemoveComments.cpp index f7e735c16..0e3e0f564 100644 --- a/code/Common/RemoveComments.cpp +++ b/code/Common/RemoveComments.cpp @@ -55,7 +55,9 @@ void CommentRemover::RemoveLineComments(const char* szComment, char* szBuffer, char chReplacement /* = ' ' */) { // validate parameters - ai_assert(NULL != szComment && NULL != szBuffer && *szComment); + ai_assert(nullptr != szComment); + ai_assert(nullptr != szBuffer); + ai_assert(*szComment); const size_t len = strlen(szComment); while (*szBuffer) { @@ -83,8 +85,11 @@ void CommentRemover::RemoveMultiLineComments(const char* szCommentStart, char chReplacement) { // validate parameters - ai_assert(NULL != szCommentStart && NULL != szCommentEnd && - NULL != szBuffer && *szCommentStart && *szCommentEnd); + ai_assert(nullptr != szCommentStart); + ai_assert(nullptr != szCommentEnd); + ai_assert(nullptr != szBuffer); + ai_assert(*szCommentStart); + ai_assert(*szCommentEnd); const size_t len = strlen(szCommentEnd); const size_t len2 = strlen(szCommentStart); diff --git a/code/Common/SceneCombiner.cpp b/code/Common/SceneCombiner.cpp index eb802dd8b..bfc4899a1 100644 --- a/code/Common/SceneCombiner.cpp +++ b/code/Common/SceneCombiner.cpp @@ -52,37 +52,41 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * OptimizeGraph step. */ // ---------------------------------------------------------------------------- +#include "ScenePrivate.h" +#include "time.h" +#include #include #include #include -#include -#include -#include "time.h" -#include -#include #include +#include +#include #include -#include "ScenePrivate.h" +#include namespace Assimp { +#if (__GNUC__ >= 8 && __GNUC_MINOR__ >= 0) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wclass-memaccess" +#endif + // ------------------------------------------------------------------------------------------------ // Add a prefix to a string -inline -void PrefixString(aiString& string,const char* prefix, unsigned int len) { +inline void PrefixString(aiString &string, const char *prefix, unsigned int len) { // If the string is already prefixed, we won't prefix it a second time if (string.length >= 1 && string.data[0] == '$') return; - if (len+string.length>=MAXLEN-1) { - ASSIMP_LOG_VERBOSE_DEBUG("Can't add an unique prefix because the string is too long"); + if (len + string.length >= MAXLEN - 1) { + ASSIMP_LOG_VERBOSE_DEBUG("Can't add an unique prefix because the string is too long"); ai_assert(false); return; } // Add the prefix - ::memmove(string.data+len,string.data,string.length+1); - ::memcpy (string.data, prefix, len); + ::memmove(string.data + len, string.data, string.length + 1); + ::memcpy(string.data, prefix, len); // And update the string's length string.length += len; @@ -90,33 +94,35 @@ void PrefixString(aiString& string,const char* prefix, unsigned int len) { // ------------------------------------------------------------------------------------------------ // Add node identifiers to a hashing set -void SceneCombiner::AddNodeHashes(aiNode* node, std::set& hashes) { +void SceneCombiner::AddNodeHashes(aiNode *node, std::set &hashes) { // Add node name to hashing set if it is non-empty - empty nodes are allowed // and they can't have any anims assigned so its absolutely safe to duplicate them. if (node->mName.length) { - hashes.insert( SuperFastHash(node->mName.data, static_cast(node->mName.length)) ); + hashes.insert(SuperFastHash(node->mName.data, static_cast(node->mName.length))); } // Process all children recursively - for (unsigned int i = 0; i < node->mNumChildren;++i) - AddNodeHashes(node->mChildren[i],hashes); + for (unsigned int i = 0; i < node->mNumChildren; ++i) { + AddNodeHashes(node->mChildren[i], hashes); + } } // ------------------------------------------------------------------------------------------------ // Add a name prefix to all nodes in a hierarchy -void SceneCombiner::AddNodePrefixes(aiNode* node, const char* prefix, unsigned int len) { - ai_assert(NULL != prefix); - PrefixString(node->mName,prefix,len); +void SceneCombiner::AddNodePrefixes(aiNode *node, const char *prefix, unsigned int len) { + ai_assert(nullptr != prefix); + + PrefixString(node->mName, prefix, len); // Process all children recursively - for ( unsigned int i = 0; i < node->mNumChildren; ++i ) { - AddNodePrefixes( node->mChildren[ i ], prefix, len ); + for (unsigned int i = 0; i < node->mNumChildren; ++i) { + AddNodePrefixes(node->mChildren[i], prefix, len); } } // ------------------------------------------------------------------------------------------------ // Search for matching names -bool SceneCombiner::FindNameMatch(const aiString& name, std::vector& input, unsigned int cur) { +bool SceneCombiner::FindNameMatch(const aiString &name, std::vector &input, unsigned int cur) { const unsigned int hash = SuperFastHash(name.data, static_cast(name.length)); // Check whether we find a positive match in one of the given sets @@ -130,87 +136,90 @@ bool SceneCombiner::FindNameMatch(const aiString& name, std::vector // ------------------------------------------------------------------------------------------------ // Add a name prefix to all nodes in a hierarchy if a hash match is found -void SceneCombiner::AddNodePrefixesChecked(aiNode* node, const char* prefix, unsigned int len, - std::vector& input, unsigned int cur) { - ai_assert(NULL != prefix); +void SceneCombiner::AddNodePrefixesChecked(aiNode *node, const char *prefix, unsigned int len, + std::vector &input, unsigned int cur) { + ai_assert(nullptr != prefix); + const unsigned int hash = SuperFastHash(node->mName.data, static_cast(node->mName.length)); // Check whether we find a positive match in one of the given sets for (unsigned int i = 0; i < input.size(); ++i) { if (cur != i && input[i].hashes.find(hash) != input[i].hashes.end()) { - PrefixString(node->mName,prefix,len); + PrefixString(node->mName, prefix, len); break; } } // Process all children recursively - for (unsigned int i = 0; i < node->mNumChildren;++i) - AddNodePrefixesChecked(node->mChildren[i],prefix,len,input,cur); + for (unsigned int i = 0; i < node->mNumChildren; ++i) { + AddNodePrefixesChecked(node->mChildren[i], prefix, len, input, cur); + } } // ------------------------------------------------------------------------------------------------ // Add an offset to all mesh indices in a node graph -void SceneCombiner::OffsetNodeMeshIndices (aiNode* node, unsigned int offset) { - for (unsigned int i = 0; i < node->mNumMeshes;++i) +void SceneCombiner::OffsetNodeMeshIndices(aiNode *node, unsigned int offset) { + for (unsigned int i = 0; i < node->mNumMeshes; ++i) node->mMeshes[i] += offset; - for ( unsigned int i = 0; i < node->mNumChildren; ++i ) { - OffsetNodeMeshIndices( node->mChildren[ i ], offset ); + for (unsigned int i = 0; i < node->mNumChildren; ++i) { + OffsetNodeMeshIndices(node->mChildren[i], offset); } } // ------------------------------------------------------------------------------------------------ // Merges two scenes. Currently only used by the LWS loader. -void SceneCombiner::MergeScenes(aiScene** _dest,std::vector& src, unsigned int flags) { - if ( nullptr == _dest ) { +void SceneCombiner::MergeScenes(aiScene **_dest, std::vector &src, unsigned int flags) { + if (nullptr == _dest) { return; } - // if _dest points to NULL allocate a new scene. Otherwise clear the old and reuse it + // if _dest points to nullptr allocate a new scene. Otherwise clear the old and reuse it if (src.empty()) { if (*_dest) { (*_dest)->~aiScene(); - SceneCombiner::CopySceneFlat(_dest,src[0]); - } - else *_dest = src[0]; + SceneCombiner::CopySceneFlat(_dest, src[0]); + } else + *_dest = src[0]; return; } - if (*_dest)(*_dest)->~aiScene(); - else *_dest = new aiScene(); + if (*_dest) + (*_dest)->~aiScene(); + else + *_dest = new aiScene(); // Create a dummy scene to serve as master for the others - aiScene* master = new aiScene(); + aiScene *master = new aiScene(); master->mRootNode = new aiNode(); master->mRootNode->mName.Set(""); - std::vector srcList (src.size()); - for (unsigned int i = 0; i < srcList.size();++i) { - srcList[i] = AttachmentInfo(src[i],master->mRootNode); + std::vector srcList(src.size()); + for (unsigned int i = 0; i < srcList.size(); ++i) { + srcList[i] = AttachmentInfo(src[i], master->mRootNode); } // 'master' will be deleted afterwards - MergeScenes (_dest, master, srcList, flags); + MergeScenes(_dest, master, srcList, flags); } // ------------------------------------------------------------------------------------------------ -void SceneCombiner::AttachToGraph (aiNode* attach, std::vector& srcList) { +void SceneCombiner::AttachToGraph(aiNode *attach, std::vector &srcList) { unsigned int cnt; - for ( cnt = 0; cnt < attach->mNumChildren; ++cnt ) { - AttachToGraph( attach->mChildren[ cnt ], srcList ); + for (cnt = 0; cnt < attach->mNumChildren; ++cnt) { + AttachToGraph(attach->mChildren[cnt], srcList); } cnt = 0; for (std::vector::iterator it = srcList.begin(); - it != srcList.end(); ++it) - { + it != srcList.end(); ++it) { if ((*it).attachToNode == attach && !(*it).resolved) ++cnt; } - if (cnt) { - aiNode** n = new aiNode*[cnt+attach->mNumChildren]; - if (attach->mNumChildren) { - ::memcpy(n,attach->mChildren,sizeof(void*)*attach->mNumChildren); + if (cnt) { + aiNode **n = new aiNode *[cnt + attach->mNumChildren]; + if (attach->mNumChildren) { + ::memcpy(n, attach->mChildren, sizeof(void *) * attach->mNumChildren); delete[] attach->mChildren; } attach->mChildren = n; @@ -218,9 +227,9 @@ void SceneCombiner::AttachToGraph (aiNode* attach, std::vectormNumChildren; attach->mNumChildren += cnt; - for (unsigned int i = 0; i < srcList.size();++i) { - NodeAttachmentInfo& att = srcList[i]; - if (att.attachToNode == attach && !att.resolved) { + for (unsigned int i = 0; i < srcList.size(); ++i) { + NodeAttachmentInfo &att = srcList[i]; + if (att.attachToNode == attach && !att.resolved) { *n = att.node; (**n).mParent = attach; ++n; @@ -233,53 +242,54 @@ void SceneCombiner::AttachToGraph (aiNode* attach, std::vector& src) { - ai_assert(NULL != master); - AttachToGraph(master->mRootNode,src); +void SceneCombiner::AttachToGraph(aiScene *master, std::vector &src) { + ai_assert(nullptr != master); + + AttachToGraph(master->mRootNode, src); } // ------------------------------------------------------------------------------------------------ -void SceneCombiner::MergeScenes(aiScene** _dest, aiScene* master, std::vector& srcList, unsigned int flags) { - if ( nullptr == _dest ) { +void SceneCombiner::MergeScenes(aiScene **_dest, aiScene *master, std::vector &srcList, unsigned int flags) { + if (nullptr == _dest) { return; } - // if _dest points to NULL allocate a new scene. Otherwise clear the old and reuse it - if (srcList.empty()) { + // if _dest points to nullptr allocate a new scene. Otherwise clear the old and reuse it + if (srcList.empty()) { if (*_dest) { - SceneCombiner::CopySceneFlat(_dest,master); - } - else *_dest = master; + SceneCombiner::CopySceneFlat(_dest, master); + } else + *_dest = master; return; } if (*_dest) { (*_dest)->~aiScene(); new (*_dest) aiScene(); - } - else *_dest = new aiScene(); + } else + *_dest = new aiScene(); - aiScene* dest = *_dest; + aiScene *dest = *_dest; - std::vector src (srcList.size()+1); + std::vector src(srcList.size() + 1); src[0].scene = master; - for (unsigned int i = 0; i < srcList.size();++i) { - src[i+1] = SceneHelper( srcList[i].scene ); + for (unsigned int i = 0; i < srcList.size(); ++i) { + src[i + 1] = SceneHelper(srcList[i].scene); } // this helper array specifies which scenes are duplicates of others - std::vector duplicates(src.size(),UINT_MAX); + std::vector duplicates(src.size(), UINT_MAX); // this helper array is used as lookup table several times std::vector offset(src.size()); // Find duplicate scenes - for (unsigned int i = 0; i < src.size();++i) { + for (unsigned int i = 0; i < src.size(); ++i) { if (duplicates[i] != i && duplicates[i] != UINT_MAX) { continue; } duplicates[i] = i; - for ( unsigned int a = i+1; a < src.size(); ++a) { + for (unsigned int a = i + 1; a < src.size(); ++a) { if (src[i].scene == src[a].scene) { duplicates[a] = i; } @@ -287,16 +297,14 @@ void SceneCombiner::MergeScenes(aiScene** _dest, aiScene* master, std::vector dist(1u,1 << 24u); boost::variate_generator > rndGen(rng, dist); #endif - for (unsigned int i = 1; i < src.size();++i) - { + for (unsigned int i = 1; i < src.size(); ++i) { //if (i != duplicates[i]) //{ // // duplicate scenes share the same UID @@ -306,7 +314,7 @@ void SceneCombiner::MergeScenes(aiScene** _dest, aiScene* master, std::vectormRootNode,src[i].hashes); + AddNodeHashes(src[i]->mRootNode, src[i].hashes); - for (unsigned int a = 0; a < src[i]->mNumAnimations;++a) { - aiAnimation* anim = src[i]->mAnimations[a]; - src[i].hashes.insert(SuperFastHash(anim->mName.data,static_cast(anim->mName.length))); + for (unsigned int a = 0; a < src[i]->mNumAnimations; ++a) { + aiAnimation *anim = src[i]->mAnimations[a]; + src[i].hashes.insert(SuperFastHash(anim->mName.data, static_cast(anim->mName.length))); } } } @@ -327,18 +335,17 @@ void SceneCombiner::MergeScenes(aiScene** _dest, aiScene* master, std::vectormNumTextures += (*cur)->mNumTextures; - dest->mNumMaterials += (*cur)->mNumMaterials; - dest->mNumMeshes += (*cur)->mNumMeshes; + if (n == duplicates[n] || flags & AI_INT_MERGE_SCENE_DUPLICATES_DEEP_CPY) { + dest->mNumTextures += (*cur)->mNumTextures; + dest->mNumMaterials += (*cur)->mNumMaterials; + dest->mNumMeshes += (*cur)->mNumMeshes; } - dest->mNumLights += (*cur)->mNumLights; - dest->mNumCameras += (*cur)->mNumCameras; + dest->mNumLights += (*cur)->mNumLights; + dest->mNumCameras += (*cur)->mNumCameras; dest->mNumAnimations += (*cur)->mNumAnimations; // Combine the flags of all scenes @@ -350,23 +357,20 @@ void SceneCombiner::MergeScenes(aiScene** _dest, aiScene* master, std::vectormNumTextures) - { - aiTexture** pip = dest->mTextures = new aiTexture*[dest->mNumMaterials]; + if (dest->mNumTextures) { + aiTexture **pip = dest->mTextures = new aiTexture *[dest->mNumMaterials]; cnt = 0; - for ( unsigned int n = 0; n < src.size();++n ) - { - SceneHelper* cur = &src[n]; - for (unsigned int i = 0; i < (*cur)->mNumTextures;++i) - { - if (n != duplicates[n]) - { - if ( flags & AI_INT_MERGE_SCENE_DUPLICATES_DEEP_CPY) - Copy(pip,(*cur)->mTextures[i]); + for (unsigned int n = 0; n < src.size(); ++n) { + SceneHelper *cur = &src[n]; + for (unsigned int i = 0; i < (*cur)->mNumTextures; ++i) { + if (n != duplicates[n]) { + if (flags & AI_INT_MERGE_SCENE_DUPLICATES_DEEP_CPY) + Copy(pip, (*cur)->mTextures[i]); - else continue; - } - else *pip = (*cur)->mTextures[i]; + else + continue; + } else + *pip = (*cur)->mTextures[i]; ++pip; } @@ -376,47 +380,42 @@ void SceneCombiner::MergeScenes(aiScene** _dest, aiScene* master, std::vectormNumMaterials) - { - aiMaterial** pip = dest->mMaterials = new aiMaterial*[dest->mNumMaterials]; + if (dest->mNumMaterials) { + aiMaterial **pip = dest->mMaterials = new aiMaterial *[dest->mNumMaterials]; cnt = 0; - for ( unsigned int n = 0; n < src.size();++n ) { - SceneHelper* cur = &src[n]; - for (unsigned int i = 0; i < (*cur)->mNumMaterials;++i) - { - if (n != duplicates[n]) - { - if ( flags & AI_INT_MERGE_SCENE_DUPLICATES_DEEP_CPY) - Copy(pip,(*cur)->mMaterials[i]); + for (unsigned int n = 0; n < src.size(); ++n) { + SceneHelper *cur = &src[n]; + for (unsigned int i = 0; i < (*cur)->mNumMaterials; ++i) { + if (n != duplicates[n]) { + if (flags & AI_INT_MERGE_SCENE_DUPLICATES_DEEP_CPY) + Copy(pip, (*cur)->mMaterials[i]); - else continue; - } - else *pip = (*cur)->mMaterials[i]; + else + continue; + } else + *pip = (*cur)->mMaterials[i]; - if ((*cur)->mNumTextures != dest->mNumTextures) { + if ((*cur)->mNumTextures != dest->mNumTextures) { // We need to update all texture indices of the mesh. So we need to search for // a material property called '$tex.file' - for (unsigned int a = 0; a < (*pip)->mNumProperties;++a) - { - aiMaterialProperty* prop = (*pip)->mProperties[a]; - if (!strncmp(prop->mKey.data,"$tex.file",9)) - { + for (unsigned int a = 0; a < (*pip)->mNumProperties; ++a) { + aiMaterialProperty *prop = (*pip)->mProperties[a]; + if (!strncmp(prop->mKey.data, "$tex.file", 9)) { // Check whether this texture is an embedded texture. // In this case the property looks like this: *, // where n is the index of the texture. - aiString& s = *((aiString*)prop->mData); - if ('*' == s.data[0]) { + aiString &s = *((aiString *)prop->mData); + if ('*' == s.data[0]) { // Offset the index and write it back .. const unsigned int idx = strtoul10(&s.data[1]) + offset[n]; - ASSIMP_itoa10(&s.data[1],sizeof(s.data)-1,idx); + ASSIMP_itoa10(&s.data[1], sizeof(s.data) - 1, idx); } } // Need to generate new, unique material names? - else if (!::strcmp( prop->mKey.data,"$mat.name" ) && flags & AI_INT_MERGE_SCENE_GEN_UNIQUE_MATNAMES) - { - aiString* pcSrc = (aiString*) prop->mData; + else if (!::strcmp(prop->mKey.data, "$mat.name") && flags & AI_INT_MERGE_SCENE_GEN_UNIQUE_MATNAMES) { + aiString *pcSrc = (aiString *)prop->mData; PrefixString(*pcSrc, (*cur).id, (*cur).idlen); } } @@ -430,25 +429,23 @@ void SceneCombiner::MergeScenes(aiScene** _dest, aiScene* master, std::vectormNumMeshes) - { - aiMesh** pip = dest->mMeshes = new aiMesh*[dest->mNumMeshes]; + if (dest->mNumMeshes) { + aiMesh **pip = dest->mMeshes = new aiMesh *[dest->mNumMeshes]; cnt = 0; - for ( unsigned int n = 0; n < src.size();++n ) - { - SceneHelper* cur = &src[n]; - for (unsigned int i = 0; i < (*cur)->mNumMeshes;++i) - { + for (unsigned int n = 0; n < src.size(); ++n) { + SceneHelper *cur = &src[n]; + for (unsigned int i = 0; i < (*cur)->mNumMeshes; ++i) { if (n != duplicates[n]) { - if ( flags & AI_INT_MERGE_SCENE_DUPLICATES_DEEP_CPY) + if (flags & AI_INT_MERGE_SCENE_DUPLICATES_DEEP_CPY) Copy(pip, (*cur)->mMeshes[i]); - else continue; - } - else *pip = (*cur)->mMeshes[i]; + else + continue; + } else + *pip = (*cur)->mMeshes[i]; // update the material index of the mesh - (*pip)->mMaterialIndex += offset[n]; + (*pip)->mMaterialIndex += offset[n]; ++pip; } @@ -458,7 +455,7 @@ void SceneCombiner::MergeScenes(aiScene** _dest, aiScene* master, std::vector nodes; + std::vector nodes; nodes.reserve(srcList.size()); // ---------------------------------------------------------------------------- @@ -471,180 +468,177 @@ void SceneCombiner::MergeScenes(aiScene** _dest, aiScene* master, std::vectormLights = (dest->mNumLights - ? new aiLight*[dest->mNumLights] : NULL); + aiLight **ppLights = dest->mLights = (dest->mNumLights ? new aiLight *[dest->mNumLights] : nullptr); - aiCamera** ppCameras = dest->mCameras = (dest->mNumCameras - ? new aiCamera*[dest->mNumCameras] : NULL); + aiCamera **ppCameras = dest->mCameras = (dest->mNumCameras ? new aiCamera *[dest->mNumCameras] : nullptr); - aiAnimation** ppAnims = dest->mAnimations = (dest->mNumAnimations - ? new aiAnimation*[dest->mNumAnimations] : NULL); + aiAnimation **ppAnims = dest->mAnimations = (dest->mNumAnimations ? new aiAnimation *[dest->mNumAnimations] : nullptr); - for ( int n = static_cast(src.size()-1); n >= 0 ;--n ) /* !!! important !!! */ + for (int n = static_cast(src.size() - 1); n >= 0; --n) /* !!! important !!! */ { - SceneHelper* cur = &src[n]; - aiNode* node; + SceneHelper *cur = &src[n]; + aiNode *node; // To offset or not to offset, this is the question - if (n != (int)duplicates[n]) - { + if (n != (int)duplicates[n]) { // Get full scene-graph copy - Copy( &node, (*cur)->mRootNode ); - OffsetNodeMeshIndices(node,offset[duplicates[n]]); + Copy(&node, (*cur)->mRootNode); + OffsetNodeMeshIndices(node, offset[duplicates[n]]); if (flags & AI_INT_MERGE_SCENE_DUPLICATES_DEEP_CPY) { // (note:) they are already 'offseted' by offset[duplicates[n]] - OffsetNodeMeshIndices(node,offset[n] - offset[duplicates[n]]); + OffsetNodeMeshIndices(node, offset[n] - offset[duplicates[n]]); } - } - else // if (n == duplicates[n]) + } else // if (n == duplicates[n]) { node = (*cur)->mRootNode; - OffsetNodeMeshIndices(node,offset[n]); + OffsetNodeMeshIndices(node, offset[n]); } if (n) // src[0] is the master node - nodes.push_back(NodeAttachmentInfo( node,srcList[n-1].attachToNode,n )); + nodes.push_back(NodeAttachmentInfo(node, srcList[n - 1].attachToNode, n)); // add name prefixes? if (flags & AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES) { // or the whole scenegraph if (flags & AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES_IF_NECESSARY) { - AddNodePrefixesChecked(node,(*cur).id,(*cur).idlen,src,n); - } - else AddNodePrefixes(node,(*cur).id,(*cur).idlen); + AddNodePrefixesChecked(node, (*cur).id, (*cur).idlen, src, n); + } else + AddNodePrefixes(node, (*cur).id, (*cur).idlen); // meshes - for (unsigned int i = 0; i < (*cur)->mNumMeshes;++i) { - aiMesh* mesh = (*cur)->mMeshes[i]; + for (unsigned int i = 0; i < (*cur)->mNumMeshes; ++i) { + aiMesh *mesh = (*cur)->mMeshes[i]; // rename all bones - for (unsigned int a = 0; a < mesh->mNumBones;++a) { + for (unsigned int a = 0; a < mesh->mNumBones; ++a) { if (flags & AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES_IF_NECESSARY) { - if (!FindNameMatch(mesh->mBones[a]->mName,src,n)) + if (!FindNameMatch(mesh->mBones[a]->mName, src, n)) continue; } - PrefixString(mesh->mBones[a]->mName,(*cur).id,(*cur).idlen); + PrefixString(mesh->mBones[a]->mName, (*cur).id, (*cur).idlen); } } } // -------------------------------------------------------------------- // Copy light sources - for (unsigned int i = 0; i < (*cur)->mNumLights;++i,++ppLights) - { + for (unsigned int i = 0; i < (*cur)->mNumLights; ++i, ++ppLights) { if (n != (int)duplicates[n]) // duplicate scene? { Copy(ppLights, (*cur)->mLights[i]); - } - else *ppLights = (*cur)->mLights[i]; - + } else + *ppLights = (*cur)->mLights[i]; // Add name prefixes? if (flags & AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES) { if (flags & AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES_IF_NECESSARY) { - if (!FindNameMatch((*ppLights)->mName,src,n)) + if (!FindNameMatch((*ppLights)->mName, src, n)) continue; } - PrefixString((*ppLights)->mName,(*cur).id,(*cur).idlen); + PrefixString((*ppLights)->mName, (*cur).id, (*cur).idlen); } } // -------------------------------------------------------------------- // Copy cameras - for (unsigned int i = 0; i < (*cur)->mNumCameras;++i,++ppCameras) { + for (unsigned int i = 0; i < (*cur)->mNumCameras; ++i, ++ppCameras) { if (n != (int)duplicates[n]) // duplicate scene? { Copy(ppCameras, (*cur)->mCameras[i]); - } - else *ppCameras = (*cur)->mCameras[i]; + } else + *ppCameras = (*cur)->mCameras[i]; // Add name prefixes? if (flags & AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES) { if (flags & AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES_IF_NECESSARY) { - if (!FindNameMatch((*ppCameras)->mName,src,n)) + if (!FindNameMatch((*ppCameras)->mName, src, n)) continue; } - PrefixString((*ppCameras)->mName,(*cur).id,(*cur).idlen); + PrefixString((*ppCameras)->mName, (*cur).id, (*cur).idlen); } } // -------------------------------------------------------------------- // Copy animations - for (unsigned int i = 0; i < (*cur)->mNumAnimations;++i,++ppAnims) { + for (unsigned int i = 0; i < (*cur)->mNumAnimations; ++i, ++ppAnims) { if (n != (int)duplicates[n]) // duplicate scene? { Copy(ppAnims, (*cur)->mAnimations[i]); - } - else *ppAnims = (*cur)->mAnimations[i]; + } else + *ppAnims = (*cur)->mAnimations[i]; // Add name prefixes? if (flags & AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES) { if (flags & AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES_IF_NECESSARY) { - if (!FindNameMatch((*ppAnims)->mName,src,n)) + if (!FindNameMatch((*ppAnims)->mName, src, n)) continue; } - PrefixString((*ppAnims)->mName,(*cur).id,(*cur).idlen); + PrefixString((*ppAnims)->mName, (*cur).id, (*cur).idlen); // don't forget to update all node animation channels - for (unsigned int a = 0; a < (*ppAnims)->mNumChannels;++a) { + for (unsigned int a = 0; a < (*ppAnims)->mNumChannels; ++a) { if (flags & AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES_IF_NECESSARY) { - if (!FindNameMatch((*ppAnims)->mChannels[a]->mNodeName,src,n)) + if (!FindNameMatch((*ppAnims)->mChannels[a]->mNodeName, src, n)) continue; } - PrefixString((*ppAnims)->mChannels[a]->mNodeName,(*cur).id,(*cur).idlen); + PrefixString((*ppAnims)->mChannels[a]->mNodeName, (*cur).id, (*cur).idlen); } } } } // Now build the output graph - AttachToGraph ( master, nodes); + AttachToGraph(master, nodes); dest->mRootNode = master->mRootNode; // Check whether we succeeded at building the output graph - for (std::vector ::iterator it = nodes.begin(); - it != nodes.end(); ++it) - { + for (std::vector::iterator it = nodes.begin(); + it != nodes.end(); ++it) { if (!(*it).resolved) { if (flags & AI_INT_MERGE_SCENE_RESOLVE_CROSS_ATTACHMENTS) { // search for this attachment point in all other imported scenes, too. - for ( unsigned int n = 0; n < src.size();++n ) { + for (unsigned int n = 0; n < src.size(); ++n) { if (n != (*it).src_idx) { - AttachToGraph(src[n].scene,nodes); + AttachToGraph(src[n].scene, nodes); if ((*it).resolved) break; } } } if (!(*it).resolved) { - ASSIMP_LOG_ERROR_F( "SceneCombiner: Failed to resolve attachment ", (*it).node->mName.data, - " ", (*it).attachToNode->mName.data ); + ASSIMP_LOG_ERROR_F("SceneCombiner: Failed to resolve attachment ", (*it).node->mName.data, + " ", (*it).attachToNode->mName.data); } } } // now delete all input scenes. Make sure duplicate scenes aren't // deleted more than one time - for ( unsigned int n = 0; n < src.size();++n ) { + for (unsigned int n = 0; n < src.size(); ++n) { if (n != duplicates[n]) // duplicate scene? continue; - aiScene* deleteMe = src[n].scene; + aiScene *deleteMe = src[n].scene; // We need to delete the arrays before the destructor is called - // we are reusing the array members - delete[] deleteMe->mMeshes; deleteMe->mMeshes = NULL; - delete[] deleteMe->mCameras; deleteMe->mCameras = NULL; - delete[] deleteMe->mLights; deleteMe->mLights = NULL; - delete[] deleteMe->mMaterials; deleteMe->mMaterials = NULL; - delete[] deleteMe->mAnimations; deleteMe->mAnimations = NULL; + delete[] deleteMe->mMeshes; + deleteMe->mMeshes = nullptr; + delete[] deleteMe->mCameras; + deleteMe->mCameras = nullptr; + delete[] deleteMe->mLights; + deleteMe->mLights = nullptr; + delete[] deleteMe->mMaterials; + deleteMe->mMaterials = nullptr; + delete[] deleteMe->mAnimations; + deleteMe->mAnimations = nullptr; - deleteMe->mRootNode = NULL; + deleteMe->mRootNode = nullptr; // Now we can safely delete the scene delete deleteMe; @@ -660,34 +654,33 @@ void SceneCombiner::MergeScenes(aiScene** _dest, aiScene* master, std::vector& asBones, - std::vector::const_iterator it, - std::vector::const_iterator end) -{ +void SceneCombiner::BuildUniqueBoneList(std::list &asBones, + std::vector::const_iterator it, + std::vector::const_iterator end) { unsigned int iOffset = 0; - for (; it != end;++it) { - for (unsigned int l = 0; l < (*it)->mNumBones;++l) { - aiBone* p = (*it)->mBones[l]; - uint32_t itml = SuperFastHash(p->mName.data,(unsigned int)p->mName.length); + for (; it != end; ++it) { + for (unsigned int l = 0; l < (*it)->mNumBones; ++l) { + aiBone *p = (*it)->mBones[l]; + uint32_t itml = SuperFastHash(p->mName.data, (unsigned int)p->mName.length); - std::list::iterator it2 = asBones.begin(); + std::list::iterator it2 = asBones.begin(); std::list::iterator end2 = asBones.end(); - for (;it2 != end2;++it2) { - if ((*it2).first == itml) { - (*it2).pSrcBones.push_back(BoneSrcIndex(p,iOffset)); + for (; it2 != end2; ++it2) { + if ((*it2).first == itml) { + (*it2).pSrcBones.push_back(BoneSrcIndex(p, iOffset)); break; } } - if (end2 == it2) { + if (end2 == it2) { // need to begin a new bone entry asBones.push_back(BoneWithHash()); - BoneWithHash& btz = asBones.back(); + BoneWithHash &btz = asBones.back(); // setup members btz.first = itml; btz.second = &p->mName; - btz.pSrcBones.push_back(BoneSrcIndex(p,iOffset)); + btz.pSrcBones.push_back(BoneSrcIndex(p, iOffset)); } } iOffset += (*it)->mNumVertices; @@ -696,10 +689,9 @@ void SceneCombiner::BuildUniqueBoneList(std::list& asBones, // ------------------------------------------------------------------------------------------------ // Merge a list of bones -void SceneCombiner::MergeBones(aiMesh* out,std::vector::const_iterator it, - std::vector::const_iterator end) -{ - if ( nullptr == out || out->mNumBones == 0 ) { +void SceneCombiner::MergeBones(aiMesh *out, std::vector::const_iterator it, + std::vector::const_iterator end) { + if (nullptr == out || out->mNumBones == 0) { return; } @@ -707,21 +699,21 @@ void SceneCombiner::MergeBones(aiMesh* out,std::vector::const_iterator // we work with hashes to make the comparisons MUCH faster, // at least if we have many bones. std::list asBones; - BuildUniqueBoneList( asBones, it, end ); + BuildUniqueBoneList(asBones, it, end); // now create the output bones out->mNumBones = 0; - out->mBones = new aiBone*[asBones.size()]; + out->mBones = new aiBone *[asBones.size()]; - for (std::list::const_iterator boneIt = asBones.begin(),boneEnd = asBones.end(); boneIt != boneEnd; ++boneIt ) { + for (std::list::const_iterator boneIt = asBones.begin(), boneEnd = asBones.end(); boneIt != boneEnd; ++boneIt) { // Allocate a bone and setup it's name - aiBone* pc = out->mBones[out->mNumBones++] = new aiBone(); - pc->mName = aiString( *( boneIt->second )); + aiBone *pc = out->mBones[out->mNumBones++] = new aiBone(); + pc->mName = aiString(*(boneIt->second)); - std::vector< BoneSrcIndex >::const_iterator wend = boneIt->pSrcBones.end(); + std::vector::const_iterator wend = boneIt->pSrcBones.end(); // Loop through all bones to be joined for this bone - for (std::vector< BoneSrcIndex >::const_iterator wmit = boneIt->pSrcBones.begin(); wmit != wend; ++wmit) { + for (std::vector::const_iterator wmit = boneIt->pSrcBones.begin(); wmit != wend; ++wmit) { pc->mNumWeights += (*wmit).first->mNumWeights; // NOTE: different offset matrices for bones with equal names @@ -734,18 +726,18 @@ void SceneCombiner::MergeBones(aiMesh* out,std::vector::const_iterator } // Allocate the vertex weight array - aiVertexWeight* avw = pc->mWeights = new aiVertexWeight[pc->mNumWeights]; + aiVertexWeight *avw = pc->mWeights = new aiVertexWeight[pc->mNumWeights]; // And copy the final weights - adjust the vertex IDs by the // face index offset of the corresponding mesh. - for (std::vector< BoneSrcIndex >::const_iterator wmit = (*boneIt).pSrcBones.begin(); wmit != (*boneIt).pSrcBones.end(); ++wmit) { + for (std::vector::const_iterator wmit = (*boneIt).pSrcBones.begin(); wmit != (*boneIt).pSrcBones.end(); ++wmit) { if (wmit == wend) { break; } - aiBone* pip = (*wmit).first; - for (unsigned int mp = 0; mp < pip->mNumWeights;++mp,++avw) { - const aiVertexWeight& vfi = pip->mWeights[mp]; + aiBone *pip = (*wmit).first; + for (unsigned int mp = 0; mp < pip->mNumWeights; ++mp, ++avw) { + const aiVertexWeight &vfi = pip->mWeights[mp]; avw->mWeight = vfi.mWeight; avw->mVertexId = vfi.mVertexId + (*wmit).second; } @@ -755,52 +747,51 @@ void SceneCombiner::MergeBones(aiMesh* out,std::vector::const_iterator // ------------------------------------------------------------------------------------------------ // Merge a list of meshes -void SceneCombiner::MergeMeshes(aiMesh** _out, unsigned int /*flags*/, - std::vector::const_iterator begin, - std::vector::const_iterator end) -{ - if ( nullptr == _out ) { +void SceneCombiner::MergeMeshes(aiMesh **_out, unsigned int /*flags*/, + std::vector::const_iterator begin, + std::vector::const_iterator end) { + if (nullptr == _out) { return; } - if (begin == end) { - *_out = NULL; // no meshes ... + if (begin == end) { + *_out = nullptr; // no meshes ... return; } // Allocate the output mesh - aiMesh* out = *_out = new aiMesh(); + aiMesh *out = *_out = new aiMesh(); out->mMaterialIndex = (*begin)->mMaterialIndex; std::string name; // Find out how much output storage we'll need - for (std::vector::const_iterator it = begin; it != end; ++it) { - const char *meshName( (*it)->mName.C_Str() ); - name += std::string( meshName ); - if ( it != end - 1 ) { + for (std::vector::const_iterator it = begin; it != end; ++it) { + const char *meshName((*it)->mName.C_Str()); + name += std::string(meshName); + if (it != end - 1) { name += "."; } - out->mNumVertices += (*it)->mNumVertices; - out->mNumFaces += (*it)->mNumFaces; - out->mNumBones += (*it)->mNumBones; + out->mNumVertices += (*it)->mNumVertices; + out->mNumFaces += (*it)->mNumFaces; + out->mNumBones += (*it)->mNumBones; // combine primitive type flags out->mPrimitiveTypes |= (*it)->mPrimitiveTypes; } - out->mName.Set( name.c_str() ); + out->mName.Set(name.c_str()); if (out->mNumVertices) { - aiVector3D* pv2; + aiVector3D *pv2; // copy vertex positions - if ((**begin).HasPositions()) { + if ((**begin).HasPositions()) { pv2 = out->mVertices = new aiVector3D[out->mNumVertices]; - for (std::vector::const_iterator it = begin; it != end; ++it) { - if ((*it)->mVertices) { - ::memcpy(pv2,(*it)->mVertices,(*it)->mNumVertices*sizeof(aiVector3D)); - } - else ASSIMP_LOG_WARN("JoinMeshes: Positions expected but input mesh contains no positions"); + for (std::vector::const_iterator it = begin; it != end; ++it) { + if ((*it)->mVertices) { + ::memcpy(pv2, (*it)->mVertices, (*it)->mNumVertices * sizeof(aiVector3D)); + } else + ASSIMP_LOG_WARN("JoinMeshes: Positions expected but input mesh contains no positions"); pv2 += (*it)->mNumVertices; } } @@ -808,29 +799,29 @@ void SceneCombiner::MergeMeshes(aiMesh** _out, unsigned int /*flags*/, if ((**begin).HasNormals()) { pv2 = out->mNormals = new aiVector3D[out->mNumVertices]; - for (std::vector::const_iterator it = begin; it != end;++it) { - if ((*it)->mNormals) { - ::memcpy(pv2,(*it)->mNormals,(*it)->mNumVertices*sizeof(aiVector3D)); + for (std::vector::const_iterator it = begin; it != end; ++it) { + if ((*it)->mNormals) { + ::memcpy(pv2, (*it)->mNormals, (*it)->mNumVertices * sizeof(aiVector3D)); } else { - ASSIMP_LOG_WARN( "JoinMeshes: Normals expected but input mesh contains no normals" ); + ASSIMP_LOG_WARN("JoinMeshes: Normals expected but input mesh contains no normals"); } pv2 += (*it)->mNumVertices; } } // copy tangents and bi-tangents - if ((**begin).HasTangentsAndBitangents()) { + if ((**begin).HasTangentsAndBitangents()) { pv2 = out->mTangents = new aiVector3D[out->mNumVertices]; - aiVector3D* pv2b = out->mBitangents = new aiVector3D[out->mNumVertices]; + aiVector3D *pv2b = out->mBitangents = new aiVector3D[out->mNumVertices]; - for (std::vector::const_iterator it = begin; it != end;++it) { - if ((*it)->mTangents) { - ::memcpy(pv2, (*it)->mTangents, (*it)->mNumVertices*sizeof(aiVector3D)); - ::memcpy(pv2b,(*it)->mBitangents,(*it)->mNumVertices*sizeof(aiVector3D)); + for (std::vector::const_iterator it = begin; it != end; ++it) { + if ((*it)->mTangents) { + ::memcpy(pv2, (*it)->mTangents, (*it)->mNumVertices * sizeof(aiVector3D)); + ::memcpy(pv2b, (*it)->mBitangents, (*it)->mNumVertices * sizeof(aiVector3D)); } else { - ASSIMP_LOG_WARN( "JoinMeshes: Tangents expected but input mesh contains no tangents" ); + ASSIMP_LOG_WARN("JoinMeshes: Tangents expected but input mesh contains no tangents"); } - pv2 += (*it)->mNumVertices; + pv2 += (*it)->mNumVertices; pv2b += (*it)->mNumVertices; } } @@ -840,11 +831,11 @@ void SceneCombiner::MergeMeshes(aiMesh** _out, unsigned int /*flags*/, out->mNumUVComponents[n] = (*begin)->mNumUVComponents[n]; pv2 = out->mTextureCoords[n] = new aiVector3D[out->mNumVertices]; - for (std::vector::const_iterator it = begin; it != end;++it) { - if ((*it)->mTextureCoords[n]) { - ::memcpy(pv2,(*it)->mTextureCoords[n],(*it)->mNumVertices*sizeof(aiVector3D)); + for (std::vector::const_iterator it = begin; it != end; ++it) { + if ((*it)->mTextureCoords[n]) { + ::memcpy(pv2, (*it)->mTextureCoords[n], (*it)->mNumVertices * sizeof(aiVector3D)); } else { - ASSIMP_LOG_WARN( "JoinMeshes: UVs expected but input mesh contains no UVs" ); + ASSIMP_LOG_WARN("JoinMeshes: UVs expected but input mesh contains no UVs"); } pv2 += (*it)->mNumVertices; } @@ -852,13 +843,13 @@ void SceneCombiner::MergeMeshes(aiMesh** _out, unsigned int /*flags*/, } // copy vertex colors n = 0; - while ((**begin).HasVertexColors(n)) { + while ((**begin).HasVertexColors(n)) { aiColor4D *pVec2 = out->mColors[n] = new aiColor4D[out->mNumVertices]; - for ( std::vector::const_iterator it = begin; it != end; ++it ) { - if ((*it)->mColors[n]) { - ::memcpy( pVec2, (*it)->mColors[ n ], (*it)->mNumVertices * sizeof( aiColor4D ) ) ; + for (std::vector::const_iterator it = begin; it != end; ++it) { + if ((*it)->mColors[n]) { + ::memcpy(pVec2, (*it)->mColors[n], (*it)->mNumVertices * sizeof(aiColor4D)); } else { - ASSIMP_LOG_WARN( "JoinMeshes: VCs expected but input mesh contains no VCs" ); + ASSIMP_LOG_WARN("JoinMeshes: VCs expected but input mesh contains no VCs"); } pVec2 += (*it)->mNumVertices; } @@ -870,21 +861,22 @@ void SceneCombiner::MergeMeshes(aiMesh** _out, unsigned int /*flags*/, { // copy faces out->mFaces = new aiFace[out->mNumFaces]; - aiFace* pf2 = out->mFaces; + aiFace *pf2 = out->mFaces; unsigned int ofs = 0; - for (std::vector::const_iterator it = begin; it != end;++it) { - for (unsigned int m = 0; m < (*it)->mNumFaces;++m,++pf2) { - aiFace& face = (*it)->mFaces[m]; + for (std::vector::const_iterator it = begin; it != end; ++it) { + for (unsigned int m = 0; m < (*it)->mNumFaces; ++m, ++pf2) { + aiFace &face = (*it)->mFaces[m]; pf2->mNumIndices = face.mNumIndices; pf2->mIndices = face.mIndices; - if (ofs) { + if (ofs) { // add the offset to the vertex - for (unsigned int q = 0; q < face.mNumIndices; ++q) + for (unsigned int q = 0; q < face.mNumIndices; ++q) { face.mIndices[q] += ofs; + } } - face.mIndices = NULL; + face.mIndices = nullptr; } ofs += (*it)->mNumVertices; } @@ -892,33 +884,32 @@ void SceneCombiner::MergeMeshes(aiMesh** _out, unsigned int /*flags*/, // bones - as this is quite lengthy, I moved the code to a separate function if (out->mNumBones) - MergeBones(out,begin,end); + MergeBones(out, begin, end); // delete all source meshes - for (std::vector::const_iterator it = begin; it != end;++it) + for (std::vector::const_iterator it = begin; it != end; ++it) delete *it; } // ------------------------------------------------------------------------------------------------ -void SceneCombiner::MergeMaterials(aiMaterial** dest, - std::vector::const_iterator begin, - std::vector::const_iterator end) -{ - if ( nullptr == dest ) { +void SceneCombiner::MergeMaterials(aiMaterial **dest, + std::vector::const_iterator begin, + std::vector::const_iterator end) { + if (nullptr == dest) { return; } - if (begin == end) { - *dest = NULL; // no materials ... + if (begin == end) { + *dest = nullptr; // no materials ... return; } // Allocate the output material - aiMaterial* out = *dest = new aiMaterial(); + aiMaterial *out = *dest = new aiMaterial(); // Get the maximal number of properties unsigned int size = 0; - for (std::vector::const_iterator it = begin; it != end; ++it) { + for (std::vector::const_iterator it = begin; it != end; ++it) { size += (*it)->mNumProperties; } @@ -927,26 +918,26 @@ void SceneCombiner::MergeMaterials(aiMaterial** dest, out->mNumAllocated = size; out->mNumProperties = 0; - out->mProperties = new aiMaterialProperty*[out->mNumAllocated]; + out->mProperties = new aiMaterialProperty *[out->mNumAllocated]; - for (std::vector::const_iterator it = begin; it != end; ++it) { - for(unsigned int i = 0; i < (*it)->mNumProperties; ++i) { - aiMaterialProperty* sprop = (*it)->mProperties[i]; + for (std::vector::const_iterator it = begin; it != end; ++it) { + for (unsigned int i = 0; i < (*it)->mNumProperties; ++i) { + aiMaterialProperty *sprop = (*it)->mProperties[i]; // Test if we already have a matching property - const aiMaterialProperty* prop_exist; - if(aiGetMaterialProperty(out, sprop->mKey.C_Str(), sprop->mSemantic, sprop->mIndex, &prop_exist) != AI_SUCCESS) { + const aiMaterialProperty *prop_exist; + if (aiGetMaterialProperty(out, sprop->mKey.C_Str(), sprop->mSemantic, sprop->mIndex, &prop_exist) != AI_SUCCESS) { // If not, we add it to the new material - aiMaterialProperty* prop = out->mProperties[out->mNumProperties] = new aiMaterialProperty(); + aiMaterialProperty *prop = out->mProperties[out->mNumProperties] = new aiMaterialProperty(); prop->mDataLength = sprop->mDataLength; prop->mData = new char[prop->mDataLength]; ::memcpy(prop->mData, sprop->mData, prop->mDataLength); - prop->mIndex = sprop->mIndex; + prop->mIndex = sprop->mIndex; prop->mSemantic = sprop->mSemantic; - prop->mKey = sprop->mKey; - prop->mType = sprop->mType; + prop->mKey = sprop->mKey; + prop->mType = sprop->mType; out->mNumProperties++; } @@ -956,34 +947,32 @@ void SceneCombiner::MergeMaterials(aiMaterial** dest, // ------------------------------------------------------------------------------------------------ template -inline -void CopyPtrArray (Type**& dest, const Type* const * src, ai_uint num) { +inline void CopyPtrArray(Type **&dest, const Type *const *src, ai_uint num) { if (!num) { - dest = NULL; + dest = nullptr; return; } - dest = new Type*[num]; - for (ai_uint i = 0; i < num;++i) { - SceneCombiner::Copy(&dest[i],src[i]); + dest = new Type *[num]; + for (ai_uint i = 0; i < num; ++i) { + SceneCombiner::Copy(&dest[i], src[i]); } } // ------------------------------------------------------------------------------------------------ template -inline -void GetArrayCopy(Type*& dest, ai_uint num ) { - if ( !dest ) { +inline void GetArrayCopy(Type *&dest, ai_uint num) { + if (!dest) { return; } - Type* old = dest; + Type *old = dest; dest = new Type[num]; ::memcpy(dest, old, sizeof(Type) * num); } // ------------------------------------------------------------------------------------------------ -void SceneCombiner::CopySceneFlat(aiScene** _dest,const aiScene* src) { - if ( nullptr == _dest || nullptr == src ) { +void SceneCombiner::CopySceneFlat(aiScene **_dest, const aiScene *src) { + if (nullptr == _dest || nullptr == src) { return; } @@ -998,97 +987,99 @@ void SceneCombiner::CopySceneFlat(aiScene** _dest,const aiScene* src) { } // ------------------------------------------------------------------------------------------------ -void SceneCombiner::CopyScene(aiScene** _dest,const aiScene* src,bool allocate) { - if ( nullptr == _dest || nullptr == src ) { +void SceneCombiner::CopyScene(aiScene **_dest, const aiScene *src, bool allocate) { + if (nullptr == _dest || nullptr == src) { return; } if (allocate) { *_dest = new aiScene(); } - aiScene* dest = *_dest; + aiScene *dest = *_dest; ai_assert(nullptr != dest); // copy metadata - if ( nullptr != src->mMetaData ) { - dest->mMetaData = new aiMetadata( *src->mMetaData ); + if (nullptr != src->mMetaData) { + dest->mMetaData = new aiMetadata(*src->mMetaData); } // copy animations dest->mNumAnimations = src->mNumAnimations; - CopyPtrArray(dest->mAnimations,src->mAnimations, - dest->mNumAnimations); + CopyPtrArray(dest->mAnimations, src->mAnimations, + dest->mNumAnimations); // copy textures dest->mNumTextures = src->mNumTextures; - CopyPtrArray(dest->mTextures,src->mTextures, - dest->mNumTextures); + CopyPtrArray(dest->mTextures, src->mTextures, + dest->mNumTextures); // copy materials dest->mNumMaterials = src->mNumMaterials; - CopyPtrArray(dest->mMaterials,src->mMaterials, - dest->mNumMaterials); + CopyPtrArray(dest->mMaterials, src->mMaterials, + dest->mNumMaterials); // copy lights dest->mNumLights = src->mNumLights; - CopyPtrArray(dest->mLights,src->mLights, - dest->mNumLights); + CopyPtrArray(dest->mLights, src->mLights, + dest->mNumLights); // copy cameras dest->mNumCameras = src->mNumCameras; - CopyPtrArray(dest->mCameras,src->mCameras, - dest->mNumCameras); + CopyPtrArray(dest->mCameras, src->mCameras, + dest->mNumCameras); // copy meshes dest->mNumMeshes = src->mNumMeshes; - CopyPtrArray(dest->mMeshes,src->mMeshes, - dest->mNumMeshes); + CopyPtrArray(dest->mMeshes, src->mMeshes, + dest->mNumMeshes); // now - copy the root node of the scene (deep copy, too) - Copy( &dest->mRootNode, src->mRootNode); + Copy(&dest->mRootNode, src->mRootNode); // and keep the flags ... dest->mFlags = src->mFlags; - // source private data might be NULL if the scene is user-allocated (i.e. for use with the export API) - if (dest->mPrivate != NULL) { + // source private data might be nullptr if the scene is user-allocated (i.e. for use with the export API) + if (dest->mPrivate != nullptr) { ScenePriv(dest)->mPPStepsApplied = ScenePriv(src) ? ScenePriv(src)->mPPStepsApplied : 0; } } // ------------------------------------------------------------------------------------------------ -void SceneCombiner::Copy( aiMesh** _dest, const aiMesh* src ) { - if ( nullptr == _dest || nullptr == src ) { +void SceneCombiner::Copy(aiMesh **_dest, const aiMesh *src) { + if (nullptr == _dest || nullptr == src) { return; } - aiMesh* dest = *_dest = new aiMesh(); + aiMesh *dest = *_dest = new aiMesh(); // get a flat copy *dest = *src; // and reallocate all arrays - GetArrayCopy( dest->mVertices, dest->mNumVertices ); - GetArrayCopy( dest->mNormals , dest->mNumVertices ); - GetArrayCopy( dest->mTangents, dest->mNumVertices ); - GetArrayCopy( dest->mBitangents, dest->mNumVertices ); + GetArrayCopy(dest->mVertices, dest->mNumVertices); + GetArrayCopy(dest->mNormals, dest->mNumVertices); + GetArrayCopy(dest->mTangents, dest->mNumVertices); + GetArrayCopy(dest->mBitangents, dest->mNumVertices); unsigned int n = 0; - while (dest->HasTextureCoords(n)) - GetArrayCopy( dest->mTextureCoords[n++], dest->mNumVertices ); + while (dest->HasTextureCoords(n)) { + GetArrayCopy(dest->mTextureCoords[n++], dest->mNumVertices); + } n = 0; - while (dest->HasVertexColors(n)) - GetArrayCopy( dest->mColors[n++], dest->mNumVertices ); + while (dest->HasVertexColors(n)) { + GetArrayCopy(dest->mColors[n++], dest->mNumVertices); + } // make a deep copy of all bones - CopyPtrArray(dest->mBones,dest->mBones,dest->mNumBones); + CopyPtrArray(dest->mBones, dest->mBones, dest->mNumBones); // make a deep copy of all faces - GetArrayCopy(dest->mFaces,dest->mNumFaces); - for (unsigned int i = 0; i < dest->mNumFaces;++i) { - aiFace& f = dest->mFaces[i]; - GetArrayCopy(f.mIndices,f.mNumIndices); + GetArrayCopy(dest->mFaces, dest->mNumFaces); + for (unsigned int i = 0; i < dest->mNumFaces; ++i) { + aiFace &f = dest->mFaces[i]; + GetArrayCopy(f.mIndices, f.mNumIndices); } // make a deep copy of all blend shapes @@ -1096,12 +1087,12 @@ void SceneCombiner::Copy( aiMesh** _dest, const aiMesh* src ) { } // ------------------------------------------------------------------------------------------------ -void SceneCombiner::Copy(aiAnimMesh** _dest, const aiAnimMesh* src) { +void SceneCombiner::Copy(aiAnimMesh **_dest, const aiAnimMesh *src) { if (nullptr == _dest || nullptr == src) { return; } - aiAnimMesh* dest = *_dest = new aiAnimMesh(); + aiAnimMesh *dest = *_dest = new aiAnimMesh(); // get a flat copy *dest = *src; @@ -1122,112 +1113,111 @@ void SceneCombiner::Copy(aiAnimMesh** _dest, const aiAnimMesh* src) { } // ------------------------------------------------------------------------------------------------ -void SceneCombiner::Copy (aiMaterial** _dest, const aiMaterial* src) { - if ( nullptr == _dest || nullptr == src ) { +void SceneCombiner::Copy(aiMaterial **_dest, const aiMaterial *src) { + if (nullptr == _dest || nullptr == src) { return; } - aiMaterial* dest = (aiMaterial*) ( *_dest = new aiMaterial() ); + aiMaterial *dest = (aiMaterial *)(*_dest = new aiMaterial()); dest->Clear(); delete[] dest->mProperties; - dest->mNumAllocated = src->mNumAllocated; - dest->mNumProperties = src->mNumProperties; - dest->mProperties = new aiMaterialProperty* [dest->mNumAllocated]; + dest->mNumAllocated = src->mNumAllocated; + dest->mNumProperties = src->mNumProperties; + dest->mProperties = new aiMaterialProperty *[dest->mNumAllocated]; - for (unsigned int i = 0; i < dest->mNumProperties;++i) - { - aiMaterialProperty* prop = dest->mProperties[i] = new aiMaterialProperty(); - aiMaterialProperty* sprop = src->mProperties[i]; + for (unsigned int i = 0; i < dest->mNumProperties; ++i) { + aiMaterialProperty *prop = dest->mProperties[i] = new aiMaterialProperty(); + aiMaterialProperty *sprop = src->mProperties[i]; prop->mDataLength = sprop->mDataLength; prop->mData = new char[prop->mDataLength]; - ::memcpy(prop->mData,sprop->mData,prop->mDataLength); + ::memcpy(prop->mData, sprop->mData, prop->mDataLength); - prop->mIndex = sprop->mIndex; + prop->mIndex = sprop->mIndex; prop->mSemantic = sprop->mSemantic; - prop->mKey = sprop->mKey; - prop->mType = sprop->mType; + prop->mKey = sprop->mKey; + prop->mType = sprop->mType; } } // ------------------------------------------------------------------------------------------------ -void SceneCombiner::Copy(aiTexture** _dest, const aiTexture* src) { - if ( nullptr == _dest || nullptr == src ) { +void SceneCombiner::Copy(aiTexture **_dest, const aiTexture *src) { + if (nullptr == _dest || nullptr == src) { return; } - aiTexture* dest = *_dest = new aiTexture(); + aiTexture *dest = *_dest = new aiTexture(); // get a flat copy *dest = *src; // and reallocate all arrays. We must do it manually here - const char* old = (const char*)dest->pcData; - if (old) - { + const char *old = (const char *)dest->pcData; + if (old) { unsigned int cpy; - if (!dest->mHeight)cpy = dest->mWidth; - else cpy = dest->mHeight * dest->mWidth * sizeof(aiTexel); + if (!dest->mHeight) + cpy = dest->mWidth; + else + cpy = dest->mHeight * dest->mWidth * sizeof(aiTexel); - if (!cpy) - { - dest->pcData = NULL; + if (!cpy) { + dest->pcData = nullptr; return; } // the cast is legal, the aiTexel c'tor does nothing important - dest->pcData = (aiTexel*) new char[cpy]; + dest->pcData = (aiTexel *)new char[cpy]; ::memcpy(dest->pcData, old, cpy); } } // ------------------------------------------------------------------------------------------------ -void SceneCombiner::Copy( aiAnimation** _dest, const aiAnimation* src ) { - if ( nullptr == _dest || nullptr == src ) { +void SceneCombiner::Copy(aiAnimation **_dest, const aiAnimation *src) { + if (nullptr == _dest || nullptr == src) { return; } - aiAnimation* dest = *_dest = new aiAnimation(); + aiAnimation *dest = *_dest = new aiAnimation(); // get a flat copy *dest = *src; // and reallocate all arrays - CopyPtrArray( dest->mChannels, src->mChannels, dest->mNumChannels ); - CopyPtrArray( dest->mMorphMeshChannels, src->mMorphMeshChannels, dest->mNumMorphMeshChannels ); + CopyPtrArray(dest->mChannels, src->mChannels, dest->mNumChannels); + CopyPtrArray(dest->mMorphMeshChannels, src->mMorphMeshChannels, dest->mNumMorphMeshChannels); } // ------------------------------------------------------------------------------------------------ -void SceneCombiner::Copy(aiNodeAnim** _dest, const aiNodeAnim* src) { - if ( nullptr == _dest || nullptr == src ) { +void SceneCombiner::Copy(aiNodeAnim **_dest, const aiNodeAnim *src) { + if (nullptr == _dest || nullptr == src) { return; } - aiNodeAnim* dest = *_dest = new aiNodeAnim(); + aiNodeAnim *dest = *_dest = new aiNodeAnim(); // get a flat copy *dest = *src; // and reallocate all arrays - GetArrayCopy( dest->mPositionKeys, dest->mNumPositionKeys ); - GetArrayCopy( dest->mScalingKeys, dest->mNumScalingKeys ); - GetArrayCopy( dest->mRotationKeys, dest->mNumRotationKeys ); + GetArrayCopy(dest->mPositionKeys, dest->mNumPositionKeys); + GetArrayCopy(dest->mScalingKeys, dest->mNumScalingKeys); + GetArrayCopy(dest->mRotationKeys, dest->mNumRotationKeys); } -void SceneCombiner::Copy(aiMeshMorphAnim** _dest, const aiMeshMorphAnim* src) { - if ( nullptr == _dest || nullptr == src ) { +void SceneCombiner::Copy(aiMeshMorphAnim **_dest, const aiMeshMorphAnim *src) { + if (nullptr == _dest || nullptr == src) { return; } - aiMeshMorphAnim* dest = *_dest = new aiMeshMorphAnim(); + aiMeshMorphAnim *dest = *_dest = new aiMeshMorphAnim(); // get a flat copy *dest = *src; // and reallocate all arrays - GetArrayCopy( dest->mKeys, dest->mNumKeys ); - for (ai_uint i = 0; i < dest->mNumKeys;++i) { + GetArrayCopy(dest->mKeys, dest->mNumKeys); + for (ai_uint i = 0; i < dest->mNumKeys; ++i) { dest->mKeys[i].mValues = new unsigned int[dest->mKeys[i].mNumValuesAndWeights]; dest->mKeys[i].mWeights = new double[dest->mKeys[i].mNumValuesAndWeights]; ::memcpy(dest->mKeys[i].mValues, src->mKeys[i].mValues, dest->mKeys[i].mNumValuesAndWeights * sizeof(unsigned int)); @@ -1236,47 +1226,47 @@ void SceneCombiner::Copy(aiMeshMorphAnim** _dest, const aiMeshMorphAnim* src) { } // ------------------------------------------------------------------------------------------------ -void SceneCombiner::Copy( aiCamera** _dest,const aiCamera* src) { - if ( nullptr == _dest || nullptr == src ) { +void SceneCombiner::Copy(aiCamera **_dest, const aiCamera *src) { + if (nullptr == _dest || nullptr == src) { return; } - aiCamera* dest = *_dest = new aiCamera(); + aiCamera *dest = *_dest = new aiCamera(); // get a flat copy, that's already OK *dest = *src; } // ------------------------------------------------------------------------------------------------ -void SceneCombiner::Copy(aiLight** _dest, const aiLight* src) { - if ( nullptr == _dest || nullptr == src ) { +void SceneCombiner::Copy(aiLight **_dest, const aiLight *src) { + if (nullptr == _dest || nullptr == src) { return; } - aiLight* dest = *_dest = new aiLight(); + aiLight *dest = *_dest = new aiLight(); // get a flat copy, that's already OK *dest = *src; } // ------------------------------------------------------------------------------------------------ -void SceneCombiner::Copy(aiBone** _dest, const aiBone* src) { - if ( nullptr == _dest || nullptr == src ) { +void SceneCombiner::Copy(aiBone **_dest, const aiBone *src) { + if (nullptr == _dest || nullptr == src) { return; } - aiBone* dest = *_dest = new aiBone(); + aiBone *dest = *_dest = new aiBone(); // get a flat copy *dest = *src; } // ------------------------------------------------------------------------------------------------ -void SceneCombiner::Copy (aiNode** _dest, const aiNode* src) -{ - ai_assert(NULL != _dest && NULL != src); +void SceneCombiner::Copy(aiNode **_dest, const aiNode *src) { + ai_assert(nullptr != _dest); + ai_assert(nullptr != src); - aiNode* dest = *_dest = new aiNode(); + aiNode *dest = *_dest = new aiNode(); // get a flat copy *dest = *src; @@ -1286,60 +1276,63 @@ void SceneCombiner::Copy (aiNode** _dest, const aiNode* src) } // and reallocate all arrays - GetArrayCopy( dest->mMeshes, dest->mNumMeshes ); - CopyPtrArray( dest->mChildren, src->mChildren,dest->mNumChildren); + GetArrayCopy(dest->mMeshes, dest->mNumMeshes); + CopyPtrArray(dest->mChildren, src->mChildren, dest->mNumChildren); - // need to set the mParent fields to the created aiNode. - for( unsigned int i = 0; i < dest->mNumChildren; i ++ ) { - dest->mChildren[i]->mParent = dest; - } + // need to set the mParent fields to the created aiNode. + for (unsigned int i = 0; i < dest->mNumChildren; i++) { + dest->mChildren[i]->mParent = dest; + } } // ------------------------------------------------------------------------------------------------ -void SceneCombiner::Copy(aiMetadata** _dest, const aiMetadata* src) { - if ( nullptr == _dest || nullptr == src ) { +void SceneCombiner::Copy(aiMetadata **_dest, const aiMetadata *src) { + if (nullptr == _dest || nullptr == src) { return; } - if ( 0 == src->mNumProperties ) { + if (0 == src->mNumProperties) { return; } - aiMetadata* dest = *_dest = aiMetadata::Alloc( src->mNumProperties ); + aiMetadata *dest = *_dest = aiMetadata::Alloc(src->mNumProperties); std::copy(src->mKeys, src->mKeys + src->mNumProperties, dest->mKeys); for (unsigned int i = 0; i < src->mNumProperties; ++i) { - aiMetadataEntry& in = src->mValues[i]; - aiMetadataEntry& out = dest->mValues[i]; + aiMetadataEntry &in = src->mValues[i]; + aiMetadataEntry &out = dest->mValues[i]; out.mType = in.mType; switch (dest->mValues[i].mType) { - case AI_BOOL: - out.mData = new bool(*static_cast(in.mData)); - break; - case AI_INT32: - out.mData = new int32_t(*static_cast(in.mData)); - break; - case AI_UINT64: - out.mData = new uint64_t(*static_cast(in.mData)); - break; - case AI_FLOAT: - out.mData = new float(*static_cast(in.mData)); - break; - case AI_DOUBLE: - out.mData = new double(*static_cast(in.mData)); - break; - case AI_AISTRING: - out.mData = new aiString(*static_cast(in.mData)); - break; - case AI_AIVECTOR3D: - out.mData = new aiVector3D(*static_cast(in.mData)); - break; - default: - ai_assert(false); - break; + case AI_BOOL: + out.mData = new bool(*static_cast(in.mData)); + break; + case AI_INT32: + out.mData = new int32_t(*static_cast(in.mData)); + break; + case AI_UINT64: + out.mData = new uint64_t(*static_cast(in.mData)); + break; + case AI_FLOAT: + out.mData = new float(*static_cast(in.mData)); + break; + case AI_DOUBLE: + out.mData = new double(*static_cast(in.mData)); + break; + case AI_AISTRING: + out.mData = new aiString(*static_cast(in.mData)); + break; + case AI_AIVECTOR3D: + out.mData = new aiVector3D(*static_cast(in.mData)); + break; + default: + ai_assert(false); + break; } } } -} // Namespace Assimp +#if (__GNUC__ >= 8 && __GNUC_MINOR__ >= 0) +#pragma GCC diagnostic pop +#endif +} // Namespace Assimp diff --git a/code/Common/ScenePreprocessor.cpp b/code/Common/ScenePreprocessor.cpp index 0cb833302..55aa04ad2 100644 --- a/code/Common/ScenePreprocessor.cpp +++ b/code/Common/ScenePreprocessor.cpp @@ -45,16 +45,14 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include - using namespace Assimp; // --------------------------------------------------------------------------------------------- -void ScenePreprocessor::ProcessScene () -{ - ai_assert(scene != NULL); +void ScenePreprocessor::ProcessScene() { + ai_assert(scene != nullptr); // Process all meshes - for (unsigned int i = 0; i < scene->mNumMeshes;++i) + for (unsigned int i = 0; i < scene->mNumMeshes; ++i) ProcessMesh(scene->mMeshes[i]); // - nothing to do for nodes for the moment @@ -63,27 +61,27 @@ void ScenePreprocessor::ProcessScene () // - nothing to do for cameras for the moment // Process all animations - for (unsigned int i = 0; i < scene->mNumAnimations;++i) + for (unsigned int i = 0; i < scene->mNumAnimations; ++i) ProcessAnimation(scene->mAnimations[i]); // Generate a default material if none was specified if (!scene->mNumMaterials && scene->mNumMeshes) { - scene->mMaterials = new aiMaterial*[2]; - aiMaterial* helper; + scene->mMaterials = new aiMaterial *[2]; + aiMaterial *helper; aiString name; scene->mMaterials[scene->mNumMaterials] = helper = new aiMaterial(); - aiColor3D clr(0.6f,0.6f,0.6f); - helper->AddProperty(&clr,1,AI_MATKEY_COLOR_DIFFUSE); + aiColor3D clr(0.6f, 0.6f, 0.6f); + helper->AddProperty(&clr, 1, AI_MATKEY_COLOR_DIFFUSE); // setup the default name to make this material identifiable name.Set(AI_DEFAULT_MATERIAL_NAME); - helper->AddProperty(&name,AI_MATKEY_NAME); + helper->AddProperty(&name, AI_MATKEY_NAME); - ASSIMP_LOG_DEBUG("ScenePreprocessor: Adding default material \'" AI_DEFAULT_MATERIAL_NAME "\'"); + ASSIMP_LOG_DEBUG("ScenePreprocessor: Adding default material \'" AI_DEFAULT_MATERIAL_NAME "\'"); - for (unsigned int i = 0; i < scene->mNumMeshes;++i) { + for (unsigned int i = 0; i < scene->mNumMeshes; ++i) { scene->mMeshes[i]->mMaterialIndex = scene->mNumMaterials; } @@ -92,17 +90,16 @@ void ScenePreprocessor::ProcessScene () } // --------------------------------------------------------------------------------------------- -void ScenePreprocessor::ProcessMesh (aiMesh* mesh) -{ +void ScenePreprocessor::ProcessMesh(aiMesh *mesh) { // If aiMesh::mNumUVComponents is *not* set assign the default value of 2 - for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i) { + for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i) { if (!mesh->mTextureCoords[i]) { mesh->mNumUVComponents[i] = 0; } else { if (!mesh->mNumUVComponents[i]) mesh->mNumUVComponents[i] = 2; - aiVector3D* p = mesh->mTextureCoords[i], *end = p+mesh->mNumVertices; + aiVector3D *p = mesh->mTextureCoords[i], *end = p + mesh->mNumVertices; // Ensure unused components are zeroed. This will make 1D texture channels work // as if they were 2D channels .. just in case an application doesn't handle @@ -110,12 +107,10 @@ void ScenePreprocessor::ProcessMesh (aiMesh* mesh) if (2 == mesh->mNumUVComponents[i]) { for (; p != end; ++p) p->z = 0.f; - } - else if (1 == mesh->mNumUVComponents[i]) { + } else if (1 == mesh->mNumUVComponents[i]) { for (; p != end; ++p) p->z = p->y = 0.f; - } - else if (3 == mesh->mNumUVComponents[i]) { + } else if (3 == mesh->mNumUVComponents[i]) { // Really 3D coordinates? Check whether the third coordinate is != 0 for at least one element for (; p != end; ++p) { if (p->z != 0) @@ -132,10 +127,9 @@ void ScenePreprocessor::ProcessMesh (aiMesh* mesh) // If the information which primitive types are there in the // mesh is currently not available, compute it. if (!mesh->mPrimitiveTypes) { - for (unsigned int a = 0; a < mesh->mNumFaces; ++a) { - aiFace& face = mesh->mFaces[a]; - switch (face.mNumIndices) - { + for (unsigned int a = 0; a < mesh->mNumFaces; ++a) { + aiFace &face = mesh->mFaces[a]; + switch (face.mNumIndices) { case 3u: mesh->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE; break; @@ -156,21 +150,20 @@ void ScenePreprocessor::ProcessMesh (aiMesh* mesh) } // If tangents and normals are given but no bitangents compute them - if (mesh->mTangents && mesh->mNormals && !mesh->mBitangents) { + if (mesh->mTangents && mesh->mNormals && !mesh->mBitangents) { mesh->mBitangents = new aiVector3D[mesh->mNumVertices]; - for (unsigned int i = 0; i < mesh->mNumVertices;++i) { + for (unsigned int i = 0; i < mesh->mNumVertices; ++i) { mesh->mBitangents[i] = mesh->mNormals[i] ^ mesh->mTangents[i]; } } } // --------------------------------------------------------------------------------------------- -void ScenePreprocessor::ProcessAnimation (aiAnimation* anim) -{ +void ScenePreprocessor::ProcessAnimation(aiAnimation *anim) { double first = 10e10, last = -10e10; - for (unsigned int i = 0; i < anim->mNumChannels;++i) { - aiNodeAnim* channel = anim->mChannels[i]; + for (unsigned int i = 0; i < anim->mNumChannels; ++i) { + aiNodeAnim *channel = anim->mChannels[i]; /* If the exact duration of the animation is not given * compute it now. @@ -178,24 +171,24 @@ void ScenePreprocessor::ProcessAnimation (aiAnimation* anim) if (anim->mDuration == -1.) { // Position keys - for (unsigned int j = 0; j < channel->mNumPositionKeys;++j) { - aiVectorKey& key = channel->mPositionKeys[j]; - first = std::min (first, key.mTime); - last = std::max (last, key.mTime); + for (unsigned int j = 0; j < channel->mNumPositionKeys; ++j) { + aiVectorKey &key = channel->mPositionKeys[j]; + first = std::min(first, key.mTime); + last = std::max(last, key.mTime); } // Scaling keys - for (unsigned int j = 0; j < channel->mNumScalingKeys;++j ) { - aiVectorKey& key = channel->mScalingKeys[j]; - first = std::min (first, key.mTime); - last = std::max (last, key.mTime); + for (unsigned int j = 0; j < channel->mNumScalingKeys; ++j) { + aiVectorKey &key = channel->mScalingKeys[j]; + first = std::min(first, key.mTime); + last = std::max(last, key.mTime); } // Rotation keys - for (unsigned int j = 0; j < channel->mNumRotationKeys;++j ) { - aiQuatKey& key = channel->mRotationKeys[ j ]; - first = std::min (first, key.mTime); - last = std::max (last, key.mTime); + for (unsigned int j = 0; j < channel->mNumRotationKeys; ++j) { + aiQuatKey &key = channel->mRotationKeys[j]; + first = std::min(first, key.mTime); + last = std::max(last, key.mTime); } } @@ -204,25 +197,25 @@ void ScenePreprocessor::ProcessAnimation (aiAnimation* anim) * track from the information we have in the transformation * matrix of the corresponding node. */ - if (!channel->mNumRotationKeys || !channel->mNumPositionKeys || !channel->mNumScalingKeys) { + if (!channel->mNumRotationKeys || !channel->mNumPositionKeys || !channel->mNumScalingKeys) { // Find the node that belongs to this animation - aiNode* node = scene->mRootNode->FindNode(channel->mNodeName); - if (node) // ValidateDS will complain later if 'node' is NULL + aiNode *node = scene->mRootNode->FindNode(channel->mNodeName); + if (node) // ValidateDS will complain later if 'node' is nullptr { // Decompose the transformation matrix of the node aiVector3D scaling, position; aiQuaternion rotation; - node->mTransformation.Decompose(scaling, rotation,position); + node->mTransformation.Decompose(scaling, rotation, position); // No rotation keys? Generate a dummy track if (!channel->mNumRotationKeys) { ai_assert(!channel->mRotationKeys); channel->mNumRotationKeys = 1; channel->mRotationKeys = new aiQuatKey[1]; - aiQuatKey& q = channel->mRotationKeys[0]; + aiQuatKey &q = channel->mRotationKeys[0]; - q.mTime = 0.; + q.mTime = 0.; q.mValue = rotation; ASSIMP_LOG_VERBOSE_DEBUG("ScenePreprocessor: Dummy rotation track has been generated"); @@ -231,13 +224,13 @@ void ScenePreprocessor::ProcessAnimation (aiAnimation* anim) } // No scaling keys? Generate a dummy track - if (!channel->mNumScalingKeys) { + if (!channel->mNumScalingKeys) { ai_assert(!channel->mScalingKeys); channel->mNumScalingKeys = 1; channel->mScalingKeys = new aiVectorKey[1]; - aiVectorKey& q = channel->mScalingKeys[0]; + aiVectorKey &q = channel->mScalingKeys[0]; - q.mTime = 0.; + q.mTime = 0.; q.mValue = scaling; ASSIMP_LOG_VERBOSE_DEBUG("ScenePreprocessor: Dummy scaling track has been generated"); @@ -250,9 +243,9 @@ void ScenePreprocessor::ProcessAnimation (aiAnimation* anim) ai_assert(!channel->mPositionKeys); channel->mNumPositionKeys = 1; channel->mPositionKeys = new aiVectorKey[1]; - aiVectorKey& q = channel->mPositionKeys[0]; + aiVectorKey &q = channel->mPositionKeys[0]; - q.mTime = 0.; + q.mTime = 0.; q.mValue = position; ASSIMP_LOG_VERBOSE_DEBUG("ScenePreprocessor: Dummy position track has been generated"); @@ -263,8 +256,8 @@ void ScenePreprocessor::ProcessAnimation (aiAnimation* anim) } } - if (anim->mDuration == -1.) { + if (anim->mDuration == -1.) { ASSIMP_LOG_VERBOSE_DEBUG("ScenePreprocessor: Setting animation duration"); - anim->mDuration = last - std::min( first, 0. ); + anim->mDuration = last - std::min(first, 0.); } } diff --git a/code/Common/ScenePreprocessor.h b/code/Common/ScenePreprocessor.h index e059d1c95..2ec67f20b 100644 --- a/code/Common/ScenePreprocessor.h +++ b/code/Common/ScenePreprocessor.h @@ -53,7 +53,7 @@ struct aiAnimation; struct aiMesh; class ScenePreprocessorTest; -namespace Assimp { +namespace Assimp { // ---------------------------------------------------------------------------------- /** ScenePreprocessor: Preprocess a scene before any post-processing @@ -63,24 +63,21 @@ namespace Assimp { * importer, such as aiMesh::mPrimitiveTypes. */ // ---------------------------------------------------------------------------------- -class ASSIMP_API ScenePreprocessor -{ +class ASSIMP_API ScenePreprocessor { // Make ourselves a friend of the corresponding test unit. friend class ::ScenePreprocessorTest; -public: +public: // ---------------------------------------------------------------- /** Default c'tpr. Use SetScene() to assign a scene to the object. */ - ScenePreprocessor() - : scene (NULL) - {} + ScenePreprocessor() : + scene(nullptr) {} /** Constructs the object and assigns a specific scene to it */ - ScenePreprocessor(aiScene* _scene) - : scene (_scene) - {} + ScenePreprocessor(aiScene *_scene) : + scene(_scene) {} // ---------------------------------------------------------------- /** Assign a (new) scene to the object. @@ -89,37 +86,33 @@ public: * Call ProcessScene to have the scene preprocessed. * @param sc Scene to be processed. */ - void SetScene (aiScene* sc) { + void SetScene(aiScene *sc) { scene = sc; } // ---------------------------------------------------------------- /** Preprocess the current scene */ - void ProcessScene (); + void ProcessScene(); protected: - // ---------------------------------------------------------------- /** Preprocess an animation in the scene * @param anim Anim to be preprocessed. */ - void ProcessAnimation (aiAnimation* anim); - + void ProcessAnimation(aiAnimation *anim); // ---------------------------------------------------------------- /** Preprocess a mesh in the scene * @param mesh Mesh to be preprocessed. */ - void ProcessMesh (aiMesh* mesh); + void ProcessMesh(aiMesh *mesh); protected: - //! Scene we're currently working on - aiScene* scene; + aiScene *scene; }; - -} // ! end namespace Assimp +} // namespace Assimp #endif // include guard diff --git a/code/Common/SkeletonMeshBuilder.cpp b/code/Common/SkeletonMeshBuilder.cpp index 724359f99..7387744bf 100644 --- a/code/Common/SkeletonMeshBuilder.cpp +++ b/code/Common/SkeletonMeshBuilder.cpp @@ -44,30 +44,31 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * @brief Implementation of a little class to construct a dummy mesh for a skeleton */ -#include #include +#include using namespace Assimp; // ------------------------------------------------------------------------------------------------ // The constructor processes the given scene and adds a mesh there. -SkeletonMeshBuilder::SkeletonMeshBuilder( aiScene* pScene, aiNode* root, bool bKnobsOnly) -{ +SkeletonMeshBuilder::SkeletonMeshBuilder(aiScene *pScene, aiNode *root, bool bKnobsOnly) { // nothing to do if there's mesh data already present at the scene - if( pScene->mNumMeshes > 0 || pScene->mRootNode == NULL) + if (pScene->mNumMeshes > 0 || pScene->mRootNode == nullptr) { return; + } - if (!root) + if (!root) { root = pScene->mRootNode; + } mKnobsOnly = bKnobsOnly; // build some faces around each node - CreateGeometry( root ); + CreateGeometry(root); // create a mesh to hold all the generated faces pScene->mNumMeshes = 1; - pScene->mMeshes = new aiMesh*[1]; + pScene->mMeshes = new aiMesh *[1]; pScene->mMeshes[0] = CreateMesh(); // and install it at the root node root->mNumMeshes = 1; @@ -75,154 +76,146 @@ SkeletonMeshBuilder::SkeletonMeshBuilder( aiScene* pScene, aiNode* root, bool bK root->mMeshes[0] = 0; // create a dummy material for the mesh - if(pScene->mNumMaterials==0){ - pScene->mNumMaterials = 1; - pScene->mMaterials = new aiMaterial*[1]; - pScene->mMaterials[0] = CreateMaterial(); + if (pScene->mNumMaterials == 0) { + pScene->mNumMaterials = 1; + pScene->mMaterials = new aiMaterial *[1]; + pScene->mMaterials[0] = CreateMaterial(); } } // ------------------------------------------------------------------------------------------------ // Recursively builds a simple mesh representation for the given node -void SkeletonMeshBuilder::CreateGeometry( const aiNode* pNode) -{ +void SkeletonMeshBuilder::CreateGeometry(const aiNode *pNode) { // add a joint entry for the node. const unsigned int vertexStartIndex = static_cast(mVertices.size()); // now build the geometry. - if( pNode->mNumChildren > 0 && !mKnobsOnly) - { + if (pNode->mNumChildren > 0 && !mKnobsOnly) { // If the node has children, we build little pointers to each of them - for( unsigned int a = 0; a < pNode->mNumChildren; a++) - { + for (unsigned int a = 0; a < pNode->mNumChildren; a++) { // find a suitable coordinate system - const aiMatrix4x4& childTransform = pNode->mChildren[a]->mTransformation; - aiVector3D childpos( childTransform.a4, childTransform.b4, childTransform.c4); + const aiMatrix4x4 &childTransform = pNode->mChildren[a]->mTransformation; + aiVector3D childpos(childTransform.a4, childTransform.b4, childTransform.c4); ai_real distanceToChild = childpos.Length(); - if( distanceToChild < 0.0001) + if (distanceToChild < 0.0001) continue; - aiVector3D up = aiVector3D( childpos).Normalize(); + aiVector3D up = aiVector3D(childpos).Normalize(); - aiVector3D orth( 1.0, 0.0, 0.0); - if( std::fabs( orth * up) > 0.99) - orth.Set( 0.0, 1.0, 0.0); + aiVector3D orth(1.0, 0.0, 0.0); + if (std::fabs(orth * up) > 0.99) + orth.Set(0.0, 1.0, 0.0); aiVector3D front = (up ^ orth).Normalize(); aiVector3D side = (front ^ up).Normalize(); unsigned int localVertexStart = static_cast(mVertices.size()); - mVertices.push_back( -front * distanceToChild * (ai_real)0.1); - mVertices.push_back( childpos); - mVertices.push_back( -side * distanceToChild * (ai_real)0.1); - mVertices.push_back( -side * distanceToChild * (ai_real)0.1); - mVertices.push_back( childpos); - mVertices.push_back( front * distanceToChild * (ai_real)0.1); - mVertices.push_back( front * distanceToChild * (ai_real)0.1); - mVertices.push_back( childpos); - mVertices.push_back( side * distanceToChild * (ai_real)0.1); - mVertices.push_back( side * distanceToChild * (ai_real)0.1); - mVertices.push_back( childpos); - mVertices.push_back( -front * distanceToChild * (ai_real)0.1); + mVertices.push_back(-front * distanceToChild * (ai_real)0.1); + mVertices.push_back(childpos); + mVertices.push_back(-side * distanceToChild * (ai_real)0.1); + mVertices.push_back(-side * distanceToChild * (ai_real)0.1); + mVertices.push_back(childpos); + mVertices.push_back(front * distanceToChild * (ai_real)0.1); + mVertices.push_back(front * distanceToChild * (ai_real)0.1); + mVertices.push_back(childpos); + mVertices.push_back(side * distanceToChild * (ai_real)0.1); + mVertices.push_back(side * distanceToChild * (ai_real)0.1); + mVertices.push_back(childpos); + mVertices.push_back(-front * distanceToChild * (ai_real)0.1); - mFaces.push_back( Face( localVertexStart + 0, localVertexStart + 1, localVertexStart + 2)); - mFaces.push_back( Face( localVertexStart + 3, localVertexStart + 4, localVertexStart + 5)); - mFaces.push_back( Face( localVertexStart + 6, localVertexStart + 7, localVertexStart + 8)); - mFaces.push_back( Face( localVertexStart + 9, localVertexStart + 10, localVertexStart + 11)); + mFaces.push_back(Face(localVertexStart + 0, localVertexStart + 1, localVertexStart + 2)); + mFaces.push_back(Face(localVertexStart + 3, localVertexStart + 4, localVertexStart + 5)); + mFaces.push_back(Face(localVertexStart + 6, localVertexStart + 7, localVertexStart + 8)); + mFaces.push_back(Face(localVertexStart + 9, localVertexStart + 10, localVertexStart + 11)); } - } - else - { + } else { // if the node has no children, it's an end node. Put a little knob there instead - aiVector3D ownpos( pNode->mTransformation.a4, pNode->mTransformation.b4, pNode->mTransformation.c4); - ai_real sizeEstimate = ownpos.Length() * ai_real( 0.18 ); + aiVector3D ownpos(pNode->mTransformation.a4, pNode->mTransformation.b4, pNode->mTransformation.c4); + ai_real sizeEstimate = ownpos.Length() * ai_real(0.18); - mVertices.push_back( aiVector3D( -sizeEstimate, 0.0, 0.0)); - mVertices.push_back( aiVector3D( 0.0, sizeEstimate, 0.0)); - mVertices.push_back( aiVector3D( 0.0, 0.0, -sizeEstimate)); - mVertices.push_back( aiVector3D( 0.0, sizeEstimate, 0.0)); - mVertices.push_back( aiVector3D( sizeEstimate, 0.0, 0.0)); - mVertices.push_back( aiVector3D( 0.0, 0.0, -sizeEstimate)); - mVertices.push_back( aiVector3D( sizeEstimate, 0.0, 0.0)); - mVertices.push_back( aiVector3D( 0.0, -sizeEstimate, 0.0)); - mVertices.push_back( aiVector3D( 0.0, 0.0, -sizeEstimate)); - mVertices.push_back( aiVector3D( 0.0, -sizeEstimate, 0.0)); - mVertices.push_back( aiVector3D( -sizeEstimate, 0.0, 0.0)); - mVertices.push_back( aiVector3D( 0.0, 0.0, -sizeEstimate)); + mVertices.push_back(aiVector3D(-sizeEstimate, 0.0, 0.0)); + mVertices.push_back(aiVector3D(0.0, sizeEstimate, 0.0)); + mVertices.push_back(aiVector3D(0.0, 0.0, -sizeEstimate)); + mVertices.push_back(aiVector3D(0.0, sizeEstimate, 0.0)); + mVertices.push_back(aiVector3D(sizeEstimate, 0.0, 0.0)); + mVertices.push_back(aiVector3D(0.0, 0.0, -sizeEstimate)); + mVertices.push_back(aiVector3D(sizeEstimate, 0.0, 0.0)); + mVertices.push_back(aiVector3D(0.0, -sizeEstimate, 0.0)); + mVertices.push_back(aiVector3D(0.0, 0.0, -sizeEstimate)); + mVertices.push_back(aiVector3D(0.0, -sizeEstimate, 0.0)); + mVertices.push_back(aiVector3D(-sizeEstimate, 0.0, 0.0)); + mVertices.push_back(aiVector3D(0.0, 0.0, -sizeEstimate)); - mVertices.push_back( aiVector3D( -sizeEstimate, 0.0, 0.0)); - mVertices.push_back( aiVector3D( 0.0, 0.0, sizeEstimate)); - mVertices.push_back( aiVector3D( 0.0, sizeEstimate, 0.0)); - mVertices.push_back( aiVector3D( 0.0, sizeEstimate, 0.0)); - mVertices.push_back( aiVector3D( 0.0, 0.0, sizeEstimate)); - mVertices.push_back( aiVector3D( sizeEstimate, 0.0, 0.0)); - mVertices.push_back( aiVector3D( sizeEstimate, 0.0, 0.0)); - mVertices.push_back( aiVector3D( 0.0, 0.0, sizeEstimate)); - mVertices.push_back( aiVector3D( 0.0, -sizeEstimate, 0.0)); - mVertices.push_back( aiVector3D( 0.0, -sizeEstimate, 0.0)); - mVertices.push_back( aiVector3D( 0.0, 0.0, sizeEstimate)); - mVertices.push_back( aiVector3D( -sizeEstimate, 0.0, 0.0)); + mVertices.push_back(aiVector3D(-sizeEstimate, 0.0, 0.0)); + mVertices.push_back(aiVector3D(0.0, 0.0, sizeEstimate)); + mVertices.push_back(aiVector3D(0.0, sizeEstimate, 0.0)); + mVertices.push_back(aiVector3D(0.0, sizeEstimate, 0.0)); + mVertices.push_back(aiVector3D(0.0, 0.0, sizeEstimate)); + mVertices.push_back(aiVector3D(sizeEstimate, 0.0, 0.0)); + mVertices.push_back(aiVector3D(sizeEstimate, 0.0, 0.0)); + mVertices.push_back(aiVector3D(0.0, 0.0, sizeEstimate)); + mVertices.push_back(aiVector3D(0.0, -sizeEstimate, 0.0)); + mVertices.push_back(aiVector3D(0.0, -sizeEstimate, 0.0)); + mVertices.push_back(aiVector3D(0.0, 0.0, sizeEstimate)); + mVertices.push_back(aiVector3D(-sizeEstimate, 0.0, 0.0)); - mFaces.push_back( Face( vertexStartIndex + 0, vertexStartIndex + 1, vertexStartIndex + 2)); - mFaces.push_back( Face( vertexStartIndex + 3, vertexStartIndex + 4, vertexStartIndex + 5)); - mFaces.push_back( Face( vertexStartIndex + 6, vertexStartIndex + 7, vertexStartIndex + 8)); - mFaces.push_back( Face( vertexStartIndex + 9, vertexStartIndex + 10, vertexStartIndex + 11)); - mFaces.push_back( Face( vertexStartIndex + 12, vertexStartIndex + 13, vertexStartIndex + 14)); - mFaces.push_back( Face( vertexStartIndex + 15, vertexStartIndex + 16, vertexStartIndex + 17)); - mFaces.push_back( Face( vertexStartIndex + 18, vertexStartIndex + 19, vertexStartIndex + 20)); - mFaces.push_back( Face( vertexStartIndex + 21, vertexStartIndex + 22, vertexStartIndex + 23)); + mFaces.push_back(Face(vertexStartIndex + 0, vertexStartIndex + 1, vertexStartIndex + 2)); + mFaces.push_back(Face(vertexStartIndex + 3, vertexStartIndex + 4, vertexStartIndex + 5)); + mFaces.push_back(Face(vertexStartIndex + 6, vertexStartIndex + 7, vertexStartIndex + 8)); + mFaces.push_back(Face(vertexStartIndex + 9, vertexStartIndex + 10, vertexStartIndex + 11)); + mFaces.push_back(Face(vertexStartIndex + 12, vertexStartIndex + 13, vertexStartIndex + 14)); + mFaces.push_back(Face(vertexStartIndex + 15, vertexStartIndex + 16, vertexStartIndex + 17)); + mFaces.push_back(Face(vertexStartIndex + 18, vertexStartIndex + 19, vertexStartIndex + 20)); + mFaces.push_back(Face(vertexStartIndex + 21, vertexStartIndex + 22, vertexStartIndex + 23)); } unsigned int numVertices = static_cast(mVertices.size() - vertexStartIndex); - if( numVertices > 0) - { + if (numVertices > 0) { // create a bone affecting all the newly created vertices - aiBone* bone = new aiBone; - mBones.push_back( bone); + aiBone *bone = new aiBone; + mBones.push_back(bone); bone->mName = pNode->mName; // calculate the bone offset matrix by concatenating the inverse transformations of all parents - bone->mOffsetMatrix = aiMatrix4x4( pNode->mTransformation).Inverse(); - for( aiNode* parent = pNode->mParent; parent != NULL; parent = parent->mParent) - bone->mOffsetMatrix = aiMatrix4x4( parent->mTransformation).Inverse() * bone->mOffsetMatrix; + bone->mOffsetMatrix = aiMatrix4x4(pNode->mTransformation).Inverse(); + for (aiNode *parent = pNode->mParent; parent != nullptr; parent = parent->mParent) + bone->mOffsetMatrix = aiMatrix4x4(parent->mTransformation).Inverse() * bone->mOffsetMatrix; // add all the vertices to the bone's influences bone->mNumWeights = numVertices; bone->mWeights = new aiVertexWeight[numVertices]; - for( unsigned int a = 0; a < numVertices; a++) - bone->mWeights[a] = aiVertexWeight( vertexStartIndex + a, 1.0); + for (unsigned int a = 0; a < numVertices; a++) + bone->mWeights[a] = aiVertexWeight(vertexStartIndex + a, 1.0); // HACK: (thom) transform all vertices to the bone's local space. Should be done before adding // them to the array, but I'm tired now and I'm annoyed. - aiMatrix4x4 boneToMeshTransform = aiMatrix4x4( bone->mOffsetMatrix).Inverse(); - for( unsigned int a = vertexStartIndex; a < mVertices.size(); a++) + aiMatrix4x4 boneToMeshTransform = aiMatrix4x4(bone->mOffsetMatrix).Inverse(); + for (unsigned int a = vertexStartIndex; a < mVertices.size(); a++) mVertices[a] = boneToMeshTransform * mVertices[a]; } // and finally recurse into the children list - for( unsigned int a = 0; a < pNode->mNumChildren; a++) - CreateGeometry( pNode->mChildren[a]); + for (unsigned int a = 0; a < pNode->mNumChildren; a++) + CreateGeometry(pNode->mChildren[a]); } // ------------------------------------------------------------------------------------------------ // Creates the mesh from the internally accumulated stuff and returns it. -aiMesh* SkeletonMeshBuilder::CreateMesh() -{ - aiMesh* mesh = new aiMesh(); +aiMesh *SkeletonMeshBuilder::CreateMesh() { + aiMesh *mesh = new aiMesh(); // add points mesh->mNumVertices = static_cast(mVertices.size()); mesh->mVertices = new aiVector3D[mesh->mNumVertices]; - std::copy( mVertices.begin(), mVertices.end(), mesh->mVertices); + std::copy(mVertices.begin(), mVertices.end(), mesh->mVertices); mesh->mNormals = new aiVector3D[mesh->mNumVertices]; // add faces mesh->mNumFaces = static_cast(mFaces.size()); mesh->mFaces = new aiFace[mesh->mNumFaces]; - for( unsigned int a = 0; a < mesh->mNumFaces; a++) - { - const Face& inface = mFaces[a]; - aiFace& outface = mesh->mFaces[a]; + for (unsigned int a = 0; a < mesh->mNumFaces; a++) { + const Face &inface = mFaces[a]; + aiFace &outface = mesh->mFaces[a]; outface.mNumIndices = 3; outface.mIndices = new unsigned int[3]; outface.mIndices[0] = inface.mIndices[0]; @@ -232,10 +225,10 @@ aiMesh* SkeletonMeshBuilder::CreateMesh() // Compute per-face normals ... we don't want the bones to be smoothed ... they're built to visualize // the skeleton, so it's good if there's a visual difference to the rest of the geometry aiVector3D nor = ((mVertices[inface.mIndices[2]] - mVertices[inface.mIndices[0]]) ^ - (mVertices[inface.mIndices[1]] - mVertices[inface.mIndices[0]])); + (mVertices[inface.mIndices[1]] - mVertices[inface.mIndices[0]])); if (nor.Length() < 1e-5) /* ensure that FindInvalidData won't remove us ...*/ - nor = aiVector3D(1.0,0.0,0.0); + nor = aiVector3D(1.0, 0.0, 0.0); for (unsigned int n = 0; n < 3; ++n) mesh->mNormals[inface.mIndices[n]] = nor; @@ -243,8 +236,8 @@ aiMesh* SkeletonMeshBuilder::CreateMesh() // add the bones mesh->mNumBones = static_cast(mBones.size()); - mesh->mBones = new aiBone*[mesh->mNumBones]; - std::copy( mBones.begin(), mBones.end(), mesh->mBones); + mesh->mBones = new aiBone *[mesh->mNumBones]; + std::copy(mBones.begin(), mBones.end(), mesh->mBones); // default mesh->mMaterialIndex = 0; @@ -254,17 +247,16 @@ aiMesh* SkeletonMeshBuilder::CreateMesh() // ------------------------------------------------------------------------------------------------ // Creates a dummy material and returns it. -aiMaterial* SkeletonMeshBuilder::CreateMaterial() -{ - aiMaterial* matHelper = new aiMaterial; +aiMaterial *SkeletonMeshBuilder::CreateMaterial() { + aiMaterial *matHelper = new aiMaterial; // Name - aiString matName( std::string( "SkeletonMaterial")); - matHelper->AddProperty( &matName, AI_MATKEY_NAME); + aiString matName(std::string("SkeletonMaterial")); + matHelper->AddProperty(&matName, AI_MATKEY_NAME); // Prevent backface culling const int no_cull = 1; - matHelper->AddProperty(&no_cull,1,AI_MATKEY_TWOSIDED); + matHelper->AddProperty(&no_cull, 1, AI_MATKEY_TWOSIDED); return matHelper; } diff --git a/code/Common/SpatialSort.cpp b/code/Common/SpatialSort.cpp index 2bf6ce2e2..86e22b242 100644 --- a/code/Common/SpatialSort.cpp +++ b/code/Common/SpatialSort.cpp @@ -210,20 +210,16 @@ BinFloat ToBinary(const ai_real &pValue) { // See http://en.wikipedia.org/wiki/Signed_number_representations. // Two's complement? - bool DefaultValue = ((-42 == (~42 + 1)) && (binValue & 0x80000000)); - bool OneComplement = ((-42 == ~42) && (binValue & 0x80000000)); - bool SignedMagnitude = ((-42 == (42 | (-0))) && (binValue & 0x80000000)); + const bool DefaultValue = ((-42 == (~42 + 1)) && (binValue & 0x80000000)); + const bool OneComplement = ((-42 == ~42) && (binValue & 0x80000000)); if (DefaultValue) return BinFloat(1 << (CHAR_BIT * sizeof(BinFloat) - 1)) - binValue; // One's complement? else if (OneComplement) return BinFloat(-0) - binValue; - // Sign-magnitude? - else if (SignedMagnitude) // -0 = 1000... binary - return binValue; - else - return binValue; + // Sign-magnitude? -0 = 1000... binary + return binValue; } } // namespace diff --git a/code/Common/StandardShapes.cpp b/code/Common/StandardShapes.cpp index d474c6129..b30fa2e25 100644 --- a/code/Common/StandardShapes.cpp +++ b/code/Common/StandardShapes.cpp @@ -4,7 +4,6 @@ Open Asset Import Library (assimp) Copyright (c) 2006-2020, assimp team - All rights reserved. Redistribution and use of this software in source and binary forms, @@ -48,70 +47,61 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include -#include -#include #include +#include #include -namespace Assimp { +namespace Assimp { - -# define ADD_TRIANGLE(n0,n1,n2) \ - positions.push_back(n0); \ - positions.push_back(n1); \ +#define ADD_TRIANGLE(n0, n1, n2) \ + positions.push_back(n0); \ + positions.push_back(n1); \ positions.push_back(n2); -# define ADD_PENTAGON(n0,n1,n2,n3,n4) \ - if (polygons) \ - { \ +#define ADD_PENTAGON(n0, n1, n2, n3, n4) \ + if (polygons) { \ + positions.push_back(n0); \ + positions.push_back(n1); \ + positions.push_back(n2); \ + positions.push_back(n3); \ + positions.push_back(n4); \ + } else { \ + ADD_TRIANGLE(n0, n1, n2) \ + ADD_TRIANGLE(n0, n2, n3) \ + ADD_TRIANGLE(n0, n3, n4) \ + } + +#define ADD_QUAD(n0, n1, n2, n3) \ + if (polygons) { \ positions.push_back(n0); \ positions.push_back(n1); \ positions.push_back(n2); \ positions.push_back(n3); \ - positions.push_back(n4); \ - } \ - else \ - { \ - ADD_TRIANGLE(n0, n1, n2) \ - ADD_TRIANGLE(n0, n2, n3) \ - ADD_TRIANGLE(n0, n3, n4) \ - } - -# define ADD_QUAD(n0,n1,n2,n3) \ - if (polygons) \ - { \ - positions.push_back(n0); \ - positions.push_back(n1); \ - positions.push_back(n2); \ - positions.push_back(n3); \ - } \ - else \ - { \ + } else { \ ADD_TRIANGLE(n0, n1, n2) \ ADD_TRIANGLE(n0, n2, n3) \ } - // ------------------------------------------------------------------------------------------------ // Fast subdivision for a mesh whose verts have a magnitude of 1 -void Subdivide(std::vector& positions) -{ +void Subdivide(std::vector &positions) { // assume this to be constant - (fixme: must be 1.0? I think so) const ai_real fl1 = positions[0].Length(); unsigned int origSize = (unsigned int)positions.size(); - for (unsigned int i = 0 ; i < origSize ; i+=3) - { - aiVector3D& tv0 = positions[i]; - aiVector3D& tv1 = positions[i+1]; - aiVector3D& tv2 = positions[i+2]; + for (unsigned int i = 0; i < origSize; i += 3) { + aiVector3D &tv0 = positions[i]; + aiVector3D &tv1 = positions[i + 1]; + aiVector3D &tv2 = positions[i + 2]; aiVector3D a = tv0, b = tv1, c = tv2; - aiVector3D v1 = aiVector3D(a.x+b.x, a.y+b.y, a.z+b.z).Normalize()*fl1; - aiVector3D v2 = aiVector3D(a.x+c.x, a.y+c.y, a.z+c.z).Normalize()*fl1; - aiVector3D v3 = aiVector3D(b.x+c.x, b.y+c.y, b.z+c.z).Normalize()*fl1; + aiVector3D v1 = aiVector3D(a.x + b.x, a.y + b.y, a.z + b.z).Normalize() * fl1; + aiVector3D v2 = aiVector3D(a.x + c.x, a.y + c.y, a.z + c.z).Normalize() * fl1; + aiVector3D v3 = aiVector3D(b.x + c.x, b.y + c.y, b.z + c.z).Normalize() * fl1; - tv0 = v1; tv1 = v3; tv2 = v2; // overwrite the original + tv0 = v1; + tv1 = v3; + tv2 = v2; // overwrite the original ADD_TRIANGLE(v1, v2, a); ADD_TRIANGLE(v2, v3, c); ADD_TRIANGLE(v3, v1, b); @@ -120,32 +110,33 @@ void Subdivide(std::vector& positions) // ------------------------------------------------------------------------------------------------ // Construct a mesh from given vertex positions -aiMesh* StandardShapes::MakeMesh(const std::vector& positions, - unsigned int numIndices) -{ - if (positions.empty() || !numIndices) return NULL; +aiMesh *StandardShapes::MakeMesh(const std::vector &positions, + unsigned int numIndices) { + if (positions.empty() || !numIndices) { + return nullptr; + } // Determine which kinds of primitives the mesh consists of - aiMesh* out = new aiMesh(); + aiMesh *out = new aiMesh(); switch (numIndices) { - case 1: - out->mPrimitiveTypes = aiPrimitiveType_POINT; - break; - case 2: - out->mPrimitiveTypes = aiPrimitiveType_LINE; - break; - case 3: - out->mPrimitiveTypes = aiPrimitiveType_TRIANGLE; - break; - default: - out->mPrimitiveTypes = aiPrimitiveType_POLYGON; - break; + case 1: + out->mPrimitiveTypes = aiPrimitiveType_POINT; + break; + case 2: + out->mPrimitiveTypes = aiPrimitiveType_LINE; + break; + case 3: + out->mPrimitiveTypes = aiPrimitiveType_TRIANGLE; + break; + default: + out->mPrimitiveTypes = aiPrimitiveType_POLYGON; + break; }; out->mNumFaces = (unsigned int)positions.size() / numIndices; out->mFaces = new aiFace[out->mNumFaces]; - for (unsigned int i = 0, a = 0; i < out->mNumFaces;++i) { - aiFace& f = out->mFaces[i]; + for (unsigned int i = 0, a = 0; i < out->mNumFaces; ++i) { + aiFace &f = out->mFaces[i]; f.mNumIndices = numIndices; f.mIndices = new unsigned int[numIndices]; for (unsigned int j = 0; i < numIndices; ++i, ++a) { @@ -154,113 +145,108 @@ aiMesh* StandardShapes::MakeMesh(const std::vector& positions, } out->mNumVertices = (unsigned int)positions.size(); out->mVertices = new aiVector3D[out->mNumVertices]; - ::memcpy(out->mVertices,&positions[0],out->mNumVertices*sizeof(aiVector3D)); + ::memcpy(out->mVertices, &positions[0], out->mNumVertices * sizeof(aiVector3D)); return out; } // ------------------------------------------------------------------------------------------------ // Construct a mesh with a specific shape (callback) -aiMesh* StandardShapes::MakeMesh ( unsigned int (*GenerateFunc)( - std::vector&)) -{ +aiMesh *StandardShapes::MakeMesh(unsigned int (*GenerateFunc)( + std::vector &)) { std::vector temp; unsigned num = (*GenerateFunc)(temp); - return MakeMesh(temp,num); + return MakeMesh(temp, num); } // ------------------------------------------------------------------------------------------------ // Construct a mesh with a specific shape (callback) -aiMesh* StandardShapes::MakeMesh ( unsigned int (*GenerateFunc)( - std::vector&, bool)) -{ +aiMesh *StandardShapes::MakeMesh(unsigned int (*GenerateFunc)( + std::vector &, bool)) { std::vector temp; - unsigned num = (*GenerateFunc)(temp,true); - return MakeMesh(temp,num); + unsigned num = (*GenerateFunc)(temp, true); + return MakeMesh(temp, num); } // ------------------------------------------------------------------------------------------------ // Construct a mesh with a specific shape (callback) -aiMesh* StandardShapes::MakeMesh (unsigned int num, void (*GenerateFunc)( - unsigned int,std::vector&)) -{ +aiMesh *StandardShapes::MakeMesh(unsigned int num, void (*GenerateFunc)( + unsigned int, std::vector &)) { std::vector temp; - (*GenerateFunc)(num,temp); - return MakeMesh(temp,3); + (*GenerateFunc)(num, temp); + return MakeMesh(temp, 3); } // ------------------------------------------------------------------------------------------------ // Build an incosahedron with points.magnitude == 1 -unsigned int StandardShapes::MakeIcosahedron(std::vector& positions) -{ - positions.reserve(positions.size()+60); +unsigned int StandardShapes::MakeIcosahedron(std::vector &positions) { + positions.reserve(positions.size() + 60); - const ai_real t = ( ai_real( 1.0 )+ ai_real( 2.236067977 ) ) / ai_real( 2.0 ); - const ai_real s = std::sqrt(ai_real(1.0) + t*t); + const ai_real t = (ai_real(1.0) + ai_real(2.236067977)) / ai_real(2.0); + const ai_real s = std::sqrt(ai_real(1.0) + t * t); - const aiVector3D v0 = aiVector3D(t,1.0, 0.0)/s; - const aiVector3D v1 = aiVector3D(-t,1.0, 0.0)/s; - const aiVector3D v2 = aiVector3D(t,-1.0, 0.0)/s; - const aiVector3D v3 = aiVector3D(-t,-1.0, 0.0)/s; - const aiVector3D v4 = aiVector3D(1.0, 0.0, t)/s; - const aiVector3D v5 = aiVector3D(1.0, 0.0,-t)/s; - const aiVector3D v6 = aiVector3D(-1.0, 0.0,t)/s; - const aiVector3D v7 = aiVector3D(-1.0, 0.0,-t)/s; - const aiVector3D v8 = aiVector3D(0.0, t, 1.0)/s; - const aiVector3D v9 = aiVector3D(0.0,-t, 1.0)/s; - const aiVector3D v10 = aiVector3D(0.0, t,-1.0)/s; - const aiVector3D v11 = aiVector3D(0.0,-t,-1.0)/s; + const aiVector3D v0 = aiVector3D(t, 1.0, 0.0) / s; + const aiVector3D v1 = aiVector3D(-t, 1.0, 0.0) / s; + const aiVector3D v2 = aiVector3D(t, -1.0, 0.0) / s; + const aiVector3D v3 = aiVector3D(-t, -1.0, 0.0) / s; + const aiVector3D v4 = aiVector3D(1.0, 0.0, t) / s; + const aiVector3D v5 = aiVector3D(1.0, 0.0, -t) / s; + const aiVector3D v6 = aiVector3D(-1.0, 0.0, t) / s; + const aiVector3D v7 = aiVector3D(-1.0, 0.0, -t) / s; + const aiVector3D v8 = aiVector3D(0.0, t, 1.0) / s; + const aiVector3D v9 = aiVector3D(0.0, -t, 1.0) / s; + const aiVector3D v10 = aiVector3D(0.0, t, -1.0) / s; + const aiVector3D v11 = aiVector3D(0.0, -t, -1.0) / s; - ADD_TRIANGLE(v0,v8,v4); - ADD_TRIANGLE(v0,v5,v10); - ADD_TRIANGLE(v2,v4,v9); - ADD_TRIANGLE(v2,v11,v5); + ADD_TRIANGLE(v0, v8, v4); + ADD_TRIANGLE(v0, v5, v10); + ADD_TRIANGLE(v2, v4, v9); + ADD_TRIANGLE(v2, v11, v5); - ADD_TRIANGLE(v1,v6,v8); - ADD_TRIANGLE(v1,v10,v7); - ADD_TRIANGLE(v3,v9,v6); - ADD_TRIANGLE(v3,v7,v11); + ADD_TRIANGLE(v1, v6, v8); + ADD_TRIANGLE(v1, v10, v7); + ADD_TRIANGLE(v3, v9, v6); + ADD_TRIANGLE(v3, v7, v11); - ADD_TRIANGLE(v0,v10,v8); - ADD_TRIANGLE(v1,v8,v10); - ADD_TRIANGLE(v2,v9,v11); - ADD_TRIANGLE(v3,v11,v9); + ADD_TRIANGLE(v0, v10, v8); + ADD_TRIANGLE(v1, v8, v10); + ADD_TRIANGLE(v2, v9, v11); + ADD_TRIANGLE(v3, v11, v9); - ADD_TRIANGLE(v4,v2,v0); - ADD_TRIANGLE(v5,v0,v2); - ADD_TRIANGLE(v6,v1,v3); - ADD_TRIANGLE(v7,v3,v1); + ADD_TRIANGLE(v4, v2, v0); + ADD_TRIANGLE(v5, v0, v2); + ADD_TRIANGLE(v6, v1, v3); + ADD_TRIANGLE(v7, v3, v1); - ADD_TRIANGLE(v8,v6,v4); - ADD_TRIANGLE(v9,v4,v6); - ADD_TRIANGLE(v10,v5,v7); - ADD_TRIANGLE(v11,v7,v5); + ADD_TRIANGLE(v8, v6, v4); + ADD_TRIANGLE(v9, v4, v6); + ADD_TRIANGLE(v10, v5, v7); + ADD_TRIANGLE(v11, v7, v5); return 3; } // ------------------------------------------------------------------------------------------------ // Build a dodecahedron with points.magnitude == 1 -unsigned int StandardShapes::MakeDodecahedron(std::vector& positions, - bool polygons /*= false*/) -{ - positions.reserve(positions.size()+108); +unsigned int StandardShapes::MakeDodecahedron(std::vector &positions, + bool polygons /*= false*/) { + positions.reserve(positions.size() + 108); - const ai_real a = ai_real( 1.0 ) / ai_real(1.7320508); - const ai_real b = std::sqrt(( ai_real( 3.0 )- ai_real( 2.23606797))/ ai_real( 6.0) ); - const ai_real c = std::sqrt(( ai_real( 3.0 )+ ai_real( 2.23606797f))/ ai_real( 6.0) ); + const ai_real a = ai_real(1.0) / ai_real(1.7320508); + const ai_real b = std::sqrt((ai_real(3.0) - ai_real(2.23606797)) / ai_real(6.0)); + const ai_real c = std::sqrt((ai_real(3.0) + ai_real(2.23606797f)) / ai_real(6.0)); - const aiVector3D v0 = aiVector3D(a,a,a); - const aiVector3D v1 = aiVector3D(a,a,-a); - const aiVector3D v2 = aiVector3D(a,-a,a); - const aiVector3D v3 = aiVector3D(a,-a,-a); - const aiVector3D v4 = aiVector3D(-a,a,a); - const aiVector3D v5 = aiVector3D(-a,a,-a); - const aiVector3D v6 = aiVector3D(-a,-a,a); - const aiVector3D v7 = aiVector3D(-a,-a,-a); - const aiVector3D v8 = aiVector3D(b,c,0.0); - const aiVector3D v9 = aiVector3D(-b,c,0.0); - const aiVector3D v10 = aiVector3D(b,-c,0.0); - const aiVector3D v11 = aiVector3D(-b,-c,0.0); + const aiVector3D v0 = aiVector3D(a, a, a); + const aiVector3D v1 = aiVector3D(a, a, -a); + const aiVector3D v2 = aiVector3D(a, -a, a); + const aiVector3D v3 = aiVector3D(a, -a, -a); + const aiVector3D v4 = aiVector3D(-a, a, a); + const aiVector3D v5 = aiVector3D(-a, a, -a); + const aiVector3D v6 = aiVector3D(-a, -a, a); + const aiVector3D v7 = aiVector3D(-a, -a, -a); + const aiVector3D v8 = aiVector3D(b, c, 0.0); + const aiVector3D v9 = aiVector3D(-b, c, 0.0); + const aiVector3D v10 = aiVector3D(b, -c, 0.0); + const aiVector3D v11 = aiVector3D(-b, -c, 0.0); const aiVector3D v12 = aiVector3D(c, 0.0, b); const aiVector3D v13 = aiVector3D(c, 0.0, -b); const aiVector3D v14 = aiVector3D(-c, 0.0, b); @@ -288,74 +274,71 @@ unsigned int StandardShapes::MakeDodecahedron(std::vector& positions // ------------------------------------------------------------------------------------------------ // Build an octahedron with points.magnitude == 1 -unsigned int StandardShapes::MakeOctahedron(std::vector& positions) -{ - positions.reserve(positions.size()+24); +unsigned int StandardShapes::MakeOctahedron(std::vector &positions) { + positions.reserve(positions.size() + 24); - const aiVector3D v0 = aiVector3D(1.0, 0.0, 0.0) ; - const aiVector3D v1 = aiVector3D(-1.0, 0.0, 0.0); - const aiVector3D v2 = aiVector3D(0.0, 1.0, 0.0); - const aiVector3D v3 = aiVector3D(0.0, -1.0, 0.0); - const aiVector3D v4 = aiVector3D(0.0, 0.0, 1.0); - const aiVector3D v5 = aiVector3D(0.0, 0.0, -1.0); + const aiVector3D v0 = aiVector3D(1.0, 0.0, 0.0); + const aiVector3D v1 = aiVector3D(-1.0, 0.0, 0.0); + const aiVector3D v2 = aiVector3D(0.0, 1.0, 0.0); + const aiVector3D v3 = aiVector3D(0.0, -1.0, 0.0); + const aiVector3D v4 = aiVector3D(0.0, 0.0, 1.0); + const aiVector3D v5 = aiVector3D(0.0, 0.0, -1.0); - ADD_TRIANGLE(v4,v0,v2); - ADD_TRIANGLE(v4,v2,v1); - ADD_TRIANGLE(v4,v1,v3); - ADD_TRIANGLE(v4,v3,v0); + ADD_TRIANGLE(v4, v0, v2); + ADD_TRIANGLE(v4, v2, v1); + ADD_TRIANGLE(v4, v1, v3); + ADD_TRIANGLE(v4, v3, v0); - ADD_TRIANGLE(v5,v2,v0); - ADD_TRIANGLE(v5,v1,v2); - ADD_TRIANGLE(v5,v3,v1); - ADD_TRIANGLE(v5,v0,v3); + ADD_TRIANGLE(v5, v2, v0); + ADD_TRIANGLE(v5, v1, v2); + ADD_TRIANGLE(v5, v3, v1); + ADD_TRIANGLE(v5, v0, v3); return 3; } // ------------------------------------------------------------------------------------------------ // Build a tetrahedron with points.magnitude == 1 -unsigned int StandardShapes::MakeTetrahedron(std::vector& positions) -{ - positions.reserve(positions.size()+9); +unsigned int StandardShapes::MakeTetrahedron(std::vector &positions) { + positions.reserve(positions.size() + 9); - const ai_real invThree = ai_real( 1.0 ) / ai_real( 3.0 ); - const ai_real a = ai_real( 1.41421 ) * invThree; - const ai_real b = ai_real( 2.4494 ) * invThree; + const ai_real invThree = ai_real(1.0) / ai_real(3.0); + const ai_real a = ai_real(1.41421) * invThree; + const ai_real b = ai_real(2.4494) * invThree; - const aiVector3D v0 = aiVector3D(0.0,0.0,1.0); - const aiVector3D v1 = aiVector3D(2*a,0,-invThree ); - const aiVector3D v2 = aiVector3D(-a,b,-invThree ); - const aiVector3D v3 = aiVector3D(-a,-b,-invThree ); + const aiVector3D v0 = aiVector3D(0.0, 0.0, 1.0); + const aiVector3D v1 = aiVector3D(2 * a, 0, -invThree); + const aiVector3D v2 = aiVector3D(-a, b, -invThree); + const aiVector3D v3 = aiVector3D(-a, -b, -invThree); - ADD_TRIANGLE(v0,v1,v2); - ADD_TRIANGLE(v0,v2,v3); - ADD_TRIANGLE(v0,v3,v1); - ADD_TRIANGLE(v1,v3,v2); + ADD_TRIANGLE(v0, v1, v2); + ADD_TRIANGLE(v0, v2, v3); + ADD_TRIANGLE(v0, v3, v1); + ADD_TRIANGLE(v1, v3, v2); return 3; } // ------------------------------------------------------------------------------------------------ // Build a hexahedron with points.magnitude == 1 -unsigned int StandardShapes::MakeHexahedron(std::vector& positions, - bool polygons /*= false*/) -{ - positions.reserve(positions.size()+36); - const ai_real length = ai_real(1.0)/ai_real(1.73205080); +unsigned int StandardShapes::MakeHexahedron(std::vector &positions, + bool polygons /*= false*/) { + positions.reserve(positions.size() + 36); + const ai_real length = ai_real(1.0) / ai_real(1.73205080); - const aiVector3D v0 = aiVector3D(-1.0,-1.0,-1.0)*length; - const aiVector3D v1 = aiVector3D(1.0,-1.0,-1.0)*length; - const aiVector3D v2 = aiVector3D(1.0,1.0,-1.0)*length; - const aiVector3D v3 = aiVector3D(-1.0,1.0,-1.0)*length; - const aiVector3D v4 = aiVector3D(-1.0,-1.0,1.0)*length; - const aiVector3D v5 = aiVector3D(1.0,-1.0,1.0)*length; - const aiVector3D v6 = aiVector3D(1.0,1.0,1.0)*length; - const aiVector3D v7 = aiVector3D(-1.0,1.0,1.0)*length; + const aiVector3D v0 = aiVector3D(-1.0, -1.0, -1.0) * length; + const aiVector3D v1 = aiVector3D(1.0, -1.0, -1.0) * length; + const aiVector3D v2 = aiVector3D(1.0, 1.0, -1.0) * length; + const aiVector3D v3 = aiVector3D(-1.0, 1.0, -1.0) * length; + const aiVector3D v4 = aiVector3D(-1.0, -1.0, 1.0) * length; + const aiVector3D v5 = aiVector3D(1.0, -1.0, 1.0) * length; + const aiVector3D v6 = aiVector3D(1.0, 1.0, 1.0) * length; + const aiVector3D v7 = aiVector3D(-1.0, 1.0, 1.0) * length; - ADD_QUAD(v0,v3,v2,v1); - ADD_QUAD(v0,v1,v5,v4); - ADD_QUAD(v0,v4,v7,v3); - ADD_QUAD(v6,v5,v1,v2); - ADD_QUAD(v6,v2,v3,v7); - ADD_QUAD(v6,v7,v4,v5); + ADD_QUAD(v0, v3, v2, v1); + ADD_QUAD(v0, v1, v5, v4); + ADD_QUAD(v0, v4, v7, v3); + ADD_QUAD(v6, v5, v1, v2); + ADD_QUAD(v6, v2, v3, v7); + ADD_QUAD(v6, v7, v4, v5); return (polygons ? 4 : 3); } @@ -366,28 +349,26 @@ unsigned int StandardShapes::MakeHexahedron(std::vector& positions, // ------------------------------------------------------------------------------------------------ // Create a subdivision sphere -void StandardShapes::MakeSphere(unsigned int tess, - std::vector& positions) -{ +void StandardShapes::MakeSphere(unsigned int tess, + std::vector &positions) { // Reserve enough storage. Every subdivision // splits each triangle in 4, the icosahedron consists of 60 verts - positions.reserve(positions.size()+60 * integer_pow(4, tess)); + positions.reserve(positions.size() + 60 * integer_pow(4, tess)); // Construct an icosahedron to start with MakeIcosahedron(positions); // ... and subdivide it until the requested output // tessellation is reached - for (unsigned int i = 0; i& positions,bool bOpen /*= false */) -{ +void StandardShapes::MakeCone(ai_real height, ai_real radius1, + ai_real radius2, unsigned int tess, + std::vector &positions, bool bOpen /*= false */) { // Sorry, a cone with less than 3 segments makes ABSOLUTELY NO SENSE if (tess < 3 || !height) return; @@ -401,39 +382,37 @@ void StandardShapes::MakeCone(ai_real height,ai_real radius1, ai_real halfHeight = height / ai_real(2.0); // radius1 is always the smaller one - if (radius2 > radius1) - { - std::swap(radius2,radius1); + if (radius2 > radius1) { + std::swap(radius2, radius1); halfHeight = -halfHeight; - } - else old = SIZE_MAX; + } else + old = SIZE_MAX; // Use a large epsilon to check whether the cone is pointy - if (radius1 < (radius2-radius1)*10e-3)radius1 = 0.0; + if (radius1 < (radius2 - radius1) * 10e-3) radius1 = 0.0; // We will need 3*2 verts per segment + 3*2 verts per segment // if the cone is closed - const unsigned int mem = tess*6 + (!bOpen ? tess*3 * (radius1 ? 2 : 1) : 0); - positions.reserve(positions.size () + mem); + const unsigned int mem = tess * 6 + (!bOpen ? tess * 3 * (radius1 ? 2 : 1) : 0); + positions.reserve(positions.size() + mem); // Now construct all segments const ai_real angle_delta = (ai_real)AI_MATH_TWO_PI / tess; - const ai_real angle_max = (ai_real)AI_MATH_TWO_PI; + const ai_real angle_max = (ai_real)AI_MATH_TWO_PI; ai_real s = 1.0; // std::cos(angle == 0); ai_real t = 0.0; // std::sin(angle == 0); - for (ai_real angle = 0.0; angle < angle_max; ) - { - const aiVector3D v1 = aiVector3D (s * radius1, -halfHeight, t * radius1 ); - const aiVector3D v2 = aiVector3D (s * radius2, halfHeight, t * radius2 ); + for (ai_real angle = 0.0; angle < angle_max;) { + const aiVector3D v1 = aiVector3D(s * radius1, -halfHeight, t * radius1); + const aiVector3D v2 = aiVector3D(s * radius2, halfHeight, t * radius2); const ai_real next = angle + angle_delta; ai_real s2 = std::cos(next); ai_real t2 = std::sin(next); - const aiVector3D v3 = aiVector3D (s2 * radius2, halfHeight, t2 * radius2 ); - const aiVector3D v4 = aiVector3D (s2 * radius1, -halfHeight, t2 * radius1 ); + const aiVector3D v3 = aiVector3D(s2 * radius2, halfHeight, t2 * radius2); + const aiVector3D v4 = aiVector3D(s2 * radius1, -halfHeight, t2 * radius1); positions.push_back(v1); positions.push_back(v2); @@ -442,21 +421,17 @@ void StandardShapes::MakeCone(ai_real height,ai_real radius1, positions.push_back(v1); positions.push_back(v3); - if (!bOpen) - { + if (!bOpen) { // generate the end 'cap' - positions.push_back(aiVector3D(s * radius2, halfHeight, t * radius2 )); - positions.push_back(aiVector3D(s2 * radius2, halfHeight, t2 * radius2 )); + positions.push_back(aiVector3D(s * radius2, halfHeight, t * radius2)); + positions.push_back(aiVector3D(s2 * radius2, halfHeight, t2 * radius2)); positions.push_back(aiVector3D(0.0, halfHeight, 0.0)); - - if (radius1) - { + if (radius1) { // generate the other end 'cap' - positions.push_back(aiVector3D(s * radius1, -halfHeight, t * radius1 )); - positions.push_back(aiVector3D(s2 * radius1, -halfHeight, t2 * radius1 )); + positions.push_back(aiVector3D(s * radius1, -halfHeight, t * radius1)); + positions.push_back(aiVector3D(s2 * radius1, -halfHeight, t2 * radius1)); positions.push_back(aiVector3D(0.0, -halfHeight, 0.0)); - } } s = s2; @@ -465,9 +440,9 @@ void StandardShapes::MakeCone(ai_real height,ai_real radius1, } // Need to flip face order? - if ( SIZE_MAX != old ) { - for (size_t p = old; p < positions.size();p += 3) { - std::swap(positions[p],positions[p+1]); + if (SIZE_MAX != old) { + for (size_t p = old; p < positions.size(); p += 3) { + std::swap(positions[p], positions[p + 1]); } } } @@ -475,8 +450,7 @@ void StandardShapes::MakeCone(ai_real height,ai_real radius1, // ------------------------------------------------------------------------------------------------ // Build a circle void StandardShapes::MakeCircle(ai_real radius, unsigned int tess, - std::vector& positions) -{ + std::vector &positions) { // Sorry, a circle with less than 3 segments makes ABSOLUTELY NO SENSE if (tess < 3 || !radius) return; @@ -484,24 +458,23 @@ void StandardShapes::MakeCircle(ai_real radius, unsigned int tess, radius = std::fabs(radius); // We will need 3 vertices per segment - positions.reserve(positions.size()+tess*3); + positions.reserve(positions.size() + tess * 3); const ai_real angle_delta = (ai_real)AI_MATH_TWO_PI / tess; - const ai_real angle_max = (ai_real)AI_MATH_TWO_PI; + const ai_real angle_max = (ai_real)AI_MATH_TWO_PI; ai_real s = 1.0; // std::cos(angle == 0); ai_real t = 0.0; // std::sin(angle == 0); - for (ai_real angle = 0.0; angle < angle_max; ) - { - positions.push_back(aiVector3D(s * radius,0.0,t * radius)); + for (ai_real angle = 0.0; angle < angle_max;) { + positions.push_back(aiVector3D(s * radius, 0.0, t * radius)); angle += angle_delta; s = std::cos(angle); t = std::sin(angle); - positions.push_back(aiVector3D(s * radius,0.0,t * radius)); + positions.push_back(aiVector3D(s * radius, 0.0, t * radius)); - positions.push_back(aiVector3D(0.0,0.0,0.0)); + positions.push_back(aiVector3D(0.0, 0.0, 0.0)); } } -} // ! Assimp +} // namespace Assimp diff --git a/code/Common/Subdivision.cpp b/code/Common/Subdivision.cpp index ca7749891..b1f07c9f5 100644 --- a/code/Common/Subdivision.cpp +++ b/code/Common/Subdivision.cpp @@ -54,7 +54,7 @@ using namespace Assimp; void mydummy() {} #ifdef _WIN32 -# pragma warning( disable : 4709 ) +#pragma warning(disable : 4709) #endif // _WIN32 // ------------------------------------------------------------------------------------------------ /** Subdivider stub class to implement the Catmull-Clarke subdivision algorithm. The @@ -63,24 +63,22 @@ void mydummy() {} // ------------------------------------------------------------------------------------------------ class CatmullClarkSubdivider : public Subdivider { public: - void Subdivide (aiMesh* mesh, aiMesh*& out, unsigned int num, bool discard_input); - void Subdivide (aiMesh** smesh, size_t nmesh, - aiMesh** out, unsigned int num, bool discard_input); + void Subdivide(aiMesh *mesh, aiMesh *&out, unsigned int num, bool discard_input); + void Subdivide(aiMesh **smesh, size_t nmesh, + aiMesh **out, unsigned int num, bool discard_input); // --------------------------------------------------------------------------- /** Intermediate description of an edge between two corners of a polygon*/ // --------------------------------------------------------------------------- - struct Edge - { - Edge() - : ref(0) - {} + struct Edge { + Edge() : + ref(0) {} Vertex edge_point, midpoint; unsigned int ref; }; typedef std::vector UIntVector; - typedef std::map EdgeMap; + typedef std::map EdgeMap; // --------------------------------------------------------------------------- // Hashing function to derive an index into an #EdgeMap from two given @@ -94,80 +92,72 @@ public: // invariant id0out+nmesh); + ai_assert(smesh < out || smesh + nmesh > out + nmesh); if (!num) { // No subdivision at all. Need to copy all the meshes .. argh. if (discard_input) { for (size_t s = 0; s < nmesh; ++s) { out[s] = smesh[s]; - smesh[s] = NULL; + smesh[s] = nullptr; } - } - else { + } else { for (size_t s = 0; s < nmesh; ++s) { - SceneCombiner::Copy(out+s,smesh[s]); + SceneCombiner::Copy(out + s, smesh[s]); } } return; } - std::vector inmeshes; - std::vector outmeshes; + std::vector inmeshes; + std::vector outmeshes; std::vector maptbl; inmeshes.reserve(nmesh); @@ -178,34 +168,35 @@ void CatmullClarkSubdivider::Subdivide ( // number of edge cases the subdivider is forced to deal with. Line and // point meshes are simply passed through. for (size_t s = 0; s < nmesh; ++s) { - aiMesh* i = smesh[s]; + aiMesh *i = smesh[s]; // FIX - mPrimitiveTypes might not yet be initialized - if (i->mPrimitiveTypes && (i->mPrimitiveTypes & (aiPrimitiveType_LINE|aiPrimitiveType_POINT))==i->mPrimitiveTypes) { + if (i->mPrimitiveTypes && (i->mPrimitiveTypes & (aiPrimitiveType_LINE | aiPrimitiveType_POINT)) == i->mPrimitiveTypes) { ASSIMP_LOG_VERBOSE_DEBUG("Catmull-Clark Subdivider: Skipping pure line/point mesh"); if (discard_input) { out[s] = i; - smesh[s] = NULL; - } - else { - SceneCombiner::Copy(out+s,i); + smesh[s] = nullptr; + } else { + SceneCombiner::Copy(out + s, i); } continue; } - outmeshes.push_back(NULL);inmeshes.push_back(i); + outmeshes.push_back(nullptr); + inmeshes.push_back(i); maptbl.push_back(static_cast(s)); } // Do the actual subdivision on the preallocated storage. InternSubdivide // *always* assumes that enough storage is available, it does not bother // checking any ranges. - ai_assert(inmeshes.size()==outmeshes.size()&&inmeshes.size()==maptbl.size()); + ai_assert(inmeshes.size() == outmeshes.size()); + ai_assert(inmeshes.size() == maptbl.size()); if (inmeshes.empty()) { ASSIMP_LOG_WARN("Catmull-Clark Subdivider: Pure point/line scene, I can't do anything"); return; } - InternSubdivide(&inmeshes.front(),inmeshes.size(),&outmeshes.front(),num); + InternSubdivide(&inmeshes.front(), inmeshes.size(), &outmeshes.front(), num); for (unsigned int i = 0; i < maptbl.size(); ++i) { ai_assert(nullptr != outmeshes[i]); out[maptbl[i]] = outmeshes[i]; @@ -229,14 +220,14 @@ void CatmullClarkSubdivider::Subdivide ( // in-place unless 'smesh' and 'out' are equal (no strange overlaps or reorderings). // Previous data is replaced/deleted then. // ------------------------------------------------------------------------------------------------ -void CatmullClarkSubdivider::InternSubdivide ( - const aiMesh* const * smesh, - size_t nmesh, - aiMesh** out, - unsigned int num - ) -{ - ai_assert(NULL != smesh && NULL != out); +void CatmullClarkSubdivider::InternSubdivide( + const aiMesh *const *smesh, + size_t nmesh, + aiMesh **out, + unsigned int num) { + ai_assert(nullptr != smesh); + ai_assert(nullptr != out); + INIT_EDGE_HASH_TEMPORARIES(); // no subdivision requested or end of recursive refinement @@ -251,25 +242,24 @@ void CatmullClarkSubdivider::InternSubdivide ( // 0. Offset table to index all meshes continuously, generate a spatially // sorted representation of all vertices in all meshes. // --------------------------------------------------------------------- - typedef std::pair IntPair; + typedef std::pair IntPair; std::vector moffsets(nmesh); unsigned int totfaces = 0, totvert = 0; for (size_t t = 0; t < nmesh; ++t) { - const aiMesh* mesh = smesh[t]; + const aiMesh *mesh = smesh[t]; - spatial.Append(mesh->mVertices,mesh->mNumVertices,sizeof(aiVector3D),false); - moffsets[t] = IntPair(totfaces,totvert); + spatial.Append(mesh->mVertices, mesh->mNumVertices, sizeof(aiVector3D), false); + moffsets[t] = IntPair(totfaces, totvert); totfaces += mesh->mNumFaces; - totvert += mesh->mNumVertices; + totvert += mesh->mNumVertices; } spatial.Finalize(); - const unsigned int num_unique = spatial.GenerateMappingTable(maptbl,ComputePositionEpsilon(smesh,nmesh)); + const unsigned int num_unique = spatial.GenerateMappingTable(maptbl, ComputePositionEpsilon(smesh, nmesh)); - -#define FLATTEN_VERTEX_IDX(mesh_idx, vert_idx) (moffsets[mesh_idx].second+vert_idx) -#define FLATTEN_FACE_IDX(mesh_idx, face_idx) (moffsets[mesh_idx].first+face_idx) +#define FLATTEN_VERTEX_IDX(mesh_idx, vert_idx) (moffsets[mesh_idx].second + vert_idx) +#define FLATTEN_FACE_IDX(mesh_idx, face_idx) (moffsets[mesh_idx].first + face_idx) // --------------------------------------------------------------------- // 1. Compute the centroid point for all faces @@ -277,14 +267,13 @@ void CatmullClarkSubdivider::InternSubdivide ( std::vector centroids(totfaces); unsigned int nfacesout = 0; for (size_t t = 0, n = 0; t < nmesh; ++t) { - const aiMesh* mesh = smesh[t]; - for (unsigned int i = 0; i < mesh->mNumFaces;++i,++n) - { - const aiFace& face = mesh->mFaces[i]; - Vertex& c = centroids[n]; + const aiMesh *mesh = smesh[t]; + for (unsigned int i = 0; i < mesh->mNumFaces; ++i, ++n) { + const aiFace &face = mesh->mFaces[i]; + Vertex &c = centroids[n]; - for (unsigned int a = 0; a < face.mNumIndices;++a) { - c += Vertex(mesh,face.mIndices[a]); + for (unsigned int a = 0; a < face.mNumIndices; ++a) { + c += Vertex(mesh, face.mIndices[a]); } c /= static_cast(face.mNumIndices); @@ -293,297 +282,297 @@ void CatmullClarkSubdivider::InternSubdivide ( } { - // we want edges to go away before the recursive calls so begin a new scope - EdgeMap edges; + // we want edges to go away before the recursive calls so begin a new scope + EdgeMap edges; - // --------------------------------------------------------------------- - // 2. Set each edge point to be the average of all neighbouring - // face points and original points. Every edge exists twice - // if there is a neighboring face. - // --------------------------------------------------------------------- - for (size_t t = 0; t < nmesh; ++t) { - const aiMesh* mesh = smesh[t]; + // --------------------------------------------------------------------- + // 2. Set each edge point to be the average of all neighbouring + // face points and original points. Every edge exists twice + // if there is a neighboring face. + // --------------------------------------------------------------------- + for (size_t t = 0; t < nmesh; ++t) { + const aiMesh *mesh = smesh[t]; - for (unsigned int i = 0; i < mesh->mNumFaces;++i) { - const aiFace& face = mesh->mFaces[i]; + for (unsigned int i = 0; i < mesh->mNumFaces; ++i) { + const aiFace &face = mesh->mFaces[i]; - for (unsigned int p =0; p< face.mNumIndices; ++p) { - const unsigned int id[] = { - face.mIndices[p], - face.mIndices[p==face.mNumIndices-1?0:p+1] - }; - const unsigned int mp[] = { - maptbl[FLATTEN_VERTEX_IDX(t,id[0])], - maptbl[FLATTEN_VERTEX_IDX(t,id[1])] - }; + for (unsigned int p = 0; p < face.mNumIndices; ++p) { + const unsigned int id[] = { + face.mIndices[p], + face.mIndices[p == face.mNumIndices - 1 ? 0 : p + 1] + }; + const unsigned int mp[] = { + maptbl[FLATTEN_VERTEX_IDX(t, id[0])], + maptbl[FLATTEN_VERTEX_IDX(t, id[1])] + }; - Edge& e = edges[MAKE_EDGE_HASH(mp[0],mp[1])]; - e.ref++; - if (e.ref<=2) { - if (e.ref==1) { // original points (end points) - add only once - e.edge_point = e.midpoint = Vertex(mesh,id[0])+Vertex(mesh,id[1]); - e.midpoint *= 0.5f; + Edge &e = edges[MAKE_EDGE_HASH(mp[0], mp[1])]; + e.ref++; + if (e.ref <= 2) { + if (e.ref == 1) { // original points (end points) - add only once + e.edge_point = e.midpoint = Vertex(mesh, id[0]) + Vertex(mesh, id[1]); + e.midpoint *= 0.5f; + } + e.edge_point += centroids[FLATTEN_FACE_IDX(t, i)]; } - e.edge_point += centroids[FLATTEN_FACE_IDX(t,i)]; } } } - } - // --------------------------------------------------------------------- - // 3. Normalize edge points - // --------------------------------------------------------------------- - {unsigned int bad_cnt = 0; - for (EdgeMap::iterator it = edges.begin(); it != edges.end(); ++it) { - if ((*it).second.ref < 2) { - ai_assert((*it).second.ref); - ++bad_cnt; - } - (*it).second.edge_point *= 1.f/((*it).second.ref+2.f); - } + // --------------------------------------------------------------------- + // 3. Normalize edge points + // --------------------------------------------------------------------- + { + unsigned int bad_cnt = 0; + for (EdgeMap::iterator it = edges.begin(); it != edges.end(); ++it) { + if ((*it).second.ref < 2) { + ai_assert((*it).second.ref); + ++bad_cnt; + } + (*it).second.edge_point *= 1.f / ((*it).second.ref + 2.f); + } - if (bad_cnt) { - // Report the number of bad edges. bad edges are referenced by less than two - // faces in the mesh. They occur at outer model boundaries in non-closed - // shapes. - ASSIMP_LOG_VERBOSE_DEBUG_F("Catmull-Clark Subdivider: got ", bad_cnt, " bad edges touching only one face (totally ", - static_cast(edges.size()), " edges). "); - }} - - // --------------------------------------------------------------------- - // 4. Compute a vertex-face adjacency table. We can't reuse the code - // from VertexTriangleAdjacency because we need the table for multiple - // meshes and out vertex indices need to be mapped to distinct values - // first. - // --------------------------------------------------------------------- - UIntVector faceadjac(nfacesout), cntadjfac(maptbl.size(),0), ofsadjvec(maptbl.size()+1,0); { - for (size_t t = 0; t < nmesh; ++t) { - const aiMesh* const minp = smesh[t]; - for (unsigned int i = 0; i < minp->mNumFaces; ++i) { - - const aiFace& f = minp->mFaces[i]; - for (unsigned int n = 0; n < f.mNumIndices; ++n) { - ++cntadjfac[maptbl[FLATTEN_VERTEX_IDX(t,f.mIndices[n])]]; + if (bad_cnt) { + // Report the number of bad edges. bad edges are referenced by less than two + // faces in the mesh. They occur at outer model boundaries in non-closed + // shapes. + ASSIMP_LOG_VERBOSE_DEBUG_F("Catmull-Clark Subdivider: got ", bad_cnt, " bad edges touching only one face (totally ", + static_cast(edges.size()), " edges). "); } } - } - unsigned int cur = 0; - for (size_t i = 0; i < cntadjfac.size(); ++i) { - ofsadjvec[i+1] = cur; - cur += cntadjfac[i]; - } - for (size_t t = 0; t < nmesh; ++t) { - const aiMesh* const minp = smesh[t]; - for (unsigned int i = 0; i < minp->mNumFaces; ++i) { - const aiFace& f = minp->mFaces[i]; - for (unsigned int n = 0; n < f.mNumIndices; ++n) { - faceadjac[ofsadjvec[1+maptbl[FLATTEN_VERTEX_IDX(t,f.mIndices[n])]]++] = FLATTEN_FACE_IDX(t,i); + // --------------------------------------------------------------------- + // 4. Compute a vertex-face adjacency table. We can't reuse the code + // from VertexTriangleAdjacency because we need the table for multiple + // meshes and out vertex indices need to be mapped to distinct values + // first. + // --------------------------------------------------------------------- + UIntVector faceadjac(nfacesout), cntadjfac(maptbl.size(), 0), ofsadjvec(maptbl.size() + 1, 0); + { + for (size_t t = 0; t < nmesh; ++t) { + const aiMesh *const minp = smesh[t]; + for (unsigned int i = 0; i < minp->mNumFaces; ++i) { + + const aiFace &f = minp->mFaces[i]; + for (unsigned int n = 0; n < f.mNumIndices; ++n) { + ++cntadjfac[maptbl[FLATTEN_VERTEX_IDX(t, f.mIndices[n])]]; + } + } } - } - } + unsigned int cur = 0; + for (size_t i = 0; i < cntadjfac.size(); ++i) { + ofsadjvec[i + 1] = cur; + cur += cntadjfac[i]; + } + for (size_t t = 0; t < nmesh; ++t) { + const aiMesh *const minp = smesh[t]; + for (unsigned int i = 0; i < minp->mNumFaces; ++i) { - // check the other way round for consistency + const aiFace &f = minp->mFaces[i]; + for (unsigned int n = 0; n < f.mNumIndices; ++n) { + faceadjac[ofsadjvec[1 + maptbl[FLATTEN_VERTEX_IDX(t, f.mIndices[n])]]++] = FLATTEN_FACE_IDX(t, i); + } + } + } + + // check the other way round for consistency #ifdef ASSIMP_BUILD_DEBUG - for (size_t t = 0; t < ofsadjvec.size()-1; ++t) { - for (unsigned int m = 0; m < cntadjfac[t]; ++m) { - const unsigned int fidx = faceadjac[ofsadjvec[t]+m]; - ai_assert(fidx < totfaces); - for (size_t n = 1; n < nmesh; ++n) { + for (size_t t = 0; t < ofsadjvec.size() - 1; ++t) { + for (unsigned int m = 0; m < cntadjfac[t]; ++m) { + const unsigned int fidx = faceadjac[ofsadjvec[t] + m]; + ai_assert(fidx < totfaces); + for (size_t n = 1; n < nmesh; ++n) { - if (moffsets[n].first > fidx) { - const aiMesh* msh = smesh[--n]; - const aiFace& f = msh->mFaces[fidx-moffsets[n].first]; + if (moffsets[n].first > fidx) { + const aiMesh *msh = smesh[--n]; + const aiFace &f = msh->mFaces[fidx - moffsets[n].first]; - bool haveit = false; - for (unsigned int i = 0; i < f.mNumIndices; ++i) { - if (maptbl[FLATTEN_VERTEX_IDX(n,f.mIndices[i])]==(unsigned int)t) { - haveit = true; - break; - } - } - ai_assert(haveit); - if (!haveit) { - ASSIMP_LOG_VERBOSE_DEBUG("Catmull-Clark Subdivider: Index not used"); - } - break; - } - } - } - } - -#endif - } - -#define GET_ADJACENT_FACES_AND_CNT(vidx,fstartout,numout) \ - fstartout = &faceadjac[ofsadjvec[vidx]], numout = cntadjfac[vidx] - - typedef std::pair TouchedOVertex; - std::vector new_points(num_unique,TouchedOVertex(false,Vertex())); - // --------------------------------------------------------------------- - // 5. Spawn a quad from each face point to the corresponding edge points - // the original points being the fourth quad points. - // --------------------------------------------------------------------- - for (size_t t = 0; t < nmesh; ++t) { - const aiMesh* const minp = smesh[t]; - aiMesh* const mout = out[t] = new aiMesh(); - - for (unsigned int a = 0; a < minp->mNumFaces; ++a) { - mout->mNumFaces += minp->mFaces[a].mNumIndices; - } - - // We need random access to the old face buffer, so reuse is not possible. - mout->mFaces = new aiFace[mout->mNumFaces]; - - mout->mNumVertices = mout->mNumFaces*4; - mout->mVertices = new aiVector3D[mout->mNumVertices]; - - // quads only, keep material index - mout->mPrimitiveTypes = aiPrimitiveType_POLYGON; - mout->mMaterialIndex = minp->mMaterialIndex; - - if (minp->HasNormals()) { - mout->mNormals = new aiVector3D[mout->mNumVertices]; - } - - if (minp->HasTangentsAndBitangents()) { - mout->mTangents = new aiVector3D[mout->mNumVertices]; - mout->mBitangents = new aiVector3D[mout->mNumVertices]; - } - - for(unsigned int i = 0; minp->HasTextureCoords(i); ++i) { - mout->mTextureCoords[i] = new aiVector3D[mout->mNumVertices]; - mout->mNumUVComponents[i] = minp->mNumUVComponents[i]; - } - - for(unsigned int i = 0; minp->HasVertexColors(i); ++i) { - mout->mColors[i] = new aiColor4D[mout->mNumVertices]; - } - - mout->mNumVertices = mout->mNumFaces<<2u; - for (unsigned int i = 0, v = 0, n = 0; i < minp->mNumFaces;++i) { - - const aiFace& face = minp->mFaces[i]; - for (unsigned int a = 0; a < face.mNumIndices;++a) { - - // Get a clean new face. - aiFace& faceOut = mout->mFaces[n++]; - faceOut.mIndices = new unsigned int [faceOut.mNumIndices = 4]; - - // Spawn a new quadrilateral (ccw winding) for this original point between: - // a) face centroid - centroids[FLATTEN_FACE_IDX(t,i)].SortBack(mout,faceOut.mIndices[0]=v++); - - // b) adjacent edge on the left, seen from the centroid - const Edge& e0 = edges[MAKE_EDGE_HASH(maptbl[FLATTEN_VERTEX_IDX(t,face.mIndices[a])], - maptbl[FLATTEN_VERTEX_IDX(t,face.mIndices[a==face.mNumIndices-1?0:a+1]) - ])]; // fixme: replace with mod face.mNumIndices? - - // c) adjacent edge on the right, seen from the centroid - const Edge& e1 = edges[MAKE_EDGE_HASH(maptbl[FLATTEN_VERTEX_IDX(t,face.mIndices[a])], - maptbl[FLATTEN_VERTEX_IDX(t,face.mIndices[!a?face.mNumIndices-1:a-1]) - ])]; // fixme: replace with mod face.mNumIndices? - - e0.edge_point.SortBack(mout,faceOut.mIndices[3]=v++); - e1.edge_point.SortBack(mout,faceOut.mIndices[1]=v++); - - // d= original point P with distinct index i - // F := 0 - // R := 0 - // n := 0 - // for each face f containing i - // F := F+ centroid of f - // R := R+ midpoint of edge of f from i to i+1 - // n := n+1 - // - // (F+2R+(n-3)P)/n - const unsigned int org = maptbl[FLATTEN_VERTEX_IDX(t,face.mIndices[a])]; - TouchedOVertex& ov = new_points[org]; - - if (!ov.first) { - ov.first = true; - - const unsigned int* adj; unsigned int cnt; - GET_ADJACENT_FACES_AND_CNT(org,adj,cnt); - - if (cnt < 3) { - ov.second = Vertex(minp,face.mIndices[a]); - } - else { - - Vertex F,R; - for (unsigned int o = 0; o < cnt; ++o) { - ai_assert(adj[o] < totfaces); - F += centroids[adj[o]]; - - // adj[0] is a global face index - search the face in the mesh list - const aiMesh* mp = NULL; - size_t nidx; - - if (adj[o] < moffsets[0].first) { - mp = smesh[nidx=0]; - } - else { - for (nidx = 1; nidx<= nmesh; ++nidx) { - if (nidx == nmesh ||moffsets[nidx].first > adj[o]) { - mp = smesh[--nidx]; - break; - } - } - } - - ai_assert(adj[o]-moffsets[nidx].first < mp->mNumFaces); - const aiFace& f = mp->mFaces[adj[o]-moffsets[nidx].first]; bool haveit = false; - - // find our original point in the face - for (unsigned int m = 0; m < f.mNumIndices; ++m) { - if (maptbl[FLATTEN_VERTEX_IDX(nidx,f.mIndices[m])] == org) { - - // add *both* edges. this way, we can be sure that we add - // *all* adjacent edges to R. In a closed shape, every - // edge is added twice - so we simply leave out the - // factor 2.f in the amove formula and get the right - // result. - - const Edge& c0 = edges[MAKE_EDGE_HASH(org,maptbl[FLATTEN_VERTEX_IDX( - nidx,f.mIndices[!m?f.mNumIndices-1:m-1])])]; - // fixme: replace with mod face.mNumIndices? - - const Edge& c1 = edges[MAKE_EDGE_HASH(org,maptbl[FLATTEN_VERTEX_IDX( - nidx,f.mIndices[m==f.mNumIndices-1?0:m+1])])]; - // fixme: replace with mod face.mNumIndices? - R += c0.midpoint+c1.midpoint; - + for (unsigned int i = 0; i < f.mNumIndices; ++i) { + if (maptbl[FLATTEN_VERTEX_IDX(n, f.mIndices[i])] == (unsigned int)t) { haveit = true; break; } } - - // this invariant *must* hold if the vertex-to-face adjacency table is valid ai_assert(haveit); - if ( !haveit ) { - ASSIMP_LOG_WARN( "OBJ: no name for material library specified." ); + if (!haveit) { + ASSIMP_LOG_VERBOSE_DEBUG("Catmull-Clark Subdivider: Index not used"); } + break; } - - const float div = static_cast(cnt), divsq = 1.f/(div*div); - ov.second = Vertex(minp,face.mIndices[a])*((div-3.f) / div) + R*divsq + F*divsq; } } - ov.second.SortBack(mout,faceOut.mIndices[2]=v++); + } + +#endif + } + +#define GET_ADJACENT_FACES_AND_CNT(vidx, fstartout, numout) \ + fstartout = &faceadjac[ofsadjvec[vidx]], numout = cntadjfac[vidx] + + typedef std::pair TouchedOVertex; + std::vector new_points(num_unique, TouchedOVertex(false, Vertex())); + // --------------------------------------------------------------------- + // 5. Spawn a quad from each face point to the corresponding edge points + // the original points being the fourth quad points. + // --------------------------------------------------------------------- + for (size_t t = 0; t < nmesh; ++t) { + const aiMesh *const minp = smesh[t]; + aiMesh *const mout = out[t] = new aiMesh(); + + for (unsigned int a = 0; a < minp->mNumFaces; ++a) { + mout->mNumFaces += minp->mFaces[a].mNumIndices; + } + + // We need random access to the old face buffer, so reuse is not possible. + mout->mFaces = new aiFace[mout->mNumFaces]; + + mout->mNumVertices = mout->mNumFaces * 4; + mout->mVertices = new aiVector3D[mout->mNumVertices]; + + // quads only, keep material index + mout->mPrimitiveTypes = aiPrimitiveType_POLYGON; + mout->mMaterialIndex = minp->mMaterialIndex; + + if (minp->HasNormals()) { + mout->mNormals = new aiVector3D[mout->mNumVertices]; + } + + if (minp->HasTangentsAndBitangents()) { + mout->mTangents = new aiVector3D[mout->mNumVertices]; + mout->mBitangents = new aiVector3D[mout->mNumVertices]; + } + + for (unsigned int i = 0; minp->HasTextureCoords(i); ++i) { + mout->mTextureCoords[i] = new aiVector3D[mout->mNumVertices]; + mout->mNumUVComponents[i] = minp->mNumUVComponents[i]; + } + + for (unsigned int i = 0; minp->HasVertexColors(i); ++i) { + mout->mColors[i] = new aiColor4D[mout->mNumVertices]; + } + + mout->mNumVertices = mout->mNumFaces << 2u; + for (unsigned int i = 0, v = 0, n = 0; i < minp->mNumFaces; ++i) { + + const aiFace &face = minp->mFaces[i]; + for (unsigned int a = 0; a < face.mNumIndices; ++a) { + + // Get a clean new face. + aiFace &faceOut = mout->mFaces[n++]; + faceOut.mIndices = new unsigned int[faceOut.mNumIndices = 4]; + + // Spawn a new quadrilateral (ccw winding) for this original point between: + // a) face centroid + centroids[FLATTEN_FACE_IDX(t, i)].SortBack(mout, faceOut.mIndices[0] = v++); + + // b) adjacent edge on the left, seen from the centroid + const Edge &e0 = edges[MAKE_EDGE_HASH(maptbl[FLATTEN_VERTEX_IDX(t, face.mIndices[a])], + maptbl[FLATTEN_VERTEX_IDX(t, face.mIndices[a == face.mNumIndices - 1 ? 0 : a + 1])])]; // fixme: replace with mod face.mNumIndices? + + // c) adjacent edge on the right, seen from the centroid + const Edge &e1 = edges[MAKE_EDGE_HASH(maptbl[FLATTEN_VERTEX_IDX(t, face.mIndices[a])], + maptbl[FLATTEN_VERTEX_IDX(t, face.mIndices[!a ? face.mNumIndices - 1 : a - 1])])]; // fixme: replace with mod face.mNumIndices? + + e0.edge_point.SortBack(mout, faceOut.mIndices[3] = v++); + e1.edge_point.SortBack(mout, faceOut.mIndices[1] = v++); + + // d= original point P with distinct index i + // F := 0 + // R := 0 + // n := 0 + // for each face f containing i + // F := F+ centroid of f + // R := R+ midpoint of edge of f from i to i+1 + // n := n+1 + // + // (F+2R+(n-3)P)/n + const unsigned int org = maptbl[FLATTEN_VERTEX_IDX(t, face.mIndices[a])]; + TouchedOVertex &ov = new_points[org]; + + if (!ov.first) { + ov.first = true; + + const unsigned int *adj; + unsigned int cnt; + GET_ADJACENT_FACES_AND_CNT(org, adj, cnt); + + if (cnt < 3) { + ov.second = Vertex(minp, face.mIndices[a]); + } else { + + Vertex F, R; + for (unsigned int o = 0; o < cnt; ++o) { + ai_assert(adj[o] < totfaces); + F += centroids[adj[o]]; + + // adj[0] is a global face index - search the face in the mesh list + const aiMesh *mp = nullptr; + size_t nidx; + + if (adj[o] < moffsets[0].first) { + mp = smesh[nidx = 0]; + } else { + for (nidx = 1; nidx <= nmesh; ++nidx) { + if (nidx == nmesh || moffsets[nidx].first > adj[o]) { + mp = smesh[--nidx]; + break; + } + } + } + + ai_assert(adj[o] - moffsets[nidx].first < mp->mNumFaces); + const aiFace &f = mp->mFaces[adj[o] - moffsets[nidx].first]; + bool haveit = false; + + // find our original point in the face + for (unsigned int m = 0; m < f.mNumIndices; ++m) { + if (maptbl[FLATTEN_VERTEX_IDX(nidx, f.mIndices[m])] == org) { + + // add *both* edges. this way, we can be sure that we add + // *all* adjacent edges to R. In a closed shape, every + // edge is added twice - so we simply leave out the + // factor 2.f in the amove formula and get the right + // result. + + const Edge &c0 = edges[MAKE_EDGE_HASH(org, maptbl[FLATTEN_VERTEX_IDX( + nidx, f.mIndices[!m ? f.mNumIndices - 1 : m - 1])])]; + // fixme: replace with mod face.mNumIndices? + + const Edge &c1 = edges[MAKE_EDGE_HASH(org, maptbl[FLATTEN_VERTEX_IDX( + nidx, f.mIndices[m == f.mNumIndices - 1 ? 0 : m + 1])])]; + // fixme: replace with mod face.mNumIndices? + R += c0.midpoint + c1.midpoint; + + haveit = true; + break; + } + } + + // this invariant *must* hold if the vertex-to-face adjacency table is valid + ai_assert(haveit); + if (!haveit) { + ASSIMP_LOG_WARN("OBJ: no name for material library specified."); + } + } + + const float div = static_cast(cnt), divsq = 1.f / (div * div); + ov.second = Vertex(minp, face.mIndices[a]) * ((div - 3.f) / div) + R * divsq + F * divsq; + } + } + ov.second.SortBack(mout, faceOut.mIndices[2] = v++); + } } } - } - } // end of scope for edges, freeing its memory + } // end of scope for edges, freeing its memory // --------------------------------------------------------------------- // 7. Apply the next subdivision step. // --------------------------------------------------------------------- if (num != 1) { - std::vector tmp(nmesh); - InternSubdivide (out,nmesh,&tmp.front(),num-1); + std::vector tmp(nmesh); + InternSubdivide(out, nmesh, &tmp.front(), num - 1); for (size_t i = 0; i < nmesh; ++i) { delete out[i]; out[i] = tmp[i]; diff --git a/code/Common/TargetAnimation.cpp b/code/Common/TargetAnimation.cpp index 3c61d2176..05fd334c4 100644 --- a/code/Common/TargetAnimation.cpp +++ b/code/Common/TargetAnimation.cpp @@ -41,58 +41,51 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "TargetAnimation.h" -#include #include +#include using namespace Assimp; - // ------------------------------------------------------------------------------------------------ -KeyIterator::KeyIterator(const std::vector* _objPos, - const std::vector* _targetObjPos, - const aiVector3D* defaultObjectPos /*= NULL*/, - const aiVector3D* defaultTargetPos /*= NULL*/) - - : reachedEnd (false) - , curTime (-1.) - , objPos (_objPos) - , targetObjPos (_targetObjPos) - , nextObjPos (0) - , nextTargetObjPos(0) -{ +KeyIterator::KeyIterator(const std::vector *_objPos, + const std::vector *_targetObjPos, + const aiVector3D *defaultObjectPos /*= nullptr*/, + const aiVector3D *defaultTargetPos /*= nullptr*/) : + reachedEnd(false), + curTime(-1.), + objPos(_objPos), + targetObjPos(_targetObjPos), + nextObjPos(0), + nextTargetObjPos(0) { // Generate default transformation tracks if necessary - if (!objPos || objPos->empty()) - { + if (!objPos || objPos->empty()) { defaultObjPos.resize(1); - defaultObjPos.front().mTime = 10e10; + defaultObjPos.front().mTime = 10e10; if (defaultObjectPos) defaultObjPos.front().mValue = *defaultObjectPos; - objPos = & defaultObjPos; + objPos = &defaultObjPos; } - if (!targetObjPos || targetObjPos->empty()) - { + if (!targetObjPos || targetObjPos->empty()) { defaultTargetObjPos.resize(1); - defaultTargetObjPos.front().mTime = 10e10; + defaultTargetObjPos.front().mTime = 10e10; if (defaultTargetPos) defaultTargetObjPos.front().mValue = *defaultTargetPos; - targetObjPos = & defaultTargetObjPos; + targetObjPos = &defaultTargetObjPos; } } // ------------------------------------------------------------------------------------------------ template -inline T Interpolate(const T& one, const T& two, ai_real val) -{ - return one + (two-one)*val; +inline T Interpolate(const T &one, const T &two, ai_real val) { + return one + (two - one) * val; } // ------------------------------------------------------------------------------------------------ -void KeyIterator::operator ++() -{ +void KeyIterator::operator++() { // If we are already at the end of all keyframes, return if (reachedEnd) { return; @@ -100,113 +93,102 @@ void KeyIterator::operator ++() // Now search in all arrays for the time value closest // to our current position on the time line - double d0,d1; + double d0, d1; - d0 = objPos->at ( std::min ( nextObjPos, static_cast(objPos->size()-1)) ).mTime; - d1 = targetObjPos->at( std::min ( nextTargetObjPos, static_cast(targetObjPos->size()-1)) ).mTime; + d0 = objPos->at(std::min(nextObjPos, static_cast(objPos->size() - 1))).mTime; + d1 = targetObjPos->at(std::min(nextTargetObjPos, static_cast(targetObjPos->size() - 1))).mTime; // Easiest case - all are identical. In this // case we don't need to interpolate so we can // return earlier - if ( d0 == d1 ) - { + if (d0 == d1) { curTime = d0; curPosition = objPos->at(nextObjPos).mValue; curTargetPosition = targetObjPos->at(nextTargetObjPos).mValue; // increment counters - if (objPos->size() != nextObjPos-1) + if (objPos->size() != nextObjPos - 1) ++nextObjPos; - if (targetObjPos->size() != nextTargetObjPos-1) + if (targetObjPos->size() != nextTargetObjPos - 1) ++nextTargetObjPos; } // An object position key is closest to us - else if (d0 < d1) - { + else if (d0 < d1) { curTime = d0; // interpolate the other if (1 == targetObjPos->size() || !nextTargetObjPos) { curTargetPosition = targetObjPos->at(0).mValue; - } - else - { - const aiVectorKey& last = targetObjPos->at(nextTargetObjPos); - const aiVectorKey& first = targetObjPos->at(nextTargetObjPos-1); + } else { + const aiVectorKey &last = targetObjPos->at(nextTargetObjPos); + const aiVectorKey &first = targetObjPos->at(nextTargetObjPos - 1); - curTargetPosition = Interpolate(first.mValue, last.mValue, (ai_real) ( - (curTime-first.mTime) / (last.mTime-first.mTime) )); + curTargetPosition = Interpolate(first.mValue, last.mValue, (ai_real)((curTime - first.mTime) / (last.mTime - first.mTime))); } - if (objPos->size() != nextObjPos-1) + if (objPos->size() != nextObjPos - 1) ++nextObjPos; } // A target position key is closest to us - else - { + else { curTime = d1; // interpolate the other if (1 == objPos->size() || !nextObjPos) { curPosition = objPos->at(0).mValue; - } - else - { - const aiVectorKey& last = objPos->at(nextObjPos); - const aiVectorKey& first = objPos->at(nextObjPos-1); + } else { + const aiVectorKey &last = objPos->at(nextObjPos); + const aiVectorKey &first = objPos->at(nextObjPos - 1); - curPosition = Interpolate(first.mValue, last.mValue, (ai_real) ( - (curTime-first.mTime) / (last.mTime-first.mTime))); + curPosition = Interpolate(first.mValue, last.mValue, (ai_real)((curTime - first.mTime) / (last.mTime - first.mTime))); } - if (targetObjPos->size() != nextTargetObjPos-1) + if (targetObjPos->size() != nextTargetObjPos - 1) ++nextTargetObjPos; } - if (nextObjPos >= objPos->size()-1 && - nextTargetObjPos >= targetObjPos->size()-1) - { + if (nextObjPos >= objPos->size() - 1 && + nextTargetObjPos >= targetObjPos->size() - 1) { // We reached the very last keyframe reachedEnd = true; } } // ------------------------------------------------------------------------------------------------ -void TargetAnimationHelper::SetTargetAnimationChannel ( - const std::vector* _targetPositions) -{ - ai_assert(NULL != _targetPositions); +void TargetAnimationHelper::SetTargetAnimationChannel( + const std::vector *_targetPositions) { + ai_assert(nullptr != _targetPositions); + targetPositions = _targetPositions; } // ------------------------------------------------------------------------------------------------ -void TargetAnimationHelper::SetMainAnimationChannel ( - const std::vector* _objectPositions) -{ - ai_assert(NULL != _objectPositions); +void TargetAnimationHelper::SetMainAnimationChannel( + const std::vector *_objectPositions) { + ai_assert(nullptr != _objectPositions); + objectPositions = _objectPositions; } // ------------------------------------------------------------------------------------------------ void TargetAnimationHelper::SetFixedMainAnimationChannel( - const aiVector3D& fixed) -{ - objectPositions = NULL; // just to avoid confusion + const aiVector3D &fixed) { + objectPositions = nullptr; // just to avoid confusion fixedMain = fixed; } // ------------------------------------------------------------------------------------------------ -void TargetAnimationHelper::Process(std::vector* distanceTrack) -{ - ai_assert(NULL != targetPositions && NULL != distanceTrack); +void TargetAnimationHelper::Process(std::vector *distanceTrack) { + ai_assert(nullptr != targetPositions); + ai_assert(nullptr != distanceTrack); // TODO: in most cases we won't need the extra array - std::vector real; + std::vector real; - std::vector* fill = (distanceTrack == objectPositions ? &real : distanceTrack); - fill->reserve(std::max( objectPositions->size(), targetPositions->size() )); + std::vector *fill = (distanceTrack == objectPositions ? &real : distanceTrack); + fill->reserve(std::max(objectPositions->size(), targetPositions->size())); // Iterate through all object keys and interpolate their values if necessary. // Then get the corresponding target position, compute the difference @@ -214,28 +196,24 @@ void TargetAnimationHelper::Process(std::vector* distanceTrack) // that rotates the base vector of the object coordinate system at that time // to match the diff vector. - KeyIterator iter(objectPositions,targetPositions,&fixedMain); - for (;!iter.Finished();++iter) - { - const aiVector3D& position = iter.GetCurPosition(); - const aiVector3D& tposition = iter.GetCurTargetPosition(); + KeyIterator iter(objectPositions, targetPositions, &fixedMain); + for (; !iter.Finished(); ++iter) { + const aiVector3D &position = iter.GetCurPosition(); + const aiVector3D &tposition = iter.GetCurTargetPosition(); // diff vector aiVector3D diff = tposition - position; ai_real f = diff.Length(); // output distance vector - if (f) - { + if (f) { fill->push_back(aiVectorKey()); - aiVectorKey& v = fill->back(); - v.mTime = iter.GetCurTime(); + aiVectorKey &v = fill->back(); + v.mTime = iter.GetCurTime(); v.mValue = diff; diff /= f; - } - else - { + } else { // FIXME: handle this } diff --git a/code/Common/TargetAnimation.h b/code/Common/TargetAnimation.h index 5b9c1881d..0854450bf 100644 --- a/code/Common/TargetAnimation.h +++ b/code/Common/TargetAnimation.h @@ -48,9 +48,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include -namespace Assimp { - - +namespace Assimp { // --------------------------------------------------------------------------- /** Helper class to iterate through all keys in an animation channel. @@ -58,55 +56,44 @@ namespace Assimp { * Missing tracks are interpolated. This is a helper class for * TargetAnimationHelper, but it can be freely used for other purposes. */ -class KeyIterator -{ +class KeyIterator { public: - - // ------------------------------------------------------------------ /** Constructs a new key iterator * - * @param _objPos Object position track. May be NULL. - * @param _targetObjPos Target object position track. May be NULL. + * @param _objPos Object position track. May be nullptr. + * @param _targetObjPos Target object position track. May be nullptr. * @param defaultObjectPos Default object position to be used if - * no animated track is available. May be NULL. + * no animated track is available. May be nullptr. * @param defaultTargetPos Default target position to be used if - * no animated track is available. May be NULL. + * no animated track is available. May be nullptr. */ - KeyIterator(const std::vector* _objPos, - const std::vector* _targetObjPos, - const aiVector3D* defaultObjectPos = NULL, - const aiVector3D* defaultTargetPos = NULL); + KeyIterator(const std::vector *_objPos, + const std::vector *_targetObjPos, + const aiVector3D *defaultObjectPos = nullptr, + const aiVector3D *defaultTargetPos = nullptr); // ------------------------------------------------------------------ /** Returns true if all keys have been processed */ - bool Finished() const - {return reachedEnd;} + bool Finished() const { return reachedEnd; } // ------------------------------------------------------------------ /** Increment the iterator */ void operator++(); - inline void operator++(int) - {return ++(*this);} - - + inline void operator++(int) { return ++(*this); } // ------------------------------------------------------------------ /** Getters to retrieve the current state of the iterator */ - inline const aiVector3D& GetCurPosition() const - {return curPosition;} + inline const aiVector3D &GetCurPosition() const { return curPosition; } - inline const aiVector3D& GetCurTargetPosition() const - {return curTargetPosition;} + inline const aiVector3D &GetCurTargetPosition() const { return curTargetPosition; } - inline double GetCurTime() const - {return curTime;} + inline double GetCurTime() const { return curTime; } private: - //! Did we reach the end? bool reachedEnd; @@ -116,10 +103,10 @@ private: double curTime; //! Input tracks and the next key to process - const std::vector* objPos,*targetObjPos; + const std::vector *objPos, *targetObjPos; unsigned int nextObjPos, nextTargetObjPos; - std::vector defaultObjPos,defaultTargetObjPos; + std::vector defaultObjPos, defaultTargetObjPos; }; // --------------------------------------------------------------------------- @@ -130,15 +117,13 @@ private: * channel for the camera/spot light itself and a separate position * animation channels specifying the position of the camera/spot light * look-at target */ -class TargetAnimationHelper -{ +class TargetAnimationHelper { public: - - TargetAnimationHelper() - : targetPositions (NULL) - , objectPositions (NULL) - {} - + TargetAnimationHelper() : + targetPositions(nullptr), + objectPositions(nullptr) { + // empty + } // ------------------------------------------------------------------ /** Sets the target animation channel @@ -147,37 +132,30 @@ public: * target at a specific position. * * @param targetPositions Translation channel*/ - void SetTargetAnimationChannel (const - std::vector* targetPositions); - + void SetTargetAnimationChannel(const std::vector *targetPositions); // ------------------------------------------------------------------ /** Sets the main animation channel * * @param objectPositions Translation channel */ - void SetMainAnimationChannel ( const - std::vector* objectPositions); + void SetMainAnimationChannel(const std::vector *objectPositions); // ------------------------------------------------------------------ /** Sets the main animation channel to a fixed value * * @param fixed Fixed value for the main animation channel*/ - void SetFixedMainAnimationChannel(const aiVector3D& fixed); - + void SetFixedMainAnimationChannel(const aiVector3D &fixed); // ------------------------------------------------------------------ /** Computes final animation channels - * @param distanceTrack Receive camera translation keys ... != NULL. */ - void Process( std::vector* distanceTrack ); - + * @param distanceTrack Receive camera translation keys ... != nullptr. */ + void Process(std::vector *distanceTrack); private: - - const std::vector* targetPositions,*objectPositions; + const std::vector *targetPositions, *objectPositions; aiVector3D fixedMain; }; - -} // ! end namespace Assimp +} // namespace Assimp #endif // include guard diff --git a/code/Common/VertexTriangleAdjacency.cpp b/code/Common/VertexTriangleAdjacency.cpp index e588dc2a4..591c8b584 100644 --- a/code/Common/VertexTriangleAdjacency.cpp +++ b/code/Common/VertexTriangleAdjacency.cpp @@ -52,46 +52,44 @@ using namespace Assimp; // ------------------------------------------------------------------------------------------------ VertexTriangleAdjacency::VertexTriangleAdjacency(aiFace *pcFaces, - unsigned int iNumFaces, - unsigned int iNumVertices /*= 0*/, - bool bComputeNumTriangles /*= false*/) -{ + unsigned int iNumFaces, + unsigned int iNumVertices /*= 0*/, + bool bComputeNumTriangles /*= false*/) { // compute the number of referenced vertices if it wasn't specified by the caller - const aiFace* const pcFaceEnd = pcFaces + iNumFaces; - if (0 == iNumVertices) { - for (aiFace* pcFace = pcFaces; pcFace != pcFaceEnd; ++pcFace) { - ai_assert( nullptr != pcFace ); + const aiFace *const pcFaceEnd = pcFaces + iNumFaces; + if (0 == iNumVertices) { + for (aiFace *pcFace = pcFaces; pcFace != pcFaceEnd; ++pcFace) { + ai_assert(nullptr != pcFace); ai_assert(3 == pcFace->mNumIndices); - iNumVertices = std::max(iNumVertices,pcFace->mIndices[0]); - iNumVertices = std::max(iNumVertices,pcFace->mIndices[1]); - iNumVertices = std::max(iNumVertices,pcFace->mIndices[2]); + iNumVertices = std::max(iNumVertices, pcFace->mIndices[0]); + iNumVertices = std::max(iNumVertices, pcFace->mIndices[1]); + iNumVertices = std::max(iNumVertices, pcFace->mIndices[2]); } } mNumVertices = iNumVertices + 1; - unsigned int* pi; + unsigned int *pi; // allocate storage - if (bComputeNumTriangles) { - pi = mLiveTriangles = new unsigned int[iNumVertices+1]; - ::memset(mLiveTriangles,0,sizeof(unsigned int)*(iNumVertices+1)); - mOffsetTable = new unsigned int[iNumVertices+2]+1; + if (bComputeNumTriangles) { + pi = mLiveTriangles = new unsigned int[iNumVertices + 1]; + ::memset(mLiveTriangles, 0, sizeof(unsigned int) * (iNumVertices + 1)); + mOffsetTable = new unsigned int[iNumVertices + 2] + 1; } else { - pi = mOffsetTable = new unsigned int[iNumVertices+2]+1; - ::memset(mOffsetTable,0,sizeof(unsigned int)*(iNumVertices+1)); - mLiveTriangles = NULL; // important, otherwise the d'tor would crash + pi = mOffsetTable = new unsigned int[iNumVertices + 2] + 1; + ::memset(mOffsetTable, 0, sizeof(unsigned int) * (iNumVertices + 1)); + mLiveTriangles = nullptr; // important, otherwise the d'tor would crash } // get a pointer to the end of the buffer - unsigned int* piEnd = pi+iNumVertices; + unsigned int *piEnd = pi + iNumVertices; *piEnd++ = 0u; // first pass: compute the number of faces referencing each vertex - for (aiFace* pcFace = pcFaces; pcFace != pcFaceEnd; ++pcFace) - { + for (aiFace *pcFace = pcFaces; pcFace != pcFaceEnd; ++pcFace) { unsigned nind = pcFace->mNumIndices; - unsigned * ind = pcFace->mIndices; + unsigned *ind = pcFace->mIndices; if (nind > 0) pi[ind[0]]++; if (nind > 1) pi[ind[1]]++; if (nind > 2) pi[ind[2]]++; @@ -99,8 +97,8 @@ VertexTriangleAdjacency::VertexTriangleAdjacency(aiFace *pcFaces, // second pass: compute the final offset table unsigned int iSum = 0; - unsigned int* piCurOut = this->mOffsetTable; - for (unsigned int* piCur = pi; piCur != piEnd;++piCur,++piCurOut) { + unsigned int *piCurOut = this->mOffsetTable; + for (unsigned int *piCur = pi; piCur != piEnd; ++piCur, ++piCurOut) { unsigned int iLastSum = iSum; iSum += *piCur; @@ -111,9 +109,9 @@ VertexTriangleAdjacency::VertexTriangleAdjacency(aiFace *pcFaces, // third pass: compute the final table this->mAdjacencyTable = new unsigned int[iSum]; iSum = 0; - for (aiFace* pcFace = pcFaces; pcFace != pcFaceEnd; ++pcFace,++iSum) { + for (aiFace *pcFace = pcFaces; pcFace != pcFaceEnd; ++pcFace, ++iSum) { unsigned nind = pcFace->mNumIndices; - unsigned * ind = pcFace->mIndices; + unsigned *ind = pcFace->mIndices; if (nind > 0) mAdjacencyTable[pi[ind[0]]++] = iSum; if (nind > 1) mAdjacencyTable[pi[ind[1]]++] = iSum; @@ -125,8 +123,7 @@ VertexTriangleAdjacency::VertexTriangleAdjacency(aiFace *pcFaces, *mOffsetTable = 0u; } // ------------------------------------------------------------------------------------------------ -VertexTriangleAdjacency::~VertexTriangleAdjacency() -{ +VertexTriangleAdjacency::~VertexTriangleAdjacency() { // delete allocated storage delete[] mOffsetTable; delete[] mAdjacencyTable; diff --git a/code/Common/ZipArchiveIOSystem.cpp b/code/Common/ZipArchiveIOSystem.cpp index 6ad10e54a..f55f9ff53 100644 --- a/code/Common/ZipArchiveIOSystem.cpp +++ b/code/Common/ZipArchiveIOSystem.cpp @@ -248,15 +248,18 @@ ZipFile::~ZipFile() { size_t ZipFile::Read(void *pvBuffer, size_t pSize, size_t pCount) { // Should be impossible ai_assert(m_Buffer != nullptr); - ai_assert(NULL != pvBuffer && 0 != pSize && 0 != pCount); + ai_assert(nullptr != pvBuffer); + ai_assert(0 != pSize); + ai_assert(0 != pCount); // Clip down to file size size_t byteSize = pSize * pCount; if ((byteSize + m_SeekPtr) > m_Size) { pCount = (m_Size - m_SeekPtr) / pSize; byteSize = pSize * pCount; - if (byteSize == 0) + if (byteSize == 0) { return 0; + } } std::memcpy(pvBuffer, m_Buffer.get() + m_SeekPtr, byteSize); diff --git a/code/Material/MaterialSystem.cpp b/code/Material/MaterialSystem.cpp index f75fa0126..e83ab97af 100644 --- a/code/Material/MaterialSystem.cpp +++ b/code/Material/MaterialSystem.cpp @@ -44,76 +44,73 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * @brief Implementation of the material system of the library */ -#include -#include -#include #include "MaterialSystem.h" -#include +#include +#include +#include #include +#include #include using namespace Assimp; // ------------------------------------------------------------------------------------------------ // Get a specific property from a material -aiReturn aiGetMaterialProperty(const aiMaterial* pMat, - const char* pKey, - unsigned int type, - unsigned int index, - const aiMaterialProperty** pPropOut) -{ - ai_assert( pMat != NULL ); - ai_assert( pKey != NULL ); - ai_assert( pPropOut != NULL ); +aiReturn aiGetMaterialProperty(const aiMaterial *pMat, + const char *pKey, + unsigned int type, + unsigned int index, + const aiMaterialProperty **pPropOut) { + ai_assert(pMat != nullptr); + ai_assert(pKey != nullptr); + ai_assert(pPropOut != nullptr); /* Just search for a property with exactly this name .. * could be improved by hashing, but it's possibly * no worth the effort (we're bound to C structures, * thus std::map or derivates are not applicable. */ - for ( unsigned int i = 0; i < pMat->mNumProperties; ++i ) { - aiMaterialProperty* prop = pMat->mProperties[i]; + for (unsigned int i = 0; i < pMat->mNumProperties; ++i) { + aiMaterialProperty *prop = pMat->mProperties[i]; if (prop /* just for safety ... */ - && 0 == strcmp( prop->mKey.data, pKey ) - && (UINT_MAX == type || prop->mSemantic == type) /* UINT_MAX is a wild-card, but this is undocumented :-) */ - && (UINT_MAX == index || prop->mIndex == index)) - { + && 0 == strcmp(prop->mKey.data, pKey) && (UINT_MAX == type || prop->mSemantic == type) /* UINT_MAX is a wild-card, but this is undocumented :-) */ + && (UINT_MAX == index || prop->mIndex == index)) { *pPropOut = pMat->mProperties[i]; return AI_SUCCESS; } } - *pPropOut = NULL; + *pPropOut = nullptr; return AI_FAILURE; } // ------------------------------------------------------------------------------------------------ // Get an array of floating-point values from the material. -aiReturn aiGetMaterialFloatArray(const aiMaterial* pMat, - const char* pKey, - unsigned int type, - unsigned int index, - ai_real* pOut, - unsigned int* pMax) -{ - ai_assert( pOut != nullptr ); - ai_assert( pMat != nullptr ); +aiReturn aiGetMaterialFloatArray(const aiMaterial *pMat, + const char *pKey, + unsigned int type, + unsigned int index, + ai_real *pOut, + unsigned int *pMax) { + ai_assert(pOut != nullptr); + ai_assert(pMat != nullptr); - const aiMaterialProperty* prop; - aiGetMaterialProperty(pMat,pKey,type,index, (const aiMaterialProperty**) &prop); - if ( nullptr == prop) { + const aiMaterialProperty *prop; + aiGetMaterialProperty(pMat, pKey, type, index, (const aiMaterialProperty **)&prop); + if (nullptr == prop) { return AI_FAILURE; } // data is given in floats, convert to ai_real unsigned int iWrite = 0; - if( aiPTI_Float == prop->mType || aiPTI_Buffer == prop->mType) { + if (aiPTI_Float == prop->mType || aiPTI_Buffer == prop->mType) { iWrite = prop->mDataLength / sizeof(float); if (pMax) { - iWrite = std::min(*pMax,iWrite); ; + iWrite = std::min(*pMax, iWrite); + ; } for (unsigned int a = 0; a < iWrite; ++a) { - pOut[ a ] = static_cast ( reinterpret_cast(prop->mData)[a] ); + pOut[a] = static_cast(reinterpret_cast(prop->mData)[a]); } if (pMax) { @@ -121,26 +118,28 @@ aiReturn aiGetMaterialFloatArray(const aiMaterial* pMat, } } // data is given in doubles, convert to float - else if( aiPTI_Double == prop->mType) { + else if (aiPTI_Double == prop->mType) { iWrite = prop->mDataLength / sizeof(double); if (pMax) { - iWrite = std::min(*pMax,iWrite); ; + iWrite = std::min(*pMax, iWrite); + ; } - for (unsigned int a = 0; a < iWrite;++a) { - pOut[a] = static_cast ( reinterpret_cast(prop->mData)[a] ); + for (unsigned int a = 0; a < iWrite; ++a) { + pOut[a] = static_cast(reinterpret_cast(prop->mData)[a]); } if (pMax) { *pMax = iWrite; } } // data is given in ints, convert to float - else if( aiPTI_Integer == prop->mType) { + else if (aiPTI_Integer == prop->mType) { iWrite = prop->mDataLength / sizeof(int32_t); if (pMax) { - iWrite = std::min(*pMax,iWrite); ; + iWrite = std::min(*pMax, iWrite); + ; } - for (unsigned int a = 0; a < iWrite;++a) { - pOut[a] = static_cast ( reinterpret_cast(prop->mData)[a] ); + for (unsigned int a = 0; a < iWrite; ++a) { + pOut[a] = static_cast(reinterpret_cast(prop->mData)[a]); } if (pMax) { *pMax = iWrite; @@ -153,16 +152,16 @@ aiReturn aiGetMaterialFloatArray(const aiMaterial* pMat, } // strings are zero-terminated with a 32 bit length prefix, so this is safe const char *cur = prop->mData + 4; - ai_assert( prop->mDataLength >= 5 ); - ai_assert( !prop->mData[ prop->mDataLength - 1 ] ); - for ( unsigned int a = 0; ;++a) { - cur = fast_atoreal_move(cur,pOut[a]); - if ( a==iWrite-1 ) { + ai_assert(prop->mDataLength >= 5); + ai_assert(!prop->mData[prop->mDataLength - 1]); + for (unsigned int a = 0;; ++a) { + cur = fast_atoreal_move(cur, pOut[a]); + if (a == iWrite - 1) { break; } - if ( !IsSpace(*cur) ) { + if (!IsSpace(*cur)) { ASSIMP_LOG_ERROR("Material property" + std::string(pKey) + - " is a string; failed to parse a float array out of it."); + " is a string; failed to parse a float array out of it."); return AI_FAILURE; } } @@ -176,36 +175,34 @@ aiReturn aiGetMaterialFloatArray(const aiMaterial* pMat, // ------------------------------------------------------------------------------------------------ // Get an array if integers from the material -aiReturn aiGetMaterialIntegerArray(const aiMaterial* pMat, - const char* pKey, - unsigned int type, - unsigned int index, - int* pOut, - unsigned int* pMax) -{ - ai_assert( pOut != NULL ); - ai_assert( pMat != NULL ); +aiReturn aiGetMaterialIntegerArray(const aiMaterial *pMat, + const char *pKey, + unsigned int type, + unsigned int index, + int *pOut, + unsigned int *pMax) { + ai_assert(pOut != nullptr); + ai_assert(pMat != nullptr); - const aiMaterialProperty* prop; - aiGetMaterialProperty(pMat,pKey,type,index,(const aiMaterialProperty**) &prop); + const aiMaterialProperty *prop; + aiGetMaterialProperty(pMat, pKey, type, index, (const aiMaterialProperty **)&prop); if (!prop) { return AI_FAILURE; } // data is given in ints, simply copy it unsigned int iWrite = 0; - if( aiPTI_Integer == prop->mType || aiPTI_Buffer == prop->mType) { + if (aiPTI_Integer == prop->mType || aiPTI_Buffer == prop->mType) { iWrite = std::max(static_cast(prop->mDataLength / sizeof(int32_t)), 1u); if (pMax) { - iWrite = std::min(*pMax,iWrite); + iWrite = std::min(*pMax, iWrite); } if (1 == prop->mDataLength) { // bool type, 1 byte *pOut = static_cast(*prop->mData); - } - else { - for (unsigned int a = 0; a < iWrite;++a) { - pOut[a] = static_cast(reinterpret_cast(prop->mData)[a]); + } else { + for (unsigned int a = 0; a < iWrite; ++a) { + pOut[a] = static_cast(reinterpret_cast(prop->mData)[a]); } } if (pMax) { @@ -213,35 +210,36 @@ aiReturn aiGetMaterialIntegerArray(const aiMaterial* pMat, } } // data is given in floats convert to int - else if( aiPTI_Float == prop->mType) { + else if (aiPTI_Float == prop->mType) { iWrite = prop->mDataLength / sizeof(float); if (pMax) { - iWrite = std::min(*pMax,iWrite); ; + iWrite = std::min(*pMax, iWrite); + ; } - for (unsigned int a = 0; a < iWrite;++a) { - pOut[a] = static_cast(reinterpret_cast(prop->mData)[a]); + for (unsigned int a = 0; a < iWrite; ++a) { + pOut[a] = static_cast(reinterpret_cast(prop->mData)[a]); } if (pMax) { *pMax = iWrite; } } // it is a string ... no way to read something out of this - else { + else { if (pMax) { iWrite = *pMax; } // strings are zero-terminated with a 32 bit length prefix, so this is safe - const char *cur = prop->mData+4; - ai_assert( prop->mDataLength >= 5 ); - ai_assert( !prop->mData[ prop->mDataLength - 1 ] ); - for (unsigned int a = 0; ;++a) { - pOut[a] = strtol10(cur,&cur); - if(a==iWrite-1) { + const char *cur = prop->mData + 4; + ai_assert(prop->mDataLength >= 5); + ai_assert(!prop->mData[prop->mDataLength - 1]); + for (unsigned int a = 0;; ++a) { + pOut[a] = strtol10(cur, &cur); + if (a == iWrite - 1) { break; } - if(!IsSpace(*cur)) { + if (!IsSpace(*cur)) { ASSIMP_LOG_ERROR("Material property" + std::string(pKey) + - " is a string; failed to parse an integer array out of it."); + " is a string; failed to parse an integer array out of it."); return AI_FAILURE; } } @@ -255,14 +253,13 @@ aiReturn aiGetMaterialIntegerArray(const aiMaterial* pMat, // ------------------------------------------------------------------------------------------------ // Get a color (3 or 4 floats) from the material -aiReturn aiGetMaterialColor(const aiMaterial* pMat, - const char* pKey, - unsigned int type, - unsigned int index, - aiColor4D* pOut) -{ +aiReturn aiGetMaterialColor(const aiMaterial *pMat, + const char *pKey, + unsigned int type, + unsigned int index, + aiColor4D *pOut) { unsigned int iMax = 4; - const aiReturn eRet = aiGetMaterialFloatArray(pMat,pKey,type,index,(ai_real*)pOut,&iMax); + const aiReturn eRet = aiGetMaterialFloatArray(pMat, pKey, type, index, (ai_real *)pOut, &iMax); // if no alpha channel is defined: set it to 1.0 if (3 == iMax) { @@ -274,46 +271,43 @@ aiReturn aiGetMaterialColor(const aiMaterial* pMat, // ------------------------------------------------------------------------------------------------ // Get a aiUVTransform (5 floats) from the material -aiReturn aiGetMaterialUVTransform(const aiMaterial* pMat, - const char* pKey, - unsigned int type, - unsigned int index, - aiUVTransform* pOut) -{ +aiReturn aiGetMaterialUVTransform(const aiMaterial *pMat, + const char *pKey, + unsigned int type, + unsigned int index, + aiUVTransform *pOut) { unsigned int iMax = 5; - return aiGetMaterialFloatArray(pMat,pKey,type,index,(ai_real*)pOut,&iMax); + return aiGetMaterialFloatArray(pMat, pKey, type, index, (ai_real *)pOut, &iMax); } // ------------------------------------------------------------------------------------------------ // Get a string from the material -aiReturn aiGetMaterialString(const aiMaterial* pMat, - const char* pKey, - unsigned int type, - unsigned int index, - aiString* pOut) -{ - ai_assert (pOut != NULL); +aiReturn aiGetMaterialString(const aiMaterial *pMat, + const char *pKey, + unsigned int type, + unsigned int index, + aiString *pOut) { + ai_assert(pOut != nullptr); - const aiMaterialProperty* prop; - aiGetMaterialProperty(pMat,pKey,type,index,(const aiMaterialProperty**)&prop); + const aiMaterialProperty *prop; + aiGetMaterialProperty(pMat, pKey, type, index, (const aiMaterialProperty **)&prop); if (!prop) { return AI_FAILURE; } - if( aiPTI_String == prop->mType) { - ai_assert(prop->mDataLength>=5); + if (aiPTI_String == prop->mType) { + ai_assert(prop->mDataLength >= 5); // The string is stored as 32 but length prefix followed by zero-terminated UTF8 data - pOut->length = static_cast(*reinterpret_cast(prop->mData)); + pOut->length = static_cast(*reinterpret_cast(prop->mData)); - ai_assert( pOut->length+1+4==prop->mDataLength ); - ai_assert( !prop->mData[ prop->mDataLength - 1 ] ); - memcpy(pOut->data,prop->mData+4,pOut->length+1); - } - else { + ai_assert(pOut->length + 1 + 4 == prop->mDataLength); + ai_assert(!prop->mData[prop->mDataLength - 1]); + memcpy(pOut->data, prop->mData + 4, pOut->length + 1); + } else { // TODO - implement lexical cast as well ASSIMP_LOG_ERROR("Material property" + std::string(pKey) + - " was found, but is no string" ); + " was found, but is no string"); return AI_FAILURE; } return AI_SUCCESS; @@ -321,94 +315,87 @@ aiReturn aiGetMaterialString(const aiMaterial* pMat, // ------------------------------------------------------------------------------------------------ // Get the number of textures on a particular texture stack -unsigned int aiGetMaterialTextureCount(const C_STRUCT aiMaterial* pMat, - C_ENUM aiTextureType type) -{ - ai_assert (pMat != NULL); +unsigned int aiGetMaterialTextureCount(const C_STRUCT aiMaterial *pMat, C_ENUM aiTextureType type) { + ai_assert(pMat != nullptr); // Textures are always stored with ascending indices (ValidateDS provides a check, so we don't need to do it again) unsigned int max = 0; - for (unsigned int i = 0; i < pMat->mNumProperties;++i) { - aiMaterialProperty* prop = pMat->mProperties[i]; + for (unsigned int i = 0; i < pMat->mNumProperties; ++i) { + aiMaterialProperty *prop = pMat->mProperties[i]; - if ( prop /* just a sanity check ... */ - && 0 == strcmp(prop->mKey.data, _AI_MATKEY_TEXTURE_BASE) && static_cast < aiTextureType>(prop->mSemantic) == type) { + if (prop /* just a sanity check ... */ + && 0 == strcmp(prop->mKey.data, _AI_MATKEY_TEXTURE_BASE) && static_cast(prop->mSemantic) == type) { - max = std::max(max,prop->mIndex+1); + max = std::max(max, prop->mIndex + 1); } } return max; } // ------------------------------------------------------------------------------------------------ -aiReturn aiGetMaterialTexture(const C_STRUCT aiMaterial* mat, - aiTextureType type, - unsigned int index, - C_STRUCT aiString* path, - aiTextureMapping* _mapping /*= NULL*/, - unsigned int* uvindex /*= NULL*/, - ai_real* blend /*= NULL*/, - aiTextureOp* op /*= NULL*/, - aiTextureMapMode* mapmode /*= NULL*/, - unsigned int* flags /*= NULL*/ - ) -{ - ai_assert( NULL != mat ); - ai_assert( NULL != path ); +aiReturn aiGetMaterialTexture(const C_STRUCT aiMaterial *mat, + aiTextureType type, + unsigned int index, + C_STRUCT aiString *path, + aiTextureMapping *_mapping /*= nullptr*/, + unsigned int *uvindex /*= nullptr*/, + ai_real *blend /*= nullptr*/, + aiTextureOp *op /*= nullptr*/, + aiTextureMapMode *mapmode /*= nullptr*/, + unsigned int *flags /*= nullptr*/ +) { + ai_assert(nullptr != mat); + ai_assert(nullptr != path); // Get the path to the texture - if (AI_SUCCESS != aiGetMaterialString(mat,AI_MATKEY_TEXTURE(type,index),path)) { + if (AI_SUCCESS != aiGetMaterialString(mat, AI_MATKEY_TEXTURE(type, index), path)) { return AI_FAILURE; } // Determine mapping type int mapping_ = static_cast(aiTextureMapping_UV); - aiGetMaterialInteger(mat,AI_MATKEY_MAPPING(type,index), &mapping_); + aiGetMaterialInteger(mat, AI_MATKEY_MAPPING(type, index), &mapping_); aiTextureMapping mapping = static_cast(mapping_); if (_mapping) *_mapping = mapping; // Get UV index - if (aiTextureMapping_UV == mapping && uvindex) { - aiGetMaterialInteger(mat,AI_MATKEY_UVWSRC(type,index),(int*)uvindex); + if (aiTextureMapping_UV == mapping && uvindex) { + aiGetMaterialInteger(mat, AI_MATKEY_UVWSRC(type, index), (int *)uvindex); } // Get blend factor - if (blend) { - aiGetMaterialFloat(mat,AI_MATKEY_TEXBLEND(type,index),blend); + if (blend) { + aiGetMaterialFloat(mat, AI_MATKEY_TEXBLEND(type, index), blend); } // Get texture operation - if (op){ - aiGetMaterialInteger(mat,AI_MATKEY_TEXOP(type,index),(int*)op); + if (op) { + aiGetMaterialInteger(mat, AI_MATKEY_TEXOP(type, index), (int *)op); } // Get texture mapping modes - if (mapmode) { - aiGetMaterialInteger(mat,AI_MATKEY_MAPPINGMODE_U(type,index),(int*)&mapmode[0]); - aiGetMaterialInteger(mat,AI_MATKEY_MAPPINGMODE_V(type,index),(int*)&mapmode[1]); + if (mapmode) { + aiGetMaterialInteger(mat, AI_MATKEY_MAPPINGMODE_U(type, index), (int *)&mapmode[0]); + aiGetMaterialInteger(mat, AI_MATKEY_MAPPINGMODE_V(type, index), (int *)&mapmode[1]); } // Get texture flags - if (flags){ - aiGetMaterialInteger(mat,AI_MATKEY_TEXFLAGS(type,index),(int*)flags); + if (flags) { + aiGetMaterialInteger(mat, AI_MATKEY_TEXFLAGS(type, index), (int *)flags); } return AI_SUCCESS; } - static const unsigned int DefaultNumAllocated = 5; // ------------------------------------------------------------------------------------------------ // Construction. Actually the one and only way to get an aiMaterial instance -aiMaterial::aiMaterial() -: mProperties( nullptr ) -, mNumProperties( 0 ) -, mNumAllocated( DefaultNumAllocated ) { +aiMaterial::aiMaterial() : + mProperties(nullptr), mNumProperties(0), mNumAllocated(DefaultNumAllocated) { // Allocate 5 entries by default - mProperties = new aiMaterialProperty*[ DefaultNumAllocated ]; + mProperties = new aiMaterialProperty *[DefaultNumAllocated]; } // ------------------------------------------------------------------------------------------------ -aiMaterial::~aiMaterial() -{ +aiMaterial::~aiMaterial() { Clear(); delete[] mProperties; @@ -423,11 +410,10 @@ aiString aiMaterial::GetName() { } // ------------------------------------------------------------------------------------------------ -void aiMaterial::Clear() -{ - for ( unsigned int i = 0; i < mNumProperties; ++i ) { +void aiMaterial::Clear() { + for (unsigned int i = 0; i < mNumProperties; ++i) { // delete this entry - delete mProperties[ i ]; + delete mProperties[i]; AI_DEBUG_INVALIDATE_PTR(mProperties[i]); } mNumProperties = 0; @@ -436,23 +422,21 @@ void aiMaterial::Clear() } // ------------------------------------------------------------------------------------------------ -aiReturn aiMaterial::RemoveProperty ( const char* pKey,unsigned int type, unsigned int index ) -{ - ai_assert( nullptr != pKey ); +aiReturn aiMaterial::RemoveProperty(const char *pKey, unsigned int type, unsigned int index) { + ai_assert(nullptr != pKey); - for (unsigned int i = 0; i < mNumProperties;++i) { - aiMaterialProperty* prop = mProperties[i]; + for (unsigned int i = 0; i < mNumProperties; ++i) { + aiMaterialProperty *prop = mProperties[i]; - if (prop && !strcmp( prop->mKey.data, pKey ) && - prop->mSemantic == type && prop->mIndex == index) - { + if (prop && !strcmp(prop->mKey.data, pKey) && + prop->mSemantic == type && prop->mIndex == index) { // Delete this entry delete mProperties[i]; // collapse the array behind --. --mNumProperties; - for (unsigned int a = i; a < mNumProperties;++a) { - mProperties[a] = mProperties[a+1]; + for (unsigned int a = i; a < mNumProperties; ++a) { + mProperties[a] = mProperties[a + 1]; } return AI_SUCCESS; } @@ -462,29 +446,27 @@ aiReturn aiMaterial::RemoveProperty ( const char* pKey,unsigned int type, unsign } // ------------------------------------------------------------------------------------------------ -aiReturn aiMaterial::AddBinaryProperty (const void* pInput, - unsigned int pSizeInBytes, - const char* pKey, - unsigned int type, - unsigned int index, - aiPropertyTypeInfo pType - ) -{ - ai_assert( pInput != nullptr ); - ai_assert(pKey != nullptr ); - ai_assert( 0 != pSizeInBytes ); +aiReturn aiMaterial::AddBinaryProperty(const void *pInput, + unsigned int pSizeInBytes, + const char *pKey, + unsigned int type, + unsigned int index, + aiPropertyTypeInfo pType) { + ai_assert(pInput != nullptr); + ai_assert(pKey != nullptr); + ai_assert(0 != pSizeInBytes); - if ( 0 == pSizeInBytes ) { - return AI_FAILURE; + if (0 == pSizeInBytes) { + return AI_FAILURE; } // first search the list whether there is already an entry with this key - unsigned int iOutIndex( UINT_MAX ); - for ( unsigned int i = 0; i < mNumProperties; ++i ) { - aiMaterialProperty *prop( mProperties[ i ] ); + unsigned int iOutIndex(UINT_MAX); + for (unsigned int i = 0; i < mNumProperties; ++i) { + aiMaterialProperty *prop(mProperties[i]); - if (prop /* just for safety */ && !strcmp( prop->mKey.data, pKey ) && - prop->mSemantic == type && prop->mIndex == index){ + if (prop /* just for safety */ && !strcmp(prop->mKey.data, pKey) && + prop->mSemantic == type && prop->mIndex == index) { delete mProperties[i]; iOutIndex = i; @@ -492,7 +474,7 @@ aiReturn aiMaterial::AddBinaryProperty (const void* pInput, } // Allocate a new material property - aiMaterialProperty* pcNew = new aiMaterialProperty(); + aiMaterialProperty *pcNew = new aiMaterialProperty(); // .. and fill it pcNew->mType = pType; @@ -501,32 +483,32 @@ aiReturn aiMaterial::AddBinaryProperty (const void* pInput, pcNew->mDataLength = pSizeInBytes; pcNew->mData = new char[pSizeInBytes]; - memcpy (pcNew->mData,pInput,pSizeInBytes); + memcpy(pcNew->mData, pInput, pSizeInBytes); - pcNew->mKey.length = static_cast( ::strlen(pKey) ); - ai_assert ( MAXLEN > pcNew->mKey.length); - strcpy( pcNew->mKey.data, pKey ); + pcNew->mKey.length = static_cast(::strlen(pKey)); + ai_assert(MAXLEN > pcNew->mKey.length); + strcpy(pcNew->mKey.data, pKey); - if (UINT_MAX != iOutIndex) { + if (UINT_MAX != iOutIndex) { mProperties[iOutIndex] = pcNew; return AI_SUCCESS; } // resize the array ... double the storage allocated - if (mNumProperties == mNumAllocated) { + if (mNumProperties == mNumAllocated) { const unsigned int iOld = mNumAllocated; mNumAllocated *= 2; - aiMaterialProperty** ppTemp; + aiMaterialProperty **ppTemp; try { - ppTemp = new aiMaterialProperty*[mNumAllocated]; - } catch (std::bad_alloc&) { + ppTemp = new aiMaterialProperty *[mNumAllocated]; + } catch (std::bad_alloc &) { delete pcNew; return AI_OUTOFMEMORY; } // just copy all items over; then replace the old array - memcpy (ppTemp,mProperties,iOld * sizeof(void*)); + memcpy(ppTemp, mProperties, iOld * sizeof(void *)); delete[] mProperties; mProperties = ppTemp; @@ -538,81 +520,76 @@ aiReturn aiMaterial::AddBinaryProperty (const void* pInput, } // ------------------------------------------------------------------------------------------------ -aiReturn aiMaterial::AddProperty (const aiString* pInput, - const char* pKey, - unsigned int type, - unsigned int index) -{ - ai_assert(sizeof(ai_uint32)==4); +aiReturn aiMaterial::AddProperty(const aiString *pInput, + const char *pKey, + unsigned int type, + unsigned int index) { + ai_assert(sizeof(ai_uint32) == 4); return AddBinaryProperty(pInput, - static_cast(pInput->length+1+4), - pKey, - type, - index, - aiPTI_String); + static_cast(pInput->length + 1 + 4), + pKey, + type, + index, + aiPTI_String); } // ------------------------------------------------------------------------------------------------ -uint32_t Assimp::ComputeMaterialHash(const aiMaterial* mat, bool includeMatName /*= false*/) -{ +uint32_t Assimp::ComputeMaterialHash(const aiMaterial *mat, bool includeMatName /*= false*/) { uint32_t hash = 1503; // magic start value, chosen to be my birthday :-) - for ( unsigned int i = 0; i < mat->mNumProperties; ++i ) { - aiMaterialProperty* prop; + for (unsigned int i = 0; i < mat->mNumProperties; ++i) { + aiMaterialProperty *prop; // Exclude all properties whose first character is '?' from the hash // See doc for aiMaterialProperty. - prop = mat->mProperties[ i ]; - if ( nullptr != prop && (includeMatName || prop->mKey.data[0] != '?')) { + prop = mat->mProperties[i]; + if (nullptr != prop && (includeMatName || prop->mKey.data[0] != '?')) { - hash = SuperFastHash(prop->mKey.data,(unsigned int)prop->mKey.length,hash); - hash = SuperFastHash(prop->mData,prop->mDataLength,hash); + hash = SuperFastHash(prop->mKey.data, (unsigned int)prop->mKey.length, hash); + hash = SuperFastHash(prop->mData, prop->mDataLength, hash); // Combine the semantic and the index with the hash - hash = SuperFastHash((const char*)&prop->mSemantic,sizeof(unsigned int),hash); - hash = SuperFastHash((const char*)&prop->mIndex,sizeof(unsigned int),hash); + hash = SuperFastHash((const char *)&prop->mSemantic, sizeof(unsigned int), hash); + hash = SuperFastHash((const char *)&prop->mIndex, sizeof(unsigned int), hash); } } return hash; } // ------------------------------------------------------------------------------------------------ -void aiMaterial::CopyPropertyList(aiMaterial* pcDest, - const aiMaterial* pcSrc - ) -{ - ai_assert(NULL != pcDest); - ai_assert(NULL != pcSrc); +void aiMaterial::CopyPropertyList(aiMaterial *pcDest, + const aiMaterial *pcSrc) { + ai_assert(nullptr != pcDest); + ai_assert(nullptr != pcSrc); unsigned int iOldNum = pcDest->mNumProperties; pcDest->mNumAllocated += pcSrc->mNumAllocated; pcDest->mNumProperties += pcSrc->mNumProperties; - aiMaterialProperty** pcOld = pcDest->mProperties; - pcDest->mProperties = new aiMaterialProperty*[pcDest->mNumAllocated]; + aiMaterialProperty **pcOld = pcDest->mProperties; + pcDest->mProperties = new aiMaterialProperty *[pcDest->mNumAllocated]; - if (iOldNum && pcOld) { - for (unsigned int i = 0; i < iOldNum;++i) { + if (iOldNum && pcOld) { + for (unsigned int i = 0; i < iOldNum; ++i) { pcDest->mProperties[i] = pcOld[i]; } } - if ( pcOld ) { + if (pcOld) { delete[] pcOld; } - for (unsigned int i = iOldNum; i< pcDest->mNumProperties;++i) { - aiMaterialProperty* propSrc = pcSrc->mProperties[i]; + for (unsigned int i = iOldNum; i < pcDest->mNumProperties; ++i) { + aiMaterialProperty *propSrc = pcSrc->mProperties[i]; // search whether we have already a property with this name -> if yes, overwrite it - aiMaterialProperty* prop; - for ( unsigned int q = 0; q < iOldNum; ++q ) { + aiMaterialProperty *prop; + for (unsigned int q = 0; q < iOldNum; ++q) { prop = pcDest->mProperties[q]; - if (prop /* just for safety */ && prop->mKey == propSrc->mKey && prop->mSemantic == propSrc->mSemantic - && prop->mIndex == propSrc->mIndex) { + if (prop /* just for safety */ && prop->mKey == propSrc->mKey && prop->mSemantic == propSrc->mSemantic && prop->mIndex == propSrc->mIndex) { delete prop; // collapse the whole array ... - memmove(&pcDest->mProperties[q],&pcDest->mProperties[q+1],i-q); + memmove(&pcDest->mProperties[q], &pcDest->mProperties[q + 1], i - q); i--; pcDest->mNumProperties--; } @@ -627,6 +604,6 @@ void aiMaterial::CopyPropertyList(aiMaterial* pcDest, prop->mIndex = propSrc->mIndex; prop->mData = new char[propSrc->mDataLength]; - memcpy(prop->mData,propSrc->mData,prop->mDataLength); + memcpy(prop->mData, propSrc->mData, prop->mDataLength); } } diff --git a/code/PostProcessing/CalcTangentsProcess.cpp b/code/PostProcessing/CalcTangentsProcess.cpp index 291205bd8..3ad88972d 100644 --- a/code/PostProcessing/CalcTangentsProcess.cpp +++ b/code/PostProcessing/CalcTangentsProcess.cpp @@ -55,54 +55,49 @@ using namespace Assimp; // ------------------------------------------------------------------------------------------------ // Constructor to be privately used by Importer -CalcTangentsProcess::CalcTangentsProcess() -: configMaxAngle( AI_DEG_TO_RAD(45.f) ) -, configSourceUV( 0 ) { +CalcTangentsProcess::CalcTangentsProcess() : + configMaxAngle(AI_DEG_TO_RAD(45.f)), configSourceUV(0) { // nothing to do here } // ------------------------------------------------------------------------------------------------ // Destructor, private as well -CalcTangentsProcess::~CalcTangentsProcess() -{ +CalcTangentsProcess::~CalcTangentsProcess() { // nothing to do here } // ------------------------------------------------------------------------------------------------ // Returns whether the processing step is present in the given flag field. -bool CalcTangentsProcess::IsActive( unsigned int pFlags) const -{ +bool CalcTangentsProcess::IsActive(unsigned int pFlags) const { return (pFlags & aiProcess_CalcTangentSpace) != 0; } // ------------------------------------------------------------------------------------------------ // Executes the post processing step on the given imported data. -void CalcTangentsProcess::SetupProperties(const Importer* pImp) -{ - ai_assert( NULL != pImp ); +void CalcTangentsProcess::SetupProperties(const Importer *pImp) { + ai_assert(nullptr != pImp); // get the current value of the property - configMaxAngle = pImp->GetPropertyFloat(AI_CONFIG_PP_CT_MAX_SMOOTHING_ANGLE,45.f); - configMaxAngle = std::max(std::min(configMaxAngle,45.0f),0.0f); + configMaxAngle = pImp->GetPropertyFloat(AI_CONFIG_PP_CT_MAX_SMOOTHING_ANGLE, 45.f); + configMaxAngle = std::max(std::min(configMaxAngle, 45.0f), 0.0f); configMaxAngle = AI_DEG_TO_RAD(configMaxAngle); - configSourceUV = pImp->GetPropertyInteger(AI_CONFIG_PP_CT_TEXTURE_CHANNEL_INDEX,0); + configSourceUV = pImp->GetPropertyInteger(AI_CONFIG_PP_CT_TEXTURE_CHANNEL_INDEX, 0); } // ------------------------------------------------------------------------------------------------ // Executes the post processing step on the given imported data. -void CalcTangentsProcess::Execute( aiScene* pScene) -{ - ai_assert( NULL != pScene ); +void CalcTangentsProcess::Execute(aiScene *pScene) { + ai_assert(nullptr != pScene); ASSIMP_LOG_DEBUG("CalcTangentsProcess begin"); bool bHas = false; - for ( unsigned int a = 0; a < pScene->mNumMeshes; a++ ) { - if(ProcessMesh( pScene->mMeshes[a],a))bHas = true; + for (unsigned int a = 0; a < pScene->mNumMeshes; a++) { + if (ProcessMesh(pScene->mMeshes[a], a)) bHas = true; } - if ( bHas ) { + if (bHas) { ASSIMP_LOG_INFO("CalcTangentsProcess finished. Tangents have been calculated"); } else { ASSIMP_LOG_DEBUG("CalcTangentsProcess finished"); @@ -111,8 +106,7 @@ void CalcTangentsProcess::Execute( aiScene* pScene) // ------------------------------------------------------------------------------------------------ // Calculates tangents and bi-tangents for the given mesh -bool CalcTangentsProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex) -{ +bool CalcTangentsProcess::ProcessMesh(aiMesh *pMesh, unsigned int meshIndex) { // we assume that the mesh is still in the verbose vertex format where each face has its own set // of vertices and no vertices are shared between faces. Sadly I don't know any quick test to // assert() it here. @@ -124,54 +118,48 @@ bool CalcTangentsProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex) // If the mesh consists of lines and/or points but not of // triangles or higher-order polygons the normal vectors // are undefined. - if (!(pMesh->mPrimitiveTypes & (aiPrimitiveType_TRIANGLE | aiPrimitiveType_POLYGON))) - { + if (!(pMesh->mPrimitiveTypes & (aiPrimitiveType_TRIANGLE | aiPrimitiveType_POLYGON))) { ASSIMP_LOG_INFO("Tangents are undefined for line and point meshes"); return false; } // what we can check, though, is if the mesh has normals and texture coordinates. That's a requirement - if( pMesh->mNormals == NULL) - { + if (pMesh->mNormals == nullptr) { ASSIMP_LOG_ERROR("Failed to compute tangents; need normals"); return false; } - if( configSourceUV >= AI_MAX_NUMBER_OF_TEXTURECOORDS || !pMesh->mTextureCoords[configSourceUV] ) - { - ASSIMP_LOG_ERROR((Formatter::format("Failed to compute tangents; need UV data in channel"),configSourceUV)); + if (configSourceUV >= AI_MAX_NUMBER_OF_TEXTURECOORDS || !pMesh->mTextureCoords[configSourceUV]) { + ASSIMP_LOG_ERROR((Formatter::format("Failed to compute tangents; need UV data in channel"), configSourceUV)); return false; } const float angleEpsilon = 0.9999f; - std::vector vertexDone( pMesh->mNumVertices, false); + std::vector vertexDone(pMesh->mNumVertices, false); const float qnan = get_qnan(); // create space for the tangents and bitangents pMesh->mTangents = new aiVector3D[pMesh->mNumVertices]; pMesh->mBitangents = new aiVector3D[pMesh->mNumVertices]; - const aiVector3D* meshPos = pMesh->mVertices; - const aiVector3D* meshNorm = pMesh->mNormals; - const aiVector3D* meshTex = pMesh->mTextureCoords[configSourceUV]; - aiVector3D* meshTang = pMesh->mTangents; - aiVector3D* meshBitang = pMesh->mBitangents; + const aiVector3D *meshPos = pMesh->mVertices; + const aiVector3D *meshNorm = pMesh->mNormals; + const aiVector3D *meshTex = pMesh->mTextureCoords[configSourceUV]; + aiVector3D *meshTang = pMesh->mTangents; + aiVector3D *meshBitang = pMesh->mBitangents; // calculate the tangent and bitangent for every face - for( unsigned int a = 0; a < pMesh->mNumFaces; a++) - { - const aiFace& face = pMesh->mFaces[a]; - if (face.mNumIndices < 3) - { + for (unsigned int a = 0; a < pMesh->mNumFaces; a++) { + const aiFace &face = pMesh->mFaces[a]; + if (face.mNumIndices < 3) { // There are less than three indices, thus the tangent vector // is not defined. We are finished with these vertices now, // their tangent vectors are set to qnan. - for (unsigned int i = 0; i < face.mNumIndices;++i) - { + for (unsigned int i = 0; i < face.mNumIndices; ++i) { unsigned int idx = face.mIndices[i]; - vertexDone [idx] = true; - meshTang [idx] = aiVector3D(qnan); - meshBitang [idx] = aiVector3D(qnan); + vertexDone[idx] = true; + meshTang[idx] = aiVector3D(qnan); + meshBitang[idx] = aiVector3D(qnan); } continue; @@ -190,9 +178,11 @@ bool CalcTangentsProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex) float tx = meshTex[p2].x - meshTex[p0].x, ty = meshTex[p2].y - meshTex[p0].y; float dirCorrection = (tx * sy - ty * sx) < 0.0f ? -1.0f : 1.0f; // when t1, t2, t3 in same position in UV space, just use default UV direction. - if ( sx * ty == sy * tx ) { - sx = 0.0; sy = 1.0; - tx = 1.0; ty = 0.0; + if (sx * ty == sy * tx) { + sx = 0.0; + sy = 1.0; + tx = 1.0; + ty = 0.0; } // tangent points in the direction where to positive X axis of the texture coord's would point in model space @@ -206,13 +196,14 @@ bool CalcTangentsProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex) bitangent.z = (w.z * sx - v.z * tx) * dirCorrection; // store for every vertex of that face - for( unsigned int b = 0; b < face.mNumIndices; ++b ) { + for (unsigned int b = 0; b < face.mNumIndices; ++b) { unsigned int p = face.mIndices[b]; // project tangent and bitangent into the plane formed by the vertex' normal aiVector3D localTangent = tangent - meshNorm[p] * (tangent * meshNorm[p]); aiVector3D localBitangent = bitangent - meshNorm[p] * (bitangent * meshNorm[p]); - localTangent.NormalizeSafe(); localBitangent.NormalizeSafe(); + localTangent.NormalizeSafe(); + localBitangent.NormalizeSafe(); // reconstruct tangent/bitangent according to normal and bitangent/tangent when it's infinite or NaN. bool invalid_tangent = is_special_float(localTangent.x) || is_special_float(localTangent.y) || is_special_float(localTangent.z); @@ -228,31 +219,28 @@ bool CalcTangentsProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex) } // and write it into the mesh. - meshTang[ p ] = localTangent; - meshBitang[ p ] = localBitangent; + meshTang[p] = localTangent; + meshBitang[p] = localBitangent; } } - // create a helper to quickly find locally close vertices among the vertex array // FIX: check whether we can reuse the SpatialSort of a previous step - SpatialSort* vertexFinder = NULL; - SpatialSort _vertexFinder; + SpatialSort *vertexFinder = nullptr; + SpatialSort _vertexFinder; float posEpsilon = 10e-6f; - if (shared) - { - std::vector >* avf; - shared->GetProperty(AI_SPP_SPATIAL_SORT,avf); - if (avf) - { - std::pair& blubb = avf->operator [] (meshIndex); + if (shared) { + std::vector> *avf; + shared->GetProperty(AI_SPP_SPATIAL_SORT, avf); + if (avf) { + std::pair &blubb = avf->operator[](meshIndex); vertexFinder = &blubb.first; - posEpsilon = blubb.second;; + posEpsilon = blubb.second; + ; } } - if (!vertexFinder) - { - _vertexFinder.Fill(pMesh->mVertices, pMesh->mNumVertices, sizeof( aiVector3D)); + if (!vertexFinder) { + _vertexFinder.Fill(pMesh->mVertices, pMesh->mNumVertices, sizeof(aiVector3D)); vertexFinder = &_vertexFinder; posEpsilon = ComputePositionEpsilon(pMesh); } @@ -263,56 +251,52 @@ bool CalcTangentsProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex) // in the second pass we now smooth out all tangents and bitangents at the same local position // if they are not too far off. - for( unsigned int a = 0; a < pMesh->mNumVertices; a++) - { - if( vertexDone[a]) + for (unsigned int a = 0; a < pMesh->mNumVertices; a++) { + if (vertexDone[a]) continue; - const aiVector3D& origPos = pMesh->mVertices[a]; - const aiVector3D& origNorm = pMesh->mNormals[a]; - const aiVector3D& origTang = pMesh->mTangents[a]; - const aiVector3D& origBitang = pMesh->mBitangents[a]; - closeVertices.resize( 0 ); + const aiVector3D &origPos = pMesh->mVertices[a]; + const aiVector3D &origNorm = pMesh->mNormals[a]; + const aiVector3D &origTang = pMesh->mTangents[a]; + const aiVector3D &origBitang = pMesh->mBitangents[a]; + closeVertices.resize(0); // find all vertices close to that position - vertexFinder->FindPositions( origPos, posEpsilon, verticesFound); + vertexFinder->FindPositions(origPos, posEpsilon, verticesFound); - closeVertices.reserve (verticesFound.size()+5); - closeVertices.push_back( a); + closeVertices.reserve(verticesFound.size() + 5); + closeVertices.push_back(a); // look among them for other vertices sharing the same normal and a close-enough tangent/bitangent - for( unsigned int b = 0; b < verticesFound.size(); b++) - { + for (unsigned int b = 0; b < verticesFound.size(); b++) { unsigned int idx = verticesFound[b]; - if( vertexDone[idx]) + if (vertexDone[idx]) continue; - if( meshNorm[idx] * origNorm < angleEpsilon) + if (meshNorm[idx] * origNorm < angleEpsilon) continue; - if( meshTang[idx] * origTang < fLimit) + if (meshTang[idx] * origTang < fLimit) continue; - if( meshBitang[idx] * origBitang < fLimit) + if (meshBitang[idx] * origBitang < fLimit) continue; // it's similar enough -> add it to the smoothing group - closeVertices.push_back( idx); + closeVertices.push_back(idx); vertexDone[idx] = true; } // smooth the tangents and bitangents of all vertices that were found to be close enough - aiVector3D smoothTangent( 0, 0, 0), smoothBitangent( 0, 0, 0); - for( unsigned int b = 0; b < closeVertices.size(); ++b) - { - smoothTangent += meshTang[ closeVertices[b] ]; - smoothBitangent += meshBitang[ closeVertices[b] ]; + aiVector3D smoothTangent(0, 0, 0), smoothBitangent(0, 0, 0); + for (unsigned int b = 0; b < closeVertices.size(); ++b) { + smoothTangent += meshTang[closeVertices[b]]; + smoothBitangent += meshBitang[closeVertices[b]]; } smoothTangent.Normalize(); smoothBitangent.Normalize(); // and write it back into all affected tangents - for( unsigned int b = 0; b < closeVertices.size(); ++b) - { - meshTang[ closeVertices[b] ] = smoothTangent; - meshBitang[ closeVertices[b] ] = smoothBitangent; + for (unsigned int b = 0; b < closeVertices.size(); ++b) { + meshTang[closeVertices[b]] = smoothTangent; + meshBitang[closeVertices[b]] = smoothBitangent; } } return true; diff --git a/code/PostProcessing/ConvertToLHProcess.cpp b/code/PostProcessing/ConvertToLHProcess.cpp index 29c2d6a26..47d4eb565 100644 --- a/code/PostProcessing/ConvertToLHProcess.cpp +++ b/code/PostProcessing/ConvertToLHProcess.cpp @@ -49,10 +49,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * better location. */ - #include "ConvertToLHProcess.h" -#include #include +#include #include using namespace Assimp; @@ -62,8 +61,10 @@ using namespace Assimp; namespace { template -void flipUVs(aiMeshType* pMesh) { - if (pMesh == nullptr) { return; } +void flipUVs(aiMeshType *pMesh) { + if (pMesh == nullptr) { + return; + } // mirror texture y coordinate for (unsigned int tcIdx = 0; tcIdx < AI_MAX_NUMBER_OF_TEXTURECOORDS; tcIdx++) { if (!pMesh->HasTextureCoords(tcIdx)) { @@ -80,8 +81,8 @@ void flipUVs(aiMeshType* pMesh) { // ------------------------------------------------------------------------------------------------ // Constructor to be privately used by Importer -MakeLeftHandedProcess::MakeLeftHandedProcess() -: BaseProcess() { +MakeLeftHandedProcess::MakeLeftHandedProcess() : + BaseProcess() { // empty } @@ -93,40 +94,36 @@ MakeLeftHandedProcess::~MakeLeftHandedProcess() { // ------------------------------------------------------------------------------------------------ // Returns whether the processing step is present in the given flag field. -bool MakeLeftHandedProcess::IsActive( unsigned int pFlags) const -{ +bool MakeLeftHandedProcess::IsActive(unsigned int pFlags) const { return 0 != (pFlags & aiProcess_MakeLeftHanded); } // ------------------------------------------------------------------------------------------------ // Executes the post processing step on the given imported data. -void MakeLeftHandedProcess::Execute( aiScene* pScene) -{ +void MakeLeftHandedProcess::Execute(aiScene *pScene) { // Check for an existent root node to proceed - ai_assert(pScene->mRootNode != NULL); + ai_assert(pScene->mRootNode != nullptr); ASSIMP_LOG_DEBUG("MakeLeftHandedProcess begin"); // recursively convert all the nodes - ProcessNode( pScene->mRootNode, aiMatrix4x4()); + ProcessNode(pScene->mRootNode, aiMatrix4x4()); // process the meshes accordingly - for ( unsigned int a = 0; a < pScene->mNumMeshes; ++a ) { - ProcessMesh( pScene->mMeshes[ a ] ); + for (unsigned int a = 0; a < pScene->mNumMeshes; ++a) { + ProcessMesh(pScene->mMeshes[a]); } // process the materials accordingly - for ( unsigned int a = 0; a < pScene->mNumMaterials; ++a ) { - ProcessMaterial( pScene->mMaterials[ a ] ); + for (unsigned int a = 0; a < pScene->mNumMaterials; ++a) { + ProcessMaterial(pScene->mMaterials[a]); } // transform all animation channels as well - for( unsigned int a = 0; a < pScene->mNumAnimations; a++) - { - aiAnimation* anim = pScene->mAnimations[a]; - for( unsigned int b = 0; b < anim->mNumChannels; b++) - { - aiNodeAnim* nodeAnim = anim->mChannels[b]; - ProcessAnimation( nodeAnim); + for (unsigned int a = 0; a < pScene->mNumAnimations; a++) { + aiAnimation *anim = pScene->mAnimations[a]; + for (unsigned int b = 0; b < anim->mNumChannels; b++) { + aiNodeAnim *nodeAnim = anim->mChannels[b]; + ProcessAnimation(nodeAnim); } } ASSIMP_LOG_DEBUG("MakeLeftHandedProcess finished"); @@ -134,8 +131,7 @@ void MakeLeftHandedProcess::Execute( aiScene* pScene) // ------------------------------------------------------------------------------------------------ // Recursively converts a node, all of its children and all of its meshes -void MakeLeftHandedProcess::ProcessNode( aiNode* pNode, const aiMatrix4x4& pParentGlobalRotation) -{ +void MakeLeftHandedProcess::ProcessNode(aiNode *pNode, const aiMatrix4x4 &pParentGlobalRotation) { // mirror all base vectors at the local Z axis pNode->mTransformation.c1 = -pNode->mTransformation.c1; pNode->mTransformation.c2 = -pNode->mTransformation.c2; @@ -150,43 +146,38 @@ void MakeLeftHandedProcess::ProcessNode( aiNode* pNode, const aiMatrix4x4& pPare pNode->mTransformation.d3 = -pNode->mTransformation.d3; // useless, but anyways... // continue for all children - for( size_t a = 0; a < pNode->mNumChildren; ++a ) { - ProcessNode( pNode->mChildren[ a ], pParentGlobalRotation * pNode->mTransformation ); + for (size_t a = 0; a < pNode->mNumChildren; ++a) { + ProcessNode(pNode->mChildren[a], pParentGlobalRotation * pNode->mTransformation); } } // ------------------------------------------------------------------------------------------------ // Converts a single mesh to left handed coordinates. -void MakeLeftHandedProcess::ProcessMesh( aiMesh* pMesh) { - if ( nullptr == pMesh ) { - ASSIMP_LOG_ERROR( "Nullptr to mesh found." ); +void MakeLeftHandedProcess::ProcessMesh(aiMesh *pMesh) { + if (nullptr == pMesh) { + ASSIMP_LOG_ERROR("Nullptr to mesh found."); return; } // mirror positions, normals and stuff along the Z axis - for( size_t a = 0; a < pMesh->mNumVertices; ++a) - { + for (size_t a = 0; a < pMesh->mNumVertices; ++a) { pMesh->mVertices[a].z *= -1.0f; if (pMesh->HasNormals()) { pMesh->mNormals[a].z *= -1.0f; } - if( pMesh->HasTangentsAndBitangents()) - { + if (pMesh->HasTangentsAndBitangents()) { pMesh->mTangents[a].z *= -1.0f; pMesh->mBitangents[a].z *= -1.0f; } } // mirror anim meshes positions, normals and stuff along the Z axis - for (size_t m = 0; m < pMesh->mNumAnimMeshes; ++m) - { - for (size_t a = 0; a < pMesh->mAnimMeshes[m]->mNumVertices; ++a) - { + for (size_t m = 0; m < pMesh->mNumAnimMeshes; ++m) { + for (size_t a = 0; a < pMesh->mAnimMeshes[m]->mNumVertices; ++a) { pMesh->mAnimMeshes[m]->mVertices[a].z *= -1.0f; if (pMesh->mAnimMeshes[m]->HasNormals()) { pMesh->mAnimMeshes[m]->mNormals[a].z *= -1.0f; } - if (pMesh->mAnimMeshes[m]->HasTangentsAndBitangents()) - { + if (pMesh->mAnimMeshes[m]->HasTangentsAndBitangents()) { pMesh->mAnimMeshes[m]->mTangents[a].z *= -1.0f; pMesh->mAnimMeshes[m]->mBitangents[a].z *= -1.0f; } @@ -194,9 +185,8 @@ void MakeLeftHandedProcess::ProcessMesh( aiMesh* pMesh) { } // mirror offset matrices of all bones - for( size_t a = 0; a < pMesh->mNumBones; ++a) - { - aiBone* bone = pMesh->mBones[a]; + for (size_t a = 0; a < pMesh->mNumBones; ++a) { + aiBone *bone = pMesh->mBones[a]; bone->mOffsetMatrix.a3 = -bone->mOffsetMatrix.a3; bone->mOffsetMatrix.b3 = -bone->mOffsetMatrix.b3; bone->mOffsetMatrix.d3 = -bone->mOffsetMatrix.d3; @@ -206,29 +196,28 @@ void MakeLeftHandedProcess::ProcessMesh( aiMesh* pMesh) { } // mirror bitangents as well as they're derived from the texture coords - if( pMesh->HasTangentsAndBitangents()) - { - for( unsigned int a = 0; a < pMesh->mNumVertices; a++) + if (pMesh->HasTangentsAndBitangents()) { + for (unsigned int a = 0; a < pMesh->mNumVertices; a++) pMesh->mBitangents[a] *= -1.0f; } } // ------------------------------------------------------------------------------------------------ // Converts a single material to left handed coordinates. -void MakeLeftHandedProcess::ProcessMaterial( aiMaterial* _mat) { - if ( nullptr == _mat ) { - ASSIMP_LOG_ERROR( "Nullptr to aiMaterial found." ); +void MakeLeftHandedProcess::ProcessMaterial(aiMaterial *_mat) { + if (nullptr == _mat) { + ASSIMP_LOG_ERROR("Nullptr to aiMaterial found."); return; } - aiMaterial* mat = (aiMaterial*)_mat; - for (unsigned int a = 0; a < mat->mNumProperties;++a) { - aiMaterialProperty* prop = mat->mProperties[a]; + aiMaterial *mat = (aiMaterial *)_mat; + for (unsigned int a = 0; a < mat->mNumProperties; ++a) { + aiMaterialProperty *prop = mat->mProperties[a]; // Mapping axis for UV mappings? - if (!::strcmp( prop->mKey.data, "$tex.mapaxis")) { - ai_assert( prop->mDataLength >= sizeof(aiVector3D)); /* something is wrong with the validation if we end up here */ - aiVector3D* pff = (aiVector3D*)prop->mData; + if (!::strcmp(prop->mKey.data, "$tex.mapaxis")) { + ai_assert(prop->mDataLength >= sizeof(aiVector3D)); // something is wrong with the validation if we end up here + aiVector3D *pff = (aiVector3D *)prop->mData; pff->z *= -1.f; } } @@ -236,15 +225,13 @@ void MakeLeftHandedProcess::ProcessMaterial( aiMaterial* _mat) { // ------------------------------------------------------------------------------------------------ // Converts the given animation to LH coordinates. -void MakeLeftHandedProcess::ProcessAnimation( aiNodeAnim* pAnim) -{ +void MakeLeftHandedProcess::ProcessAnimation(aiNodeAnim *pAnim) { // position keys - for( unsigned int a = 0; a < pAnim->mNumPositionKeys; a++) + for (unsigned int a = 0; a < pAnim->mNumPositionKeys; a++) pAnim->mPositionKeys[a].mValue.z *= -1.0f; // rotation keys - for( unsigned int a = 0; a < pAnim->mNumRotationKeys; a++) - { + 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; @@ -258,55 +245,50 @@ void MakeLeftHandedProcess::ProcessAnimation( aiNodeAnim* pAnim) } #endif // !! ASSIMP_BUILD_NO_MAKELEFTHANDED_PROCESS -#ifndef ASSIMP_BUILD_NO_FLIPUVS_PROCESS +#ifndef ASSIMP_BUILD_NO_FLIPUVS_PROCESS // # FlipUVsProcess // ------------------------------------------------------------------------------------------------ // Constructor to be privately used by Importer -FlipUVsProcess::FlipUVsProcess() -{} +FlipUVsProcess::FlipUVsProcess() {} // ------------------------------------------------------------------------------------------------ // Destructor, private as well -FlipUVsProcess::~FlipUVsProcess() -{} +FlipUVsProcess::~FlipUVsProcess() {} // ------------------------------------------------------------------------------------------------ // Returns whether the processing step is present in the given flag field. -bool FlipUVsProcess::IsActive( unsigned int pFlags) const -{ +bool FlipUVsProcess::IsActive(unsigned int pFlags) const { return 0 != (pFlags & aiProcess_FlipUVs); } // ------------------------------------------------------------------------------------------------ // Executes the post processing step on the given imported data. -void FlipUVsProcess::Execute( aiScene* pScene) -{ +void FlipUVsProcess::Execute(aiScene *pScene) { ASSIMP_LOG_DEBUG("FlipUVsProcess begin"); - for (unsigned int i = 0; i < pScene->mNumMeshes;++i) + for (unsigned int i = 0; i < pScene->mNumMeshes; ++i) ProcessMesh(pScene->mMeshes[i]); - for (unsigned int i = 0; i < pScene->mNumMaterials;++i) + for (unsigned int i = 0; i < pScene->mNumMaterials; ++i) ProcessMaterial(pScene->mMaterials[i]); ASSIMP_LOG_DEBUG("FlipUVsProcess finished"); } // ------------------------------------------------------------------------------------------------ // Converts a single material -void FlipUVsProcess::ProcessMaterial (aiMaterial* _mat) -{ - aiMaterial* mat = (aiMaterial*)_mat; - for (unsigned int a = 0; a < mat->mNumProperties;++a) { - aiMaterialProperty* prop = mat->mProperties[a]; - if( !prop ) { - ASSIMP_LOG_VERBOSE_DEBUG( "Property is null" ); +void FlipUVsProcess::ProcessMaterial(aiMaterial *_mat) { + aiMaterial *mat = (aiMaterial *)_mat; + for (unsigned int a = 0; a < mat->mNumProperties; ++a) { + aiMaterialProperty *prop = mat->mProperties[a]; + if (!prop) { + ASSIMP_LOG_VERBOSE_DEBUG("Property is null"); continue; } // UV transformation key? - if (!::strcmp( prop->mKey.data, "$tex.uvtrafo")) { - ai_assert( prop->mDataLength >= sizeof(aiUVTransform)); /* something is wrong with the validation if we end up here */ - aiUVTransform* uv = (aiUVTransform*)prop->mData; + if (!::strcmp(prop->mKey.data, "$tex.uvtrafo")) { + ai_assert(prop->mDataLength >= sizeof(aiUVTransform)); // something is wrong with the validation if we end up here + aiUVTransform *uv = (aiUVTransform *)prop->mData; // just flip it, that's everything uv->mTranslation.y *= -1.f; @@ -317,8 +299,7 @@ void FlipUVsProcess::ProcessMaterial (aiMaterial* _mat) // ------------------------------------------------------------------------------------------------ // Converts a single mesh -void FlipUVsProcess::ProcessMesh( aiMesh* pMesh) -{ +void FlipUVsProcess::ProcessMesh(aiMesh *pMesh) { flipUVs(pMesh); for (unsigned int idx = 0; idx < pMesh->mNumAnimMeshes; idx++) { flipUVs(pMesh->mAnimMeshes[idx]); @@ -326,44 +307,38 @@ void FlipUVsProcess::ProcessMesh( aiMesh* pMesh) } #endif // !ASSIMP_BUILD_NO_FLIPUVS_PROCESS -#ifndef ASSIMP_BUILD_NO_FLIPWINDING_PROCESS +#ifndef ASSIMP_BUILD_NO_FLIPWINDING_PROCESS // # FlipWindingOrderProcess // ------------------------------------------------------------------------------------------------ // Constructor to be privately used by Importer -FlipWindingOrderProcess::FlipWindingOrderProcess() -{} +FlipWindingOrderProcess::FlipWindingOrderProcess() {} // ------------------------------------------------------------------------------------------------ // Destructor, private as well -FlipWindingOrderProcess::~FlipWindingOrderProcess() -{} +FlipWindingOrderProcess::~FlipWindingOrderProcess() {} // ------------------------------------------------------------------------------------------------ // Returns whether the processing step is present in the given flag field. -bool FlipWindingOrderProcess::IsActive( unsigned int pFlags) const -{ +bool FlipWindingOrderProcess::IsActive(unsigned int pFlags) const { return 0 != (pFlags & aiProcess_FlipWindingOrder); } // ------------------------------------------------------------------------------------------------ // Executes the post processing step on the given imported data. -void FlipWindingOrderProcess::Execute( aiScene* pScene) -{ +void FlipWindingOrderProcess::Execute(aiScene *pScene) { ASSIMP_LOG_DEBUG("FlipWindingOrderProcess begin"); - for (unsigned int i = 0; i < pScene->mNumMeshes;++i) + for (unsigned int i = 0; i < pScene->mNumMeshes; ++i) ProcessMesh(pScene->mMeshes[i]); ASSIMP_LOG_DEBUG("FlipWindingOrderProcess finished"); } // ------------------------------------------------------------------------------------------------ // Converts a single mesh -void FlipWindingOrderProcess::ProcessMesh( aiMesh* pMesh) -{ +void FlipWindingOrderProcess::ProcessMesh(aiMesh *pMesh) { // invert the order of all faces in this mesh - for( unsigned int a = 0; a < pMesh->mNumFaces; a++) - { - aiFace& face = pMesh->mFaces[a]; + for (unsigned int a = 0; a < pMesh->mNumFaces; a++) { + aiFace &face = pMesh->mFaces[a]; for (unsigned int b = 0; b < face.mNumIndices / 2; b++) { std::swap(face.mIndices[b], face.mIndices[face.mNumIndices - 1 - b]); } @@ -371,39 +346,34 @@ void FlipWindingOrderProcess::ProcessMesh( aiMesh* pMesh) // invert the order of all components in this mesh anim meshes for (unsigned int m = 0; m < pMesh->mNumAnimMeshes; m++) { - aiAnimMesh* animMesh = pMesh->mAnimMeshes[m]; + aiAnimMesh *animMesh = pMesh->mAnimMeshes[m]; unsigned int numVertices = animMesh->mNumVertices; if (animMesh->HasPositions()) { - for (unsigned int a = 0; a < numVertices; a++) - { + for (unsigned int a = 0; a < numVertices; a++) { std::swap(animMesh->mVertices[a], animMesh->mVertices[numVertices - 1 - a]); } } if (animMesh->HasNormals()) { - for (unsigned int a = 0; a < numVertices; a++) - { + for (unsigned int a = 0; a < numVertices; a++) { std::swap(animMesh->mNormals[a], animMesh->mNormals[numVertices - 1 - a]); } } for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; i++) { if (animMesh->HasTextureCoords(i)) { - for (unsigned int a = 0; a < numVertices; a++) - { + for (unsigned int a = 0; a < numVertices; a++) { std::swap(animMesh->mTextureCoords[i][a], animMesh->mTextureCoords[i][numVertices - 1 - a]); } } } if (animMesh->HasTangentsAndBitangents()) { - for (unsigned int a = 0; a < numVertices; a++) - { + for (unsigned int a = 0; a < numVertices; a++) { std::swap(animMesh->mTangents[a], animMesh->mTangents[numVertices - 1 - a]); std::swap(animMesh->mBitangents[a], animMesh->mBitangents[numVertices - 1 - a]); } } for (unsigned int v = 0; v < AI_MAX_NUMBER_OF_COLOR_SETS; v++) { if (animMesh->HasVertexColors(v)) { - for (unsigned int a = 0; a < numVertices; a++) - { + for (unsigned int a = 0; a < numVertices; a++) { std::swap(animMesh->mColors[v][a], animMesh->mColors[v][numVertices - 1 - a]); } } diff --git a/code/PostProcessing/DeboneProcess.cpp b/code/PostProcessing/DeboneProcess.cpp index 9d6313f71..4d9cb6ab6 100644 --- a/code/PostProcessing/DeboneProcess.cpp +++ b/code/PostProcessing/DeboneProcess.cpp @@ -414,7 +414,8 @@ void DeboneProcess::UpdateNode(aiNode* pNode) const } if( pNode->mNumMeshes > 0 ) { - delete [] pNode->mMeshes; pNode->mMeshes = NULL; + delete[] pNode->mMeshes; + pNode->mMeshes = nullptr; } pNode->mNumMeshes = static_cast(newMeshList.size()); diff --git a/code/PostProcessing/DropFaceNormalsProcess.cpp b/code/PostProcessing/DropFaceNormalsProcess.cpp index 1d7cf33b0..170dedb29 100644 --- a/code/PostProcessing/DropFaceNormalsProcess.cpp +++ b/code/PostProcessing/DropFaceNormalsProcess.cpp @@ -98,12 +98,14 @@ void DropFaceNormalsProcess::Execute( aiScene* pScene) { // ------------------------------------------------------------------------------------------------ // Executes the post processing step on the given imported data. -bool DropFaceNormalsProcess::DropMeshFaceNormals (aiMesh* pMesh) { - if (NULL == pMesh->mNormals) { +bool DropFaceNormalsProcess::DropMeshFaceNormals (aiMesh* mesh) { + ai_assert(nullptr != mesh); + + if (nullptr == mesh->mNormals) { return false; } - delete[] pMesh->mNormals; - pMesh->mNormals = nullptr; + delete[] mesh->mNormals; + mesh->mNormals = nullptr; return true; } diff --git a/code/PostProcessing/FindInstancesProcess.cpp b/code/PostProcessing/FindInstancesProcess.cpp index 9a4c6f53b..41f78a9eb 100644 --- a/code/PostProcessing/FindInstancesProcess.cpp +++ b/code/PostProcessing/FindInstancesProcess.cpp @@ -243,7 +243,7 @@ void FindInstancesProcess::Execute( aiScene* pScene) // Delete the instanced mesh, we don't need it anymore delete inst; - pScene->mMeshes[i] = NULL; + pScene->mMeshes[i] = nullptr; break; } } @@ -256,7 +256,7 @@ void FindInstancesProcess::Execute( aiScene* pScene) ai_assert(0 != numMeshesOut); if (numMeshesOut != pScene->mNumMeshes) { - // Collapse the meshes array by removing all NULL entries + // Collapse the meshes array by removing all nullptr entries for (unsigned int real = 0, i = 0; real < numMeshesOut; ++i) { if (pScene->mMeshes[i]) pScene->mMeshes[real++] = pScene->mMeshes[i]; diff --git a/code/PostProcessing/FindInvalidDataProcess.cpp b/code/PostProcessing/FindInvalidDataProcess.cpp index 3ad2446b3..dc2b3c548 100644 --- a/code/PostProcessing/FindInvalidDataProcess.cpp +++ b/code/PostProcessing/FindInvalidDataProcess.cpp @@ -45,11 +45,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef ASSIMP_BUILD_NO_FINDINVALIDDATA_PROCESS // internal headers -# include "FindInvalidDataProcess.h" -# include "ProcessHelper.h" +#include "FindInvalidDataProcess.h" +#include "ProcessHelper.h" -# include -# include +#include +#include using namespace Assimp; @@ -97,7 +97,7 @@ void UpdateMeshReferences(aiNode *node, const std::vector &meshMap node->mNumMeshes = out; if (0 == out) { delete[] node->mMeshes; - node->mMeshes = NULL; + node->mMeshes = nullptr; } } // recursively update all children @@ -124,9 +124,10 @@ void FindInvalidDataProcess::Execute(aiScene *pScene) { if (2 == result) { // remove this mesh delete pScene->mMeshes[a]; - pScene->mMeshes[a] = NULL; + pScene->mMeshes[a] = nullptr; meshMapping[a] = UINT_MAX; + out = true; continue; } @@ -201,7 +202,7 @@ inline bool ProcessArray(T *&in, unsigned int num, const char *name, if (err) { ASSIMP_LOG_ERROR_F("FindInvalidDataProcess fails on mesh ", name, ": ", err); delete[] in; - in = NULL; + in = nullptr; return true; } return false; @@ -345,7 +346,7 @@ int FindInvalidDataProcess::ProcessMesh(aiMesh *pMesh) { // delete all subsequent texture coordinate sets. for (unsigned int a = i + 1; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a) { delete[] pMesh->mTextureCoords[a]; - pMesh->mTextureCoords[a] = NULL; + pMesh->mTextureCoords[a] = nullptr; pMesh->mNumUVComponents[a] = 0; } @@ -391,14 +392,14 @@ int FindInvalidDataProcess::ProcessMesh(aiMesh *pMesh) { // Process mesh tangents if (pMesh->mTangents && ProcessArray(pMesh->mTangents, pMesh->mNumVertices, "tangents", dirtyMask)) { delete[] pMesh->mBitangents; - pMesh->mBitangents = NULL; + pMesh->mBitangents = nullptr; ret = true; } // Process mesh bitangents if (pMesh->mBitangents && ProcessArray(pMesh->mBitangents, pMesh->mNumVertices, "bitangents", dirtyMask)) { delete[] pMesh->mTangents; - pMesh->mTangents = NULL; + pMesh->mTangents = nullptr; ret = true; } } diff --git a/code/PostProcessing/GenFaceNormalsProcess.cpp b/code/PostProcessing/GenFaceNormalsProcess.cpp index 08a1d9aae..b610ef830 100644 --- a/code/PostProcessing/GenFaceNormalsProcess.cpp +++ b/code/PostProcessing/GenFaceNormalsProcess.cpp @@ -45,41 +45,37 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * normals for all imported faces. */ - #include "GenFaceNormalsProcess.h" +#include #include +#include #include #include -#include -#include - using namespace Assimp; // ------------------------------------------------------------------------------------------------ // Constructor to be privately used by Importer -GenFaceNormalsProcess::GenFaceNormalsProcess() -{ +GenFaceNormalsProcess::GenFaceNormalsProcess() { // nothing to do here } // ------------------------------------------------------------------------------------------------ // Destructor, private as well -GenFaceNormalsProcess::~GenFaceNormalsProcess() -{ +GenFaceNormalsProcess::~GenFaceNormalsProcess() { // nothing to do here } // ------------------------------------------------------------------------------------------------ // Returns whether the processing step is present in the given flag field. -bool GenFaceNormalsProcess::IsActive( unsigned int pFlags) const { +bool GenFaceNormalsProcess::IsActive(unsigned int pFlags) const { force_ = (pFlags & aiProcess_ForceGenNormals) != 0; - return (pFlags & aiProcess_GenNormals) != 0; + return (pFlags & aiProcess_GenNormals) != 0; } // ------------------------------------------------------------------------------------------------ // Executes the post processing step on the given imported data. -void GenFaceNormalsProcess::Execute( aiScene* pScene) { +void GenFaceNormalsProcess::Execute(aiScene *pScene) { ASSIMP_LOG_DEBUG("GenFaceNormalsProcess begin"); if (pScene->mFlags & AI_SCENE_FLAGS_NON_VERBOSE_FORMAT) { @@ -87,33 +83,35 @@ void GenFaceNormalsProcess::Execute( aiScene* pScene) { } bool bHas = false; - for( unsigned int a = 0; a < pScene->mNumMeshes; a++) { - if(this->GenMeshFaceNormals( pScene->mMeshes[a])) { + for (unsigned int a = 0; a < pScene->mNumMeshes; a++) { + if (this->GenMeshFaceNormals(pScene->mMeshes[a])) { bHas = true; } } - if (bHas) { + if (bHas) { ASSIMP_LOG_INFO("GenFaceNormalsProcess finished. " - "Face normals have been calculated"); + "Face normals have been calculated"); } else { ASSIMP_LOG_DEBUG("GenFaceNormalsProcess finished. " - "Normals are already there"); + "Normals are already there"); } } // ------------------------------------------------------------------------------------------------ // Executes the post processing step on the given imported data. -bool GenFaceNormalsProcess::GenMeshFaceNormals (aiMesh* pMesh) -{ - if (NULL != pMesh->mNormals) { - if (force_) delete[] pMesh->mNormals; - else return false; +bool GenFaceNormalsProcess::GenMeshFaceNormals(aiMesh *pMesh) { + if (nullptr != pMesh->mNormals) { + if (force_) { + delete[] pMesh->mNormals; + } else { + return false; + } } // If the mesh consists of lines and/or points but not of // triangles or higher-order polygons the normal vectors // are undefined. - if (!(pMesh->mPrimitiveTypes & (aiPrimitiveType_TRIANGLE | aiPrimitiveType_POLYGON))) { + if (!(pMesh->mPrimitiveTypes & (aiPrimitiveType_TRIANGLE | aiPrimitiveType_POLYGON))) { ASSIMP_LOG_INFO("Normal vectors are undefined for line and point meshes"); return false; } @@ -123,22 +121,22 @@ bool GenFaceNormalsProcess::GenMeshFaceNormals (aiMesh* pMesh) const float qnan = get_qnan(); // iterate through all faces and compute per-face normals but store them per-vertex. - for( unsigned int a = 0; a < pMesh->mNumFaces; a++) { - const aiFace& face = pMesh->mFaces[a]; - if (face.mNumIndices < 3) { + for (unsigned int a = 0; a < pMesh->mNumFaces; a++) { + const aiFace &face = pMesh->mFaces[a]; + if (face.mNumIndices < 3) { // either a point or a line -> no well-defined normal vector - for (unsigned int i = 0;i < face.mNumIndices;++i) { + for (unsigned int i = 0; i < face.mNumIndices; ++i) { pMesh->mNormals[face.mIndices[i]] = aiVector3D(qnan); } continue; } - const aiVector3D* pV1 = &pMesh->mVertices[face.mIndices[0]]; - const aiVector3D* pV2 = &pMesh->mVertices[face.mIndices[1]]; - const aiVector3D* pV3 = &pMesh->mVertices[face.mIndices[face.mNumIndices-1]]; + const aiVector3D *pV1 = &pMesh->mVertices[face.mIndices[0]]; + const aiVector3D *pV2 = &pMesh->mVertices[face.mIndices[1]]; + const aiVector3D *pV3 = &pMesh->mVertices[face.mIndices[face.mNumIndices - 1]]; const aiVector3D vNor = ((*pV2 - *pV1) ^ (*pV3 - *pV1)).NormalizeSafe(); - for (unsigned int i = 0;i < face.mNumIndices;++i) { + for (unsigned int i = 0; i < face.mNumIndices; ++i) { pMesh->mNormals[face.mIndices[i]] = vNor; } } diff --git a/code/PostProcessing/GenVertexNormalsProcess.cpp b/code/PostProcessing/GenVertexNormalsProcess.cpp index 1df333410..72031153b 100644 --- a/code/PostProcessing/GenVertexNormalsProcess.cpp +++ b/code/PostProcessing/GenVertexNormalsProcess.cpp @@ -45,8 +45,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * normals for all imported faces. */ - - // internal headers #include "GenVertexNormalsProcess.h" #include "ProcessHelper.h" @@ -57,8 +55,8 @@ using namespace Assimp; // ------------------------------------------------------------------------------------------------ // Constructor to be privately used by Importer -GenVertexNormalsProcess::GenVertexNormalsProcess() -: configMaxAngle( AI_DEG_TO_RAD( 175.f ) ) { +GenVertexNormalsProcess::GenVertexNormalsProcess() : + configMaxAngle(AI_DEG_TO_RAD(175.f)) { // empty } @@ -70,25 +68,22 @@ GenVertexNormalsProcess::~GenVertexNormalsProcess() { // ------------------------------------------------------------------------------------------------ // Returns whether the processing step is present in the given flag field. -bool GenVertexNormalsProcess::IsActive( unsigned int pFlags) const -{ +bool GenVertexNormalsProcess::IsActive(unsigned int pFlags) const { force_ = (pFlags & aiProcess_ForceGenNormals) != 0; return (pFlags & aiProcess_GenSmoothNormals) != 0; } // ------------------------------------------------------------------------------------------------ // Executes the post processing step on the given imported data. -void GenVertexNormalsProcess::SetupProperties(const Importer* pImp) -{ +void GenVertexNormalsProcess::SetupProperties(const Importer *pImp) { // Get the current value of the AI_CONFIG_PP_GSN_MAX_SMOOTHING_ANGLE property - configMaxAngle = pImp->GetPropertyFloat(AI_CONFIG_PP_GSN_MAX_SMOOTHING_ANGLE,(ai_real)175.0); - configMaxAngle = AI_DEG_TO_RAD(std::max(std::min(configMaxAngle,(ai_real)175.0),(ai_real)0.0)); + configMaxAngle = pImp->GetPropertyFloat(AI_CONFIG_PP_GSN_MAX_SMOOTHING_ANGLE, (ai_real)175.0); + configMaxAngle = AI_DEG_TO_RAD(std::max(std::min(configMaxAngle, (ai_real)175.0), (ai_real)0.0)); } // ------------------------------------------------------------------------------------------------ // Executes the post processing step on the given imported data. -void GenVertexNormalsProcess::Execute( aiScene* pScene) -{ +void GenVertexNormalsProcess::Execute(aiScene *pScene) { ASSIMP_LOG_DEBUG("GenVertexNormalsProcess begin"); if (pScene->mFlags & AI_SCENE_FLAGS_NON_VERBOSE_FORMAT) { @@ -96,34 +91,34 @@ void GenVertexNormalsProcess::Execute( aiScene* pScene) } bool bHas = false; - for( unsigned int a = 0; a < pScene->mNumMeshes; ++a) { - if(GenMeshVertexNormals( pScene->mMeshes[a],a)) + for (unsigned int a = 0; a < pScene->mNumMeshes; ++a) { + if (GenMeshVertexNormals(pScene->mMeshes[a], a)) bHas = true; } - if (bHas) { + if (bHas) { ASSIMP_LOG_INFO("GenVertexNormalsProcess finished. " - "Vertex normals have been calculated"); + "Vertex normals have been calculated"); } else { ASSIMP_LOG_DEBUG("GenVertexNormalsProcess finished. " - "Normals are already there"); + "Normals are already there"); } } // ------------------------------------------------------------------------------------------------ // Executes the post processing step on the given imported data. -bool GenVertexNormalsProcess::GenMeshVertexNormals (aiMesh* pMesh, unsigned int meshIndex) -{ - if (NULL != pMesh->mNormals) { - if (force_) delete[] pMesh->mNormals; - else return false; +bool GenVertexNormalsProcess::GenMeshVertexNormals(aiMesh *pMesh, unsigned int meshIndex) { + if (nullptr != pMesh->mNormals) { + if (force_) + delete[] pMesh->mNormals; + else + return false; } // If the mesh consists of lines and/or points but not of // triangles or higher-order polygons the normal vectors // are undefined. - if (!(pMesh->mPrimitiveTypes & (aiPrimitiveType_TRIANGLE | aiPrimitiveType_POLYGON))) - { + if (!(pMesh->mPrimitiveTypes & (aiPrimitiveType_TRIANGLE | aiPrimitiveType_POLYGON))) { ASSIMP_LOG_INFO("Normal vectors are undefined for line and point meshes"); return false; } @@ -133,75 +128,71 @@ bool GenVertexNormalsProcess::GenMeshVertexNormals (aiMesh* pMesh, unsigned int pMesh->mNormals = new aiVector3D[pMesh->mNumVertices]; // Compute per-face normals but store them per-vertex - for( unsigned int a = 0; a < pMesh->mNumFaces; a++) - { - const aiFace& face = pMesh->mFaces[a]; - if (face.mNumIndices < 3) - { + for (unsigned int a = 0; a < pMesh->mNumFaces; a++) { + const aiFace &face = pMesh->mFaces[a]; + if (face.mNumIndices < 3) { // either a point or a line -> no normal vector - for (unsigned int i = 0;i < face.mNumIndices;++i) { + for (unsigned int i = 0; i < face.mNumIndices; ++i) { pMesh->mNormals[face.mIndices[i]] = aiVector3D(qnan); } continue; } - const aiVector3D* pV1 = &pMesh->mVertices[face.mIndices[0]]; - const aiVector3D* pV2 = &pMesh->mVertices[face.mIndices[1]]; - const aiVector3D* pV3 = &pMesh->mVertices[face.mIndices[face.mNumIndices-1]]; + const aiVector3D *pV1 = &pMesh->mVertices[face.mIndices[0]]; + const aiVector3D *pV2 = &pMesh->mVertices[face.mIndices[1]]; + const aiVector3D *pV3 = &pMesh->mVertices[face.mIndices[face.mNumIndices - 1]]; const aiVector3D vNor = ((*pV2 - *pV1) ^ (*pV3 - *pV1)).NormalizeSafe(); - for (unsigned int i = 0;i < face.mNumIndices;++i) { + for (unsigned int i = 0; i < face.mNumIndices; ++i) { pMesh->mNormals[face.mIndices[i]] = vNor; } } // Set up a SpatialSort to quickly find all vertices close to a given position // check whether we can reuse the SpatialSort of a previous step. - SpatialSort* vertexFinder = NULL; - SpatialSort _vertexFinder; - ai_real posEpsilon = ai_real( 1e-5 ); + SpatialSort *vertexFinder = nullptr; + SpatialSort _vertexFinder; + ai_real posEpsilon = ai_real(1e-5); if (shared) { - std::vector >* avf; - shared->GetProperty(AI_SPP_SPATIAL_SORT,avf); - if (avf) - { - std::pair& blubb = avf->operator [] (meshIndex); + std::vector> *avf; + shared->GetProperty(AI_SPP_SPATIAL_SORT, avf); + if (avf) { + std::pair &blubb = avf->operator[](meshIndex); vertexFinder = &blubb.first; posEpsilon = blubb.second; } } - if (!vertexFinder) { - _vertexFinder.Fill(pMesh->mVertices, pMesh->mNumVertices, sizeof( aiVector3D)); + if (!vertexFinder) { + _vertexFinder.Fill(pMesh->mVertices, pMesh->mNumVertices, sizeof(aiVector3D)); vertexFinder = &_vertexFinder; posEpsilon = ComputePositionEpsilon(pMesh); } std::vector verticesFound; - aiVector3D* pcNew = new aiVector3D[pMesh->mNumVertices]; + aiVector3D *pcNew = new aiVector3D[pMesh->mNumVertices]; - if (configMaxAngle >= AI_DEG_TO_RAD( 175.f )) { + if (configMaxAngle >= AI_DEG_TO_RAD(175.f)) { // There is no angle limit. Thus all vertices with positions close // to each other will receive the same vertex normal. This allows us // to optimize the whole algorithm a little bit ... - std::vector abHad(pMesh->mNumVertices,false); - for (unsigned int i = 0; i < pMesh->mNumVertices;++i) { + std::vector abHad(pMesh->mNumVertices, false); + for (unsigned int i = 0; i < pMesh->mNumVertices; ++i) { if (abHad[i]) { continue; } // Get all vertices that share this one ... - vertexFinder->FindPositions( pMesh->mVertices[i], posEpsilon, verticesFound); + vertexFinder->FindPositions(pMesh->mVertices[i], posEpsilon, verticesFound); aiVector3D pcNor; for (unsigned int a = 0; a < verticesFound.size(); ++a) { - const aiVector3D& v = pMesh->mNormals[verticesFound[a]]; - if (is_not_qnan(v.x))pcNor += v; + const aiVector3D &v = pMesh->mNormals[verticesFound[a]]; + if (is_not_qnan(v.x)) pcNor += v; } pcNor.NormalizeSafe(); // Write the smoothed normal back to all affected normals - for (unsigned int a = 0; a < verticesFound.size(); ++a) - { + for (unsigned int a = 0; a < verticesFound.size(); ++a) { unsigned int vidx = verticesFound[a]; pcNew[vidx] = pcNor; abHad[vidx] = true; @@ -210,11 +201,11 @@ bool GenVertexNormalsProcess::GenMeshVertexNormals (aiMesh* pMesh, unsigned int } // Slower code path if a smooth angle is set. There are many ways to achieve // the effect, this one is the most straightforward one. - else { + else { const ai_real fLimit = std::cos(configMaxAngle); - for (unsigned int i = 0; i < pMesh->mNumVertices;++i) { + for (unsigned int i = 0; i < pMesh->mNumVertices; ++i) { // Get all vertices that share this one ... - vertexFinder->FindPositions( pMesh->mVertices[i] , posEpsilon, verticesFound); + vertexFinder->FindPositions(pMesh->mVertices[i], posEpsilon, verticesFound); aiVector3D vr = pMesh->mNormals[i]; diff --git a/code/PostProcessing/JoinVerticesProcess.cpp b/code/PostProcessing/JoinVerticesProcess.cpp index 4a6362e3e..5f8139536 100644 --- a/code/PostProcessing/JoinVerticesProcess.cpp +++ b/code/PostProcessing/JoinVerticesProcess.cpp @@ -266,7 +266,7 @@ int JoinVerticesProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex) std::vector replaceIndex( pMesh->mNumVertices, 0xffffffff); // float posEpsilonSqr; - SpatialSort* vertexFinder = NULL; + SpatialSort *vertexFinder = nullptr; SpatialSort _vertexFinder; typedef std::pair SpatPair; @@ -408,7 +408,7 @@ int JoinVerticesProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex) std::vector newWeights; newWeights.reserve( bone->mNumWeights); - if ( NULL != bone->mWeights ) { + if (nullptr != bone->mWeights) { for ( unsigned int b = 0; b < bone->mNumWeights; b++ ) { const aiVertexWeight& ow = bone->mWeights[ b ]; // if the vertex is a unique one, translate it @@ -420,7 +420,7 @@ int JoinVerticesProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex) } } } else { - ASSIMP_LOG_ERROR( "X-Export: aiBone shall contain weights, but pointer to them is NULL." ); + ASSIMP_LOG_ERROR( "X-Export: aiBone shall contain weights, but pointer to them is nullptr." ); } if (newWeights.size() > 0) { diff --git a/code/PostProcessing/LimitBoneWeightsProcess.cpp b/code/PostProcessing/LimitBoneWeightsProcess.cpp index 5b8934159..b4f0b48d8 100644 --- a/code/PostProcessing/LimitBoneWeightsProcess.cpp +++ b/code/PostProcessing/LimitBoneWeightsProcess.cpp @@ -114,6 +114,10 @@ void LimitBoneWeightsProcess::ProcessMesh(aiMesh* pMesh) for (unsigned int w = 0; w < bone->mNumWeights; ++w) { const aiVertexWeight& vw = bone->mWeights[w]; + + if (vertexWeights.size() <= vw.mVertexId) + continue; + vertexWeights[vw.mVertexId].push_back(Weight(b, vw.mWeight)); maxVertexWeights = std::max(maxVertexWeights, vertexWeights[vw.mVertexId].size()); } diff --git a/code/PostProcessing/MakeVerboseFormat.cpp b/code/PostProcessing/MakeVerboseFormat.cpp index 3928a5b27..cff5ed5e5 100644 --- a/code/PostProcessing/MakeVerboseFormat.cpp +++ b/code/PostProcessing/MakeVerboseFormat.cpp @@ -43,7 +43,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. /** @file Implementation of the post processing step "MakeVerboseFormat" */ - #include "MakeVerboseFormat.h" #include #include @@ -51,26 +50,22 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. using namespace Assimp; // ------------------------------------------------------------------------------------------------ -MakeVerboseFormatProcess::MakeVerboseFormatProcess() -{ +MakeVerboseFormatProcess::MakeVerboseFormatProcess() { // nothing to do here } // ------------------------------------------------------------------------------------------------ -MakeVerboseFormatProcess::~MakeVerboseFormatProcess() -{ +MakeVerboseFormatProcess::~MakeVerboseFormatProcess() { // nothing to do here } // ------------------------------------------------------------------------------------------------ // Executes the post processing step on the given imported data. -void MakeVerboseFormatProcess::Execute( aiScene* pScene) -{ - ai_assert(NULL != pScene); +void MakeVerboseFormatProcess::Execute(aiScene *pScene) { + ai_assert(nullptr != pScene); ASSIMP_LOG_DEBUG("MakeVerboseFormatProcess begin"); bool bHas = false; - for( unsigned int a = 0; a < pScene->mNumMeshes; a++) - { - if( MakeVerboseFormat( pScene->mMeshes[a])) + for (unsigned int a = 0; a < pScene->mNumMeshes; a++) { + if (MakeVerboseFormat(pScene->mMeshes[a])) bHas = true; } if (bHas) { @@ -84,29 +79,26 @@ void MakeVerboseFormatProcess::Execute( aiScene* pScene) // ------------------------------------------------------------------------------------------------ // Executes the post processing step on the given imported data. -bool MakeVerboseFormatProcess::MakeVerboseFormat(aiMesh* pcMesh) -{ - ai_assert(NULL != pcMesh); +bool MakeVerboseFormatProcess::MakeVerboseFormat(aiMesh *pcMesh) { + ai_assert(nullptr != pcMesh); unsigned int iOldNumVertices = pcMesh->mNumVertices; - const unsigned int iNumVerts = pcMesh->mNumFaces*3; + const unsigned int iNumVerts = pcMesh->mNumFaces * 3; - aiVector3D* pvPositions = new aiVector3D[ iNumVerts ]; + aiVector3D *pvPositions = new aiVector3D[iNumVerts]; - aiVector3D* pvNormals = NULL; - if (pcMesh->HasNormals()) - { + aiVector3D *pvNormals = nullptr; + if (pcMesh->HasNormals()) { pvNormals = new aiVector3D[iNumVerts]; } - aiVector3D* pvTangents = NULL, *pvBitangents = NULL; - if (pcMesh->HasTangentsAndBitangents()) - { + aiVector3D *pvTangents = nullptr, *pvBitangents = nullptr; + if (pcMesh->HasTangentsAndBitangents()) { pvTangents = new aiVector3D[iNumVerts]; pvBitangents = new aiVector3D[iNumVerts]; } - aiVector3D* apvTextureCoords[AI_MAX_NUMBER_OF_TEXTURECOORDS] = {0}; - aiColor4D* apvColorSets[AI_MAX_NUMBER_OF_COLOR_SETS] = {0}; + aiVector3D *apvTextureCoords[AI_MAX_NUMBER_OF_TEXTURECOORDS] = { 0 }; + aiColor4D *apvColorSets[AI_MAX_NUMBER_OF_COLOR_SETS] = { 0 }; unsigned int p = 0; while (pcMesh->HasTextureCoords(p)) @@ -117,24 +109,21 @@ bool MakeVerboseFormatProcess::MakeVerboseFormat(aiMesh* pcMesh) apvColorSets[p++] = new aiColor4D[iNumVerts]; // allocate enough memory to hold output bones and vertex weights ... - std::vector* newWeights = new std::vector[pcMesh->mNumBones]; - for (unsigned int i = 0;i < pcMesh->mNumBones;++i) { - newWeights[i].reserve(pcMesh->mBones[i]->mNumWeights*3); + std::vector *newWeights = new std::vector[pcMesh->mNumBones]; + for (unsigned int i = 0; i < pcMesh->mNumBones; ++i) { + newWeights[i].reserve(pcMesh->mBones[i]->mNumWeights * 3); } // iterate through all faces and build a clean list unsigned int iIndex = 0; - for (unsigned int a = 0; a< pcMesh->mNumFaces;++a) - { - aiFace* pcFace = &pcMesh->mFaces[a]; - for (unsigned int q = 0; q < pcFace->mNumIndices;++q,++iIndex) - { + for (unsigned int a = 0; a < pcMesh->mNumFaces; ++a) { + aiFace *pcFace = &pcMesh->mFaces[a]; + for (unsigned int q = 0; q < pcFace->mNumIndices; ++q, ++iIndex) { // need to build a clean list of bones, too - for (unsigned int i = 0;i < pcMesh->mNumBones;++i) - { - for (unsigned int boneIdx = 0; boneIdx < pcMesh->mBones[i]->mNumWeights; ++boneIdx) { - const aiVertexWeight &w = pcMesh->mBones[i]->mWeights[boneIdx]; - if(pcFace->mIndices[q] == w.mVertexId) { + for (unsigned int i = 0; i < pcMesh->mNumBones; ++i) { + for (unsigned int boneIdx = 0; boneIdx < pcMesh->mBones[i]->mNumWeights; ++boneIdx) { + const aiVertexWeight &w = pcMesh->mBones[i]->mWeights[boneIdx]; + if (pcFace->mIndices[q] == w.mVertexId) { aiVertexWeight wNew; wNew.mVertexId = iIndex; wNew.mWeight = w.mWeight; @@ -145,45 +134,38 @@ bool MakeVerboseFormatProcess::MakeVerboseFormat(aiMesh* pcMesh) pvPositions[iIndex] = pcMesh->mVertices[pcFace->mIndices[q]]; - if (pcMesh->HasNormals()) - { + if (pcMesh->HasNormals()) { pvNormals[iIndex] = pcMesh->mNormals[pcFace->mIndices[q]]; } - if (pcMesh->HasTangentsAndBitangents()) - { + if (pcMesh->HasTangentsAndBitangents()) { pvTangents[iIndex] = pcMesh->mTangents[pcFace->mIndices[q]]; pvBitangents[iIndex] = pcMesh->mBitangents[pcFace->mIndices[q]]; } unsigned int pp = 0; - while (pcMesh->HasTextureCoords(pp)) - { - apvTextureCoords[pp][iIndex] = pcMesh->mTextureCoords[pp][pcFace->mIndices[q]]; - ++pp; + while (pcMesh->HasTextureCoords(pp)) { + apvTextureCoords[pp][iIndex] = pcMesh->mTextureCoords[pp][pcFace->mIndices[q]]; + ++pp; } - pp = 0; - while (pcMesh->HasVertexColors(pp)) - { - apvColorSets[pp][iIndex] = pcMesh->mColors[pp][pcFace->mIndices[q]]; - ++pp; + pp = 0; + while (pcMesh->HasVertexColors(pp)) { + apvColorSets[pp][iIndex] = pcMesh->mColors[pp][pcFace->mIndices[q]]; + ++pp; } pcFace->mIndices[q] = iIndex; } } - - // build output vertex weights - for (unsigned int i = 0;i < pcMesh->mNumBones;++i) - { - delete [] pcMesh->mBones[i]->mWeights; + for (unsigned int i = 0; i < pcMesh->mNumBones; ++i) { + delete[] pcMesh->mBones[i]->mWeights; if (!newWeights[i].empty()) { pcMesh->mBones[i]->mWeights = new aiVertexWeight[newWeights[i].size()]; - aiVertexWeight *weightToCopy = &( newWeights[i][0] ); + aiVertexWeight *weightToCopy = &(newWeights[i][0]); memcpy(pcMesh->mBones[i]->mWeights, weightToCopy, - sizeof(aiVertexWeight) * newWeights[i].size()); + sizeof(aiVertexWeight) * newWeights[i].size()); } else { - pcMesh->mBones[i]->mWeights = NULL; + pcMesh->mBones[i]->mWeights = nullptr; } } delete[] newWeights; @@ -193,28 +175,24 @@ bool MakeVerboseFormatProcess::MakeVerboseFormat(aiMesh* pcMesh) pcMesh->mVertices = pvPositions; p = 0; - while (pcMesh->HasTextureCoords(p)) - { + while (pcMesh->HasTextureCoords(p)) { delete[] pcMesh->mTextureCoords[p]; pcMesh->mTextureCoords[p] = apvTextureCoords[p]; ++p; } p = 0; - while (pcMesh->HasVertexColors(p)) - { + while (pcMesh->HasVertexColors(p)) { delete[] pcMesh->mColors[p]; pcMesh->mColors[p] = apvColorSets[p]; ++p; } pcMesh->mNumVertices = iNumVerts; - if (pcMesh->HasNormals()) - { + if (pcMesh->HasNormals()) { delete[] pcMesh->mNormals; pcMesh->mNormals = pvNormals; } - if (pcMesh->HasTangentsAndBitangents()) - { + if (pcMesh->HasTangentsAndBitangents()) { delete[] pcMesh->mTangents; pcMesh->mTangents = pvTangents; delete[] pcMesh->mBitangents; @@ -223,15 +201,14 @@ bool MakeVerboseFormatProcess::MakeVerboseFormat(aiMesh* pcMesh) return (pcMesh->mNumVertices != iOldNumVertices); } - // ------------------------------------------------------------------------------------------------ -bool IsMeshInVerboseFormat(const aiMesh* mesh) { +bool IsMeshInVerboseFormat(const aiMesh *mesh) { // avoid slow vector specialization - std::vector seen(mesh->mNumVertices,0); - for(unsigned int i = 0; i < mesh->mNumFaces; ++i) { - const aiFace& f = mesh->mFaces[i]; - for(unsigned int j = 0; j < f.mNumIndices; ++j) { - if(++seen[f.mIndices[j]] == 2) { + std::vector seen(mesh->mNumVertices, 0); + for (unsigned int i = 0; i < mesh->mNumFaces; ++i) { + const aiFace &f = mesh->mFaces[i]; + for (unsigned int j = 0; j < f.mNumIndices; ++j) { + if (++seen[f.mIndices[j]] == 2) { // found a duplicate index return false; } @@ -242,9 +219,9 @@ bool IsMeshInVerboseFormat(const aiMesh* mesh) { } // ------------------------------------------------------------------------------------------------ -bool MakeVerboseFormatProcess::IsVerboseFormat(const aiScene* pScene) { - for(unsigned int i = 0; i < pScene->mNumMeshes; ++i) { - if(!IsMeshInVerboseFormat(pScene->mMeshes[i])) { +bool MakeVerboseFormatProcess::IsVerboseFormat(const aiScene *pScene) { + for (unsigned int i = 0; i < pScene->mNumMeshes; ++i) { + if (!IsMeshInVerboseFormat(pScene->mMeshes[i])) { return false; } } diff --git a/code/PostProcessing/PretransformVertices.cpp b/code/PostProcessing/PretransformVertices.cpp index 293a5c0ea..790ab086e 100644 --- a/code/PostProcessing/PretransformVertices.cpp +++ b/code/PostProcessing/PretransformVertices.cpp @@ -445,7 +445,7 @@ void PretransformVertices::Execute(aiScene *pScene) { delete mesh->mBones[a]; delete[] mesh->mBones; - mesh->mBones = NULL; + mesh->mBones = nullptr; } // now build a list of output meshes @@ -472,12 +472,12 @@ void PretransformVertices::Execute(aiScene *pScene) { pScene->mMeshes = npp; } - // now iterate through all meshes and transform them to worldspace + // now iterate through all meshes and transform them to world-space for (unsigned int i = 0; i < pScene->mNumMeshes; ++i) { ApplyTransform(pScene->mMeshes[i], *reinterpret_cast(pScene->mMeshes[i]->mBones)); // prevent improper destruction - pScene->mMeshes[i]->mBones = NULL; + pScene->mMeshes[i]->mBones = nullptr; pScene->mMeshes[i]->mNumBones = 0; } } else { @@ -539,22 +539,22 @@ void PretransformVertices::Execute(aiScene *pScene) { for (unsigned int i = 0; i < pScene->mNumMeshes; ++i) { aiMesh *mesh = pScene->mMeshes[i]; mesh->mNumBones = 0; - mesh->mBones = NULL; + mesh->mBones = nullptr; // we're reusing the face index arrays. avoid destruction for (unsigned int a = 0; a < mesh->mNumFaces; ++a) { mesh->mFaces[a].mNumIndices = 0; - mesh->mFaces[a].mIndices = NULL; + mesh->mFaces[a].mIndices = nullptr; } delete mesh; // Invalidate the contents of the old mesh array. We will most // likely have less output meshes now, so the last entries of - // the mesh array are not overridden. We set them to NULL to + // the mesh array are not overridden. We set them to nullptr to // make sure the developer gets notified when his application // attempts to access these fields ... - mesh = NULL; + mesh = nullptr; } // It is impossible that we have more output meshes than @@ -571,14 +571,14 @@ void PretransformVertices::Execute(aiScene *pScene) { delete pScene->mAnimations[i]; delete[] pScene->mAnimations; - pScene->mAnimations = NULL; + pScene->mAnimations = nullptr; pScene->mNumAnimations = 0; // --- we need to keep all cameras and lights for (unsigned int i = 0; i < pScene->mNumCameras; ++i) { aiCamera *cam = pScene->mCameras[i]; const aiNode *nd = pScene->mRootNode->FindNode(cam->mName); - ai_assert(NULL != nd); + ai_assert(nullptr != nd); // multiply all properties of the camera with the absolute // transformation of the corresponding node @@ -590,7 +590,7 @@ void PretransformVertices::Execute(aiScene *pScene) { for (unsigned int i = 0; i < pScene->mNumLights; ++i) { aiLight *l = pScene->mLights[i]; const aiNode *nd = pScene->mRootNode->FindNode(l->mName); - ai_assert(NULL != nd); + ai_assert(nullptr != nd); // multiply all properties of the camera with the absolute // transformation of the corresponding node diff --git a/code/PostProcessing/ProcessHelper.cpp b/code/PostProcessing/ProcessHelper.cpp index 123986438..e3a8aab8a 100644 --- a/code/PostProcessing/ProcessHelper.cpp +++ b/code/PostProcessing/ProcessHelper.cpp @@ -43,22 +43,19 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. /// @file ProcessHelper.cpp /** Implement shared utility functions for postprocessing steps */ - #include "ProcessHelper.h" - #include namespace Assimp { // ------------------------------------------------------------------------------- -void ConvertListToStrings(const std::string& in, std::list& out) -{ - const char* s = in.c_str(); +void ConvertListToStrings(const std::string &in, std::list &out) { + const char *s = in.c_str(); while (*s) { SkipSpacesAndLineEnd(&s); if (*s == '\'') { - const char* base = ++s; + const char *base = ++s; while (*s != '\'') { ++s; if (*s == '\0') { @@ -66,43 +63,39 @@ void ConvertListToStrings(const std::string& in, std::list& out) return; } } - out.push_back(std::string(base,(size_t)(s-base))); + out.push_back(std::string(base, (size_t)(s - base))); ++s; - } - else { + } else { out.push_back(GetNextToken(s)); } } } // ------------------------------------------------------------------------------- -void FindAABBTransformed (const aiMesh* mesh, aiVector3D& min, aiVector3D& max, - const aiMatrix4x4& m) -{ - min = aiVector3D ( ai_real( 10e10 ), ai_real( 10e10 ), ai_real( 10e10 ) ); - max = aiVector3D ( ai_real( -10e10 ), ai_real( -10e10 ), ai_real( -10e10 ) ); - for (unsigned int i = 0;i < mesh->mNumVertices;++i) - { +void FindAABBTransformed(const aiMesh *mesh, aiVector3D &min, aiVector3D &max, + const aiMatrix4x4 &m) { + min = aiVector3D(ai_real(10e10), ai_real(10e10), ai_real(10e10)); + max = aiVector3D(ai_real(-10e10), ai_real(-10e10), ai_real(-10e10)); + for (unsigned int i = 0; i < mesh->mNumVertices; ++i) { const aiVector3D v = m * mesh->mVertices[i]; - min = std::min(v,min); - max = std::max(v,max); + min = std::min(v, min); + max = std::max(v, max); } } // ------------------------------------------------------------------------------- -void FindMeshCenter (aiMesh* mesh, aiVector3D& out, aiVector3D& min, aiVector3D& max) -{ - ArrayBounds(mesh->mVertices,mesh->mNumVertices, min,max); - out = min + (max-min)*(ai_real)0.5; +void FindMeshCenter(aiMesh *mesh, aiVector3D &out, aiVector3D &min, aiVector3D &max) { + ArrayBounds(mesh->mVertices, mesh->mNumVertices, min, max); + out = min + (max - min) * (ai_real)0.5; } // ------------------------------------------------------------------------------- -void FindSceneCenter (aiScene* scene, aiVector3D& out, aiVector3D& min, aiVector3D& max) { - if ( NULL == scene ) { +void FindSceneCenter(aiScene *scene, aiVector3D &out, aiVector3D &min, aiVector3D &max) { + if (nullptr == scene) { return; } - if ( 0 == scene->mNumMeshes ) { + if (0 == scene->mNumMeshes) { return; } FindMeshCenter(scene->mMeshes[0], out, min, max); @@ -116,79 +109,71 @@ void FindSceneCenter (aiScene* scene, aiVector3D& out, aiVector3D& min, aiVector if (max[1] < tmax[1]) max[1] = tmax[1]; if (max[2] < tmax[2]) max[2] = tmax[2]; } - out = min + (max-min)*(ai_real)0.5; -} - - -// ------------------------------------------------------------------------------- -void FindMeshCenterTransformed (aiMesh* mesh, aiVector3D& out, aiVector3D& min, - aiVector3D& max, const aiMatrix4x4& m) -{ - FindAABBTransformed(mesh,min,max,m); - out = min + (max-min)*(ai_real)0.5; + out = min + (max - min) * (ai_real)0.5; } // ------------------------------------------------------------------------------- -void FindMeshCenter (aiMesh* mesh, aiVector3D& out) -{ - aiVector3D min,max; - FindMeshCenter(mesh,out,min,max); +void FindMeshCenterTransformed(aiMesh *mesh, aiVector3D &out, aiVector3D &min, + aiVector3D &max, const aiMatrix4x4 &m) { + FindAABBTransformed(mesh, min, max, m); + out = min + (max - min) * (ai_real)0.5; } // ------------------------------------------------------------------------------- -void FindMeshCenterTransformed (aiMesh* mesh, aiVector3D& out, - const aiMatrix4x4& m) -{ - aiVector3D min,max; - FindMeshCenterTransformed(mesh,out,min,max,m); +void FindMeshCenter(aiMesh *mesh, aiVector3D &out) { + aiVector3D min, max; + FindMeshCenter(mesh, out, min, max); } // ------------------------------------------------------------------------------- -ai_real ComputePositionEpsilon(const aiMesh* pMesh) -{ - const ai_real epsilon = ai_real( 1e-4 ); +void FindMeshCenterTransformed(aiMesh *mesh, aiVector3D &out, + const aiMatrix4x4 &m) { + aiVector3D min, max; + FindMeshCenterTransformed(mesh, out, min, max, m); +} + +// ------------------------------------------------------------------------------- +ai_real ComputePositionEpsilon(const aiMesh *pMesh) { + const ai_real epsilon = ai_real(1e-4); // calculate the position bounds so we have a reliable epsilon to check position differences against aiVector3D minVec, maxVec; - ArrayBounds(pMesh->mVertices,pMesh->mNumVertices,minVec,maxVec); + ArrayBounds(pMesh->mVertices, pMesh->mNumVertices, minVec, maxVec); return (maxVec - minVec).Length() * epsilon; } // ------------------------------------------------------------------------------- -ai_real ComputePositionEpsilon(const aiMesh* const* pMeshes, size_t num) -{ - ai_assert( NULL != pMeshes ); +ai_real ComputePositionEpsilon(const aiMesh *const *pMeshes, size_t num) { + ai_assert(nullptr != pMeshes); - const ai_real epsilon = ai_real( 1e-4 ); + const ai_real epsilon = ai_real(1e-4); // calculate the position bounds so we have a reliable epsilon to check position differences against aiVector3D minVec, maxVec, mi, ma; - MinMaxChooser()(minVec,maxVec); + MinMaxChooser()(minVec, maxVec); for (size_t a = 0; a < num; ++a) { - const aiMesh* pMesh = pMeshes[a]; - ArrayBounds(pMesh->mVertices,pMesh->mNumVertices,mi,ma); + const aiMesh *pMesh = pMeshes[a]; + ArrayBounds(pMesh->mVertices, pMesh->mNumVertices, mi, ma); - minVec = std::min(minVec,mi); - maxVec = std::max(maxVec,ma); + minVec = std::min(minVec, mi); + maxVec = std::max(maxVec, ma); } return (maxVec - minVec).Length() * epsilon; } - // ------------------------------------------------------------------------------- -unsigned int GetMeshVFormatUnique(const aiMesh* pcMesh) -{ - ai_assert(NULL != pcMesh); +unsigned int GetMeshVFormatUnique(const aiMesh *pcMesh) { + ai_assert(nullptr != pcMesh); // FIX: the hash may never be 0. Otherwise a comparison against // nullptr could be successful unsigned int iRet = 1; // normals - if (pcMesh->HasNormals())iRet |= 0x2; + if (pcMesh->HasNormals()) iRet |= 0x2; // tangents and bitangents - if (pcMesh->HasTangentsAndBitangents())iRet |= 0x4; + if (pcMesh->HasTangentsAndBitangents()) iRet |= 0x4; #ifdef BOOST_STATIC_ASSERT BOOST_STATIC_ASSERT(8 >= AI_MAX_NUMBER_OF_COLOR_SETS); @@ -197,8 +182,7 @@ unsigned int GetMeshVFormatUnique(const aiMesh* pcMesh) // texture coordinates unsigned int p = 0; - while (pcMesh->HasTextureCoords(p)) - { + while (pcMesh->HasTextureCoords(p)) { iRet |= (0x100 << p); if (3 == pcMesh->mNumUVComponents[p]) iRet |= (0x10000 << p); @@ -207,34 +191,32 @@ unsigned int GetMeshVFormatUnique(const aiMesh* pcMesh) } // vertex colors p = 0; - while (pcMesh->HasVertexColors(p))iRet |= (0x1000000 << p++); + while (pcMesh->HasVertexColors(p)) + iRet |= (0x1000000 << p++); return iRet; } // ------------------------------------------------------------------------------- -VertexWeightTable* ComputeVertexBoneWeightTable(const aiMesh* pMesh) -{ +VertexWeightTable *ComputeVertexBoneWeightTable(const aiMesh *pMesh) { if (!pMesh || !pMesh->mNumVertices || !pMesh->mNumBones) { - return NULL; + return nullptr; } - VertexWeightTable* avPerVertexWeights = new VertexWeightTable[pMesh->mNumVertices]; - for (unsigned int i = 0; i < pMesh->mNumBones;++i) { + VertexWeightTable *avPerVertexWeights = new VertexWeightTable[pMesh->mNumVertices]; + for (unsigned int i = 0; i < pMesh->mNumBones; ++i) { - aiBone* bone = pMesh->mBones[i]; - for (unsigned int a = 0; a < bone->mNumWeights;++a) { - const aiVertexWeight& weight = bone->mWeights[a]; - avPerVertexWeights[weight.mVertexId].push_back( std::pair(i,weight.mWeight) ); + aiBone *bone = pMesh->mBones[i]; + for (unsigned int a = 0; a < bone->mNumWeights; ++a) { + const aiVertexWeight &weight = bone->mWeights[a]; + avPerVertexWeights[weight.mVertexId].push_back(std::pair(i, weight.mWeight)); } } return avPerVertexWeights; } // ------------------------------------------------------------------------------- -const char* MappingTypeToString(aiTextureMapping in) -{ - switch (in) - { +const char *MappingTypeToString(aiTextureMapping in) { + switch (in) { case aiTextureMapping_UV: return "UV"; case aiTextureMapping_BOX: @@ -252,24 +234,22 @@ const char* MappingTypeToString(aiTextureMapping in) } ai_assert(false); - return "BUG"; + return "BUG"; } - // ------------------------------------------------------------------------------- -aiMesh* MakeSubmesh(const aiMesh *pMesh, const std::vector &subMeshFaces, unsigned int subFlags) -{ +aiMesh *MakeSubmesh(const aiMesh *pMesh, const std::vector &subMeshFaces, unsigned int subFlags) { aiMesh *oMesh = new aiMesh(); - std::vector vMap(pMesh->mNumVertices,UINT_MAX); + std::vector vMap(pMesh->mNumVertices, UINT_MAX); size_t numSubVerts = 0; size_t numSubFaces = subMeshFaces.size(); - for(unsigned int i=0;imFaces[subMeshFaces[i]]; - for(unsigned int j=0;j(numSubVerts++); } } @@ -285,114 +265,114 @@ aiMesh* MakeSubmesh(const aiMesh *pMesh, const std::vector &subMes oMesh->mNumFaces = static_cast(subMeshFaces.size()); oMesh->mNumVertices = static_cast(numSubVerts); oMesh->mVertices = new aiVector3D[numSubVerts]; - if( pMesh->HasNormals() ) { + if (pMesh->HasNormals()) { oMesh->mNormals = new aiVector3D[numSubVerts]; } - if( pMesh->HasTangentsAndBitangents() ) { + if (pMesh->HasTangentsAndBitangents()) { oMesh->mTangents = new aiVector3D[numSubVerts]; oMesh->mBitangents = new aiVector3D[numSubVerts]; } - for( size_t a = 0; pMesh->HasTextureCoords(static_cast(a)) ; ++a ) { + for (size_t a = 0; pMesh->HasTextureCoords(static_cast(a)); ++a) { oMesh->mTextureCoords[a] = new aiVector3D[numSubVerts]; oMesh->mNumUVComponents[a] = pMesh->mNumUVComponents[a]; } - for( size_t a = 0; pMesh->HasVertexColors( static_cast(a)); ++a ) { + for (size_t a = 0; pMesh->HasVertexColors(static_cast(a)); ++a) { oMesh->mColors[a] = new aiColor4D[numSubVerts]; } // and copy over the data, generating faces with linear indices along the way oMesh->mFaces = new aiFace[numSubFaces]; - for(unsigned int a = 0; a < numSubFaces; ++a ) { + for (unsigned int a = 0; a < numSubFaces; ++a) { - const aiFace& srcFace = pMesh->mFaces[subMeshFaces[a]]; - aiFace& dstFace = oMesh->mFaces[a]; + const aiFace &srcFace = pMesh->mFaces[subMeshFaces[a]]; + aiFace &dstFace = oMesh->mFaces[a]; dstFace.mNumIndices = srcFace.mNumIndices; dstFace.mIndices = new unsigned int[dstFace.mNumIndices]; // accumulate linearly all the vertices of the source face - for( size_t b = 0; b < dstFace.mNumIndices; ++b ) { + for (size_t b = 0; b < dstFace.mNumIndices; ++b) { dstFace.mIndices[b] = vMap[srcFace.mIndices[b]]; } } - for(unsigned int srcIndex = 0; srcIndex < pMesh->mNumVertices; ++srcIndex ) { + for (unsigned int srcIndex = 0; srcIndex < pMesh->mNumVertices; ++srcIndex) { unsigned int nvi = vMap[srcIndex]; - if(nvi==UINT_MAX) { + if (nvi == UINT_MAX) { continue; } oMesh->mVertices[nvi] = pMesh->mVertices[srcIndex]; - if( pMesh->HasNormals() ) { + if (pMesh->HasNormals()) { oMesh->mNormals[nvi] = pMesh->mNormals[srcIndex]; } - if( pMesh->HasTangentsAndBitangents() ) { + if (pMesh->HasTangentsAndBitangents()) { oMesh->mTangents[nvi] = pMesh->mTangents[srcIndex]; oMesh->mBitangents[nvi] = pMesh->mBitangents[srcIndex]; } - for( size_t c = 0, cc = pMesh->GetNumUVChannels(); c < cc; ++c ) { - oMesh->mTextureCoords[c][nvi] = pMesh->mTextureCoords[c][srcIndex]; + for (size_t c = 0, cc = pMesh->GetNumUVChannels(); c < cc; ++c) { + oMesh->mTextureCoords[c][nvi] = pMesh->mTextureCoords[c][srcIndex]; } - for( size_t c = 0, cc = pMesh->GetNumColorChannels(); c < cc; ++c ) { + for (size_t c = 0, cc = pMesh->GetNumColorChannels(); c < cc; ++c) { oMesh->mColors[c][nvi] = pMesh->mColors[c][srcIndex]; } } - if(~subFlags&AI_SUBMESH_FLAGS_SANS_BONES) { - std::vector subBones(pMesh->mNumBones,0); + if (~subFlags & AI_SUBMESH_FLAGS_SANS_BONES) { + std::vector subBones(pMesh->mNumBones, 0); - for(unsigned int a=0;amNumBones;++a) { - const aiBone* bone = pMesh->mBones[a]; + for (unsigned int a = 0; a < pMesh->mNumBones; ++a) { + const aiBone *bone = pMesh->mBones[a]; - for(unsigned int b=0;bmNumWeights;b++) { + for (unsigned int b = 0; b < bone->mNumWeights; b++) { unsigned int v = vMap[bone->mWeights[b].mVertexId]; - if(v!=UINT_MAX) { + if (v != UINT_MAX) { subBones[a]++; } } } - for(unsigned int a=0;amNumBones;++a) { - if(subBones[a]>0) { + for (unsigned int a = 0; a < pMesh->mNumBones; ++a) { + if (subBones[a] > 0) { oMesh->mNumBones++; } } - if(oMesh->mNumBones) { - oMesh->mBones = new aiBone*[oMesh->mNumBones](); + if (oMesh->mNumBones) { + oMesh->mBones = new aiBone *[oMesh->mNumBones](); unsigned int nbParanoia = oMesh->mNumBones; oMesh->mNumBones = 0; //rewind - for(unsigned int a=0;amNumBones;++a) { - if(subBones[a]==0) { + for (unsigned int a = 0; a < pMesh->mNumBones; ++a) { + if (subBones[a] == 0) { continue; } aiBone *newBone = new aiBone; oMesh->mBones[oMesh->mNumBones++] = newBone; - const aiBone* bone = pMesh->mBones[a]; + const aiBone *bone = pMesh->mBones[a]; newBone->mName = bone->mName; newBone->mOffsetMatrix = bone->mOffsetMatrix; newBone->mWeights = new aiVertexWeight[subBones[a]]; - for(unsigned int b=0;bmNumWeights;b++) { + for (unsigned int b = 0; b < bone->mNumWeights; b++) { const unsigned int v = vMap[bone->mWeights[b].mVertexId]; - if(v!=UINT_MAX) { - aiVertexWeight w(v,bone->mWeights[b].mWeight); + if (v != UINT_MAX) { + aiVertexWeight w(v, bone->mWeights[b].mWeight); newBone->mWeights[newBone->mNumWeights++] = w; } } } - ai_assert(nbParanoia==oMesh->mNumBones); + ai_assert(nbParanoia == oMesh->mNumBones); (void)nbParanoia; // remove compiler warning on release build } } diff --git a/code/PostProcessing/ProcessHelper.h b/code/PostProcessing/ProcessHelper.h index 5762fbb35..660555ef0 100644 --- a/code/PostProcessing/ProcessHelper.h +++ b/code/PostProcessing/ProcessHelper.h @@ -43,16 +43,16 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef AI_PROCESS_HELPER_H_INCLUDED #define AI_PROCESS_HELPER_H_INCLUDED -#include #include -#include #include -#include +#include +#include #include +#include -#include #include "Common/BaseProcess.h" #include +#include #include @@ -63,86 +63,83 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifdef __cplusplus namespace std { - // std::min for aiVector3D - template - inline ::aiVector3t min (const ::aiVector3t& a, const ::aiVector3t& b) { - return ::aiVector3t (min(a.x,b.x),min(a.y,b.y),min(a.z,b.z)); - } +// std::min for aiVector3D +template +inline ::aiVector3t min(const ::aiVector3t &a, const ::aiVector3t &b) { + return ::aiVector3t(min(a.x, b.x), min(a.y, b.y), min(a.z, b.z)); +} - // std::max for aiVector3t - template - inline ::aiVector3t max (const ::aiVector3t& a, const ::aiVector3t& b) { - return ::aiVector3t (max(a.x,b.x),max(a.y,b.y),max(a.z,b.z)); - } +// std::max for aiVector3t +template +inline ::aiVector3t max(const ::aiVector3t &a, const ::aiVector3t &b) { + return ::aiVector3t(max(a.x, b.x), max(a.y, b.y), max(a.z, b.z)); +} - // std::min for aiVector2t - template - inline ::aiVector2t min (const ::aiVector2t& a, const ::aiVector2t& b) { - return ::aiVector2t (min(a.x,b.x),min(a.y,b.y)); - } +// std::min for aiVector2t +template +inline ::aiVector2t min(const ::aiVector2t &a, const ::aiVector2t &b) { + return ::aiVector2t(min(a.x, b.x), min(a.y, b.y)); +} - // std::max for aiVector2t - template - inline ::aiVector2t max (const ::aiVector2t& a, const ::aiVector2t& b) { - return ::aiVector2t (max(a.x,b.x),max(a.y,b.y)); - } +// std::max for aiVector2t +template +inline ::aiVector2t max(const ::aiVector2t &a, const ::aiVector2t &b) { + return ::aiVector2t(max(a.x, b.x), max(a.y, b.y)); +} - // std::min for aiColor4D - template - inline ::aiColor4t min (const ::aiColor4t& a, const ::aiColor4t& b) { - return ::aiColor4t (min(a.r,b.r),min(a.g,b.g),min(a.b,b.b),min(a.a,b.a)); - } +// std::min for aiColor4D +template +inline ::aiColor4t min(const ::aiColor4t &a, const ::aiColor4t &b) { + return ::aiColor4t(min(a.r, b.r), min(a.g, b.g), min(a.b, b.b), min(a.a, b.a)); +} - // std::max for aiColor4D - template - inline ::aiColor4t max (const ::aiColor4t& a, const ::aiColor4t& b) { - return ::aiColor4t (max(a.r,b.r),max(a.g,b.g),max(a.b,b.b),max(a.a,b.a)); - } +// std::max for aiColor4D +template +inline ::aiColor4t max(const ::aiColor4t &a, const ::aiColor4t &b) { + return ::aiColor4t(max(a.r, b.r), max(a.g, b.g), max(a.b, b.b), max(a.a, b.a)); +} +// std::min for aiQuaterniont +template +inline ::aiQuaterniont min(const ::aiQuaterniont &a, const ::aiQuaterniont &b) { + return ::aiQuaterniont(min(a.w, b.w), min(a.x, b.x), min(a.y, b.y), min(a.z, b.z)); +} - // std::min for aiQuaterniont - template - inline ::aiQuaterniont min (const ::aiQuaterniont& a, const ::aiQuaterniont& b) { - return ::aiQuaterniont (min(a.w,b.w),min(a.x,b.x),min(a.y,b.y),min(a.z,b.z)); - } +// std::max for aiQuaterniont +template +inline ::aiQuaterniont max(const ::aiQuaterniont &a, const ::aiQuaterniont &b) { + return ::aiQuaterniont(max(a.w, b.w), max(a.x, b.x), max(a.y, b.y), max(a.z, b.z)); +} - // std::max for aiQuaterniont - template - inline ::aiQuaterniont max (const ::aiQuaterniont& a, const ::aiQuaterniont& b) { - return ::aiQuaterniont (max(a.w,b.w),max(a.x,b.x),max(a.y,b.y),max(a.z,b.z)); - } +// std::min for aiVectorKey +inline ::aiVectorKey min(const ::aiVectorKey &a, const ::aiVectorKey &b) { + return ::aiVectorKey(min(a.mTime, b.mTime), min(a.mValue, b.mValue)); +} +// std::max for aiVectorKey +inline ::aiVectorKey max(const ::aiVectorKey &a, const ::aiVectorKey &b) { + return ::aiVectorKey(max(a.mTime, b.mTime), max(a.mValue, b.mValue)); +} +// std::min for aiQuatKey +inline ::aiQuatKey min(const ::aiQuatKey &a, const ::aiQuatKey &b) { + return ::aiQuatKey(min(a.mTime, b.mTime), min(a.mValue, b.mValue)); +} - // std::min for aiVectorKey - inline ::aiVectorKey min (const ::aiVectorKey& a, const ::aiVectorKey& b) { - return ::aiVectorKey (min(a.mTime,b.mTime),min(a.mValue,b.mValue)); - } +// std::max for aiQuatKey +inline ::aiQuatKey max(const ::aiQuatKey &a, const ::aiQuatKey &b) { + return ::aiQuatKey(max(a.mTime, b.mTime), max(a.mValue, b.mValue)); +} - // std::max for aiVectorKey - inline ::aiVectorKey max (const ::aiVectorKey& a, const ::aiVectorKey& b) { - return ::aiVectorKey (max(a.mTime,b.mTime),max(a.mValue,b.mValue)); - } +// std::min for aiVertexWeight +inline ::aiVertexWeight min(const ::aiVertexWeight &a, const ::aiVertexWeight &b) { + return ::aiVertexWeight(min(a.mVertexId, b.mVertexId), min(a.mWeight, b.mWeight)); +} - // std::min for aiQuatKey - inline ::aiQuatKey min (const ::aiQuatKey& a, const ::aiQuatKey& b) { - return ::aiQuatKey (min(a.mTime,b.mTime),min(a.mValue,b.mValue)); - } - - // std::max for aiQuatKey - inline ::aiQuatKey max (const ::aiQuatKey& a, const ::aiQuatKey& b) { - return ::aiQuatKey (max(a.mTime,b.mTime),max(a.mValue,b.mValue)); - } - - // std::min for aiVertexWeight - inline ::aiVertexWeight min (const ::aiVertexWeight& a, const ::aiVertexWeight& b) { - return ::aiVertexWeight (min(a.mVertexId,b.mVertexId),min(a.mWeight,b.mWeight)); - } - - // std::max for aiVertexWeight - inline ::aiVertexWeight max (const ::aiVertexWeight& a, const ::aiVertexWeight& b) { - return ::aiVertexWeight (max(a.mVertexId,b.mVertexId),max(a.mWeight,b.mWeight)); - } +// std::max for aiVertexWeight +inline ::aiVertexWeight max(const ::aiVertexWeight &a, const ::aiVertexWeight &b) { + return ::aiVertexWeight(max(a.mVertexId, b.mVertexId), max(a.mWeight, b.mWeight)); +} } // end namespace std #endif // !! C++ @@ -154,60 +151,80 @@ namespace Assimp { template struct MinMaxChooser; -template <> struct MinMaxChooser { - void operator ()(float& min,float& max) { +template <> +struct MinMaxChooser { + void operator()(float &min, float &max) { max = -1e10f; - min = 1e10f; -}}; -template <> struct MinMaxChooser { - void operator ()(double& min,double& max) { + min = 1e10f; + } +}; +template <> +struct MinMaxChooser { + void operator()(double &min, double &max) { max = -1e10; - min = 1e10; -}}; -template <> struct MinMaxChooser { - void operator ()(unsigned int& min,unsigned int& max) { + min = 1e10; + } +}; +template <> +struct MinMaxChooser { + void operator()(unsigned int &min, unsigned int &max) { max = 0; - min = (1u<<(sizeof(unsigned int)*8-1)); -}}; + min = (1u << (sizeof(unsigned int) * 8 - 1)); + } +}; -template struct MinMaxChooser< aiVector3t > { - void operator ()(aiVector3t& min,aiVector3t& max) { - max = aiVector3t(-1e10f,-1e10f,-1e10f); - min = aiVector3t( 1e10f, 1e10f, 1e10f); -}}; -template struct MinMaxChooser< aiVector2t > { - void operator ()(aiVector2t& min,aiVector2t& max) { - max = aiVector2t(-1e10f,-1e10f); - min = aiVector2t( 1e10f, 1e10f); - }}; -template struct MinMaxChooser< aiColor4t > { - void operator ()(aiColor4t& min,aiColor4t& max) { - max = aiColor4t(-1e10f,-1e10f,-1e10f,-1e10f); - min = aiColor4t( 1e10f, 1e10f, 1e10f, 1e10f); -}}; +template +struct MinMaxChooser> { + void operator()(aiVector3t &min, aiVector3t &max) { + max = aiVector3t(-1e10f, -1e10f, -1e10f); + min = aiVector3t(1e10f, 1e10f, 1e10f); + } +}; +template +struct MinMaxChooser> { + void operator()(aiVector2t &min, aiVector2t &max) { + max = aiVector2t(-1e10f, -1e10f); + min = aiVector2t(1e10f, 1e10f); + } +}; +template +struct MinMaxChooser> { + void operator()(aiColor4t &min, aiColor4t &max) { + max = aiColor4t(-1e10f, -1e10f, -1e10f, -1e10f); + min = aiColor4t(1e10f, 1e10f, 1e10f, 1e10f); + } +}; -template struct MinMaxChooser< aiQuaterniont > { - void operator ()(aiQuaterniont& min,aiQuaterniont& max) { - max = aiQuaterniont(-1e10f,-1e10f,-1e10f,-1e10f); - min = aiQuaterniont( 1e10f, 1e10f, 1e10f, 1e10f); -}}; +template +struct MinMaxChooser> { + void operator()(aiQuaterniont &min, aiQuaterniont &max) { + max = aiQuaterniont(-1e10f, -1e10f, -1e10f, -1e10f); + min = aiQuaterniont(1e10f, 1e10f, 1e10f, 1e10f); + } +}; -template <> struct MinMaxChooser { - void operator ()(aiVectorKey& min,aiVectorKey& max) { - MinMaxChooser()(min.mTime,max.mTime); - MinMaxChooser()(min.mValue,max.mValue); -}}; -template <> struct MinMaxChooser { - void operator ()(aiQuatKey& min,aiQuatKey& max) { - MinMaxChooser()(min.mTime,max.mTime); - MinMaxChooser()(min.mValue,max.mValue); -}}; +template <> +struct MinMaxChooser { + void operator()(aiVectorKey &min, aiVectorKey &max) { + MinMaxChooser()(min.mTime, max.mTime); + MinMaxChooser()(min.mValue, max.mValue); + } +}; +template <> +struct MinMaxChooser { + void operator()(aiQuatKey &min, aiQuatKey &max) { + MinMaxChooser()(min.mTime, max.mTime); + MinMaxChooser()(min.mValue, max.mValue); + } +}; -template <> struct MinMaxChooser { - void operator ()(aiVertexWeight& min,aiVertexWeight& max) { - MinMaxChooser()(min.mVertexId,max.mVertexId); - MinMaxChooser()(min.mWeight,max.mWeight); -}}; +template <> +struct MinMaxChooser { + void operator()(aiVertexWeight &min, aiVertexWeight &max) { + MinMaxChooser()(min.mVertexId, max.mVertexId); + MinMaxChooser()(min.mWeight, max.mWeight); + } +}; // ------------------------------------------------------------------------------- /** @brief Find the min/max values of an array of Ts @@ -217,36 +234,31 @@ template <> struct MinMaxChooser { * @param[out] max maximum value */ template -inline void ArrayBounds(const T* in, unsigned int size, T& min, T& max) -{ - MinMaxChooser ()(min,max); - for (unsigned int i = 0; i < size;++i) { - min = std::min(in[i],min); - max = std::max(in[i],max); +inline void ArrayBounds(const T *in, unsigned int size, T &min, T &max) { + MinMaxChooser()(min, max); + for (unsigned int i = 0; i < size; ++i) { + min = std::min(in[i], min); + max = std::max(in[i], max); } } - // ------------------------------------------------------------------------------- /** Little helper function to calculate the quadratic difference * of two colours. * @param pColor1 First color * @param pColor2 second color * @return Quadratic color difference */ -inline ai_real GetColorDifference( const aiColor4D& pColor1, const aiColor4D& pColor2) -{ - const aiColor4D c (pColor1.r - pColor2.r, pColor1.g - pColor2.g, pColor1.b - pColor2.b, pColor1.a - pColor2.a); - return c.r*c.r + c.g*c.g + c.b*c.b + c.a*c.a; +inline ai_real GetColorDifference(const aiColor4D &pColor1, const aiColor4D &pColor2) { + const aiColor4D c(pColor1.r - pColor2.r, pColor1.g - pColor2.g, pColor1.b - pColor2.b, pColor1.a - pColor2.a); + return c.r * c.r + c.g * c.g + c.b * c.b + c.a * c.a; } - // ------------------------------------------------------------------------------- /** @brief Extract single strings from a list of identifiers * @param in Input string list. * @param out Receives a list of clean output strings * @sdee #AI_CONFIG_PP_OG_EXCLUDE_LIST */ -void ConvertListToStrings(const std::string& in, std::list& out); - +void ConvertListToStrings(const std::string &in, std::list &out); // ------------------------------------------------------------------------------- /** @brief Compute the AABB of a mesh after applying a given transform @@ -254,8 +266,7 @@ void ConvertListToStrings(const std::string& in, std::list& out); * @param[out] min Receives minimum transformed vertex * @param[out] max Receives maximum transformed vertex * @param m Transformation matrix to be applied */ -void FindAABBTransformed (const aiMesh* mesh, aiVector3D& min, aiVector3D& max, const aiMatrix4x4& m); - +void FindAABBTransformed(const aiMesh *mesh, aiVector3D &min, aiVector3D &max, const aiMatrix4x4 &m); // ------------------------------------------------------------------------------- /** @brief Helper function to determine the 'real' center of a mesh @@ -265,7 +276,7 @@ void FindAABBTransformed (const aiMesh* mesh, aiVector3D& min, aiVector3D& max, * @param[out] min Minimum vertex of the mesh * @param[out] max maximum vertex of the mesh * @param[out] out Center point */ -void FindMeshCenter (aiMesh* mesh, aiVector3D& out, aiVector3D& min, aiVector3D& max); +void FindMeshCenter(aiMesh *mesh, aiVector3D &out, aiVector3D &min, aiVector3D &max); // ------------------------------------------------------------------------------- /** @brief Helper function to determine the 'real' center of a scene @@ -275,106 +286,90 @@ void FindMeshCenter (aiMesh* mesh, aiVector3D& out, aiVector3D& min, aiVector3D& * @param[out] min Minimum vertex of the scene * @param[out] max maximum vertex of the scene * @param[out] out Center point */ -void FindSceneCenter (aiScene* scene, aiVector3D& out, aiVector3D& min, aiVector3D& max); - +void FindSceneCenter(aiScene *scene, aiVector3D &out, aiVector3D &min, aiVector3D &max); // ------------------------------------------------------------------------------- // Helper function to determine the 'real' center of a mesh after applying a given transform -void FindMeshCenterTransformed (aiMesh* mesh, aiVector3D& out, aiVector3D& min,aiVector3D& max, const aiMatrix4x4& m); - +void FindMeshCenterTransformed(aiMesh *mesh, aiVector3D &out, aiVector3D &min, aiVector3D &max, const aiMatrix4x4 &m); // ------------------------------------------------------------------------------- // Helper function to determine the 'real' center of a mesh -void FindMeshCenter (aiMesh* mesh, aiVector3D& out); - +void FindMeshCenter(aiMesh *mesh, aiVector3D &out); // ------------------------------------------------------------------------------- // Helper function to determine the 'real' center of a mesh after applying a given transform -void FindMeshCenterTransformed (aiMesh* mesh, aiVector3D& out,const aiMatrix4x4& m); - +void FindMeshCenterTransformed(aiMesh *mesh, aiVector3D &out, const aiMatrix4x4 &m); // ------------------------------------------------------------------------------- // Compute a good epsilon value for position comparisons on a mesh -ai_real ComputePositionEpsilon(const aiMesh* pMesh); - +ai_real ComputePositionEpsilon(const aiMesh *pMesh); // ------------------------------------------------------------------------------- // Compute a good epsilon value for position comparisons on a array of meshes -ai_real ComputePositionEpsilon(const aiMesh* const* pMeshes, size_t num); - +ai_real ComputePositionEpsilon(const aiMesh *const *pMeshes, size_t num); // ------------------------------------------------------------------------------- // Compute an unique value for the vertex format of a mesh -unsigned int GetMeshVFormatUnique(const aiMesh* pcMesh); - +unsigned int GetMeshVFormatUnique(const aiMesh *pcMesh); // defs for ComputeVertexBoneWeightTable() -typedef std::pair PerVertexWeight; -typedef std::vector VertexWeightTable; +typedef std::pair PerVertexWeight; +typedef std::vector VertexWeightTable; // ------------------------------------------------------------------------------- // Compute a per-vertex bone weight table -VertexWeightTable* ComputeVertexBoneWeightTable(const aiMesh* pMesh); +VertexWeightTable *ComputeVertexBoneWeightTable(const aiMesh *pMesh); // ------------------------------------------------------------------------------- // Get a string for a given aiTextureMapping -const char* MappingTypeToString(aiTextureMapping in); - +const char *MappingTypeToString(aiTextureMapping in); // flags for MakeSubmesh() #define AI_SUBMESH_FLAGS_SANS_BONES 0x1 // ------------------------------------------------------------------------------- // Split a mesh given a list of faces to be contained in the sub mesh -aiMesh* MakeSubmesh(const aiMesh *superMesh, const std::vector &subMeshFaces, unsigned int subFlags); +aiMesh *MakeSubmesh(const aiMesh *superMesh, const std::vector &subMeshFaces, unsigned int subFlags); // ------------------------------------------------------------------------------- // Utility postprocess step to share the spatial sort tree between // all steps which use it to speedup its computations. -class ComputeSpatialSortProcess : public BaseProcess -{ - bool IsActive( unsigned int pFlags) const - { - return NULL != shared && 0 != (pFlags & (aiProcess_CalcTangentSpace | - aiProcess_GenNormals | aiProcess_JoinIdenticalVertices)); +class ComputeSpatialSortProcess : public BaseProcess { + bool IsActive(unsigned int pFlags) const { + return nullptr != shared && 0 != (pFlags & (aiProcess_CalcTangentSpace | + aiProcess_GenNormals | aiProcess_JoinIdenticalVertices)); } - void Execute( aiScene* pScene) - { + void Execute(aiScene *pScene) { typedef std::pair _Type; ASSIMP_LOG_DEBUG("Generate spatially-sorted vertex cache"); - std::vector<_Type>* p = new std::vector<_Type>(pScene->mNumMeshes); + std::vector<_Type> *p = new std::vector<_Type>(pScene->mNumMeshes); std::vector<_Type>::iterator it = p->begin(); for (unsigned int i = 0; i < pScene->mNumMeshes; ++i, ++it) { - aiMesh* mesh = pScene->mMeshes[i]; - _Type& blubb = *it; - blubb.first.Fill(mesh->mVertices,mesh->mNumVertices,sizeof(aiVector3D)); + aiMesh *mesh = pScene->mMeshes[i]; + _Type &blubb = *it; + blubb.first.Fill(mesh->mVertices, mesh->mNumVertices, sizeof(aiVector3D)); blubb.second = ComputePositionEpsilon(mesh); } - shared->AddProperty(AI_SPP_SPATIAL_SORT,p); + shared->AddProperty(AI_SPP_SPATIAL_SORT, p); } }; // ------------------------------------------------------------------------------- // ... and the same again to cleanup the whole stuff -class DestroySpatialSortProcess : public BaseProcess -{ - bool IsActive( unsigned int pFlags) const - { - return NULL != shared && 0 != (pFlags & (aiProcess_CalcTangentSpace | - aiProcess_GenNormals | aiProcess_JoinIdenticalVertices)); +class DestroySpatialSortProcess : public BaseProcess { + bool IsActive(unsigned int pFlags) const { + return nullptr != shared && 0 != (pFlags & (aiProcess_CalcTangentSpace | + aiProcess_GenNormals | aiProcess_JoinIdenticalVertices)); } - void Execute( aiScene* /*pScene*/) - { + void Execute(aiScene * /*pScene*/) { shared->RemoveProperty(AI_SPP_SPATIAL_SORT); } }; - - -} // ! namespace Assimp +} // namespace Assimp #endif // !! AI_PROCESS_HELPER_H_INCLUDED diff --git a/code/PostProcessing/RemoveRedundantMaterials.cpp b/code/PostProcessing/RemoveRedundantMaterials.cpp index 7f8b77d20..498b40a34 100644 --- a/code/PostProcessing/RemoveRedundantMaterials.cpp +++ b/code/PostProcessing/RemoveRedundantMaterials.cpp @@ -197,7 +197,7 @@ void RemoveRedundantMatsProcess::Execute( aiScene* pScene) // update all material indices for (unsigned int p = 0; p < pScene->mNumMeshes;++p) { aiMesh* mesh = pScene->mMeshes[p]; - ai_assert( NULL!=mesh ); + ai_assert(nullptr != mesh); mesh->mMaterialIndex = aiMappingTable[mesh->mMaterialIndex]; } // delete the old material list diff --git a/code/PostProcessing/RemoveVCProcess.cpp b/code/PostProcessing/RemoveVCProcess.cpp index 5ff5b55fa..82540996e 100644 --- a/code/PostProcessing/RemoveVCProcess.cpp +++ b/code/PostProcessing/RemoveVCProcess.cpp @@ -44,43 +44,37 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * any parts of the mesh structure from the imported data. */ - #include "RemoveVCProcess.h" #include -#include #include +#include using namespace Assimp; // ------------------------------------------------------------------------------------------------ // Constructor to be privately used by Importer RemoveVCProcess::RemoveVCProcess() : - configDeleteFlags() - , mScene() -{} + configDeleteFlags(), mScene() {} // ------------------------------------------------------------------------------------------------ // Destructor, private as well -RemoveVCProcess::~RemoveVCProcess() -{} +RemoveVCProcess::~RemoveVCProcess() {} // ------------------------------------------------------------------------------------------------ // Returns whether the processing step is present in the given flag field. -bool RemoveVCProcess::IsActive( unsigned int pFlags) const -{ +bool RemoveVCProcess::IsActive(unsigned int pFlags) const { return (pFlags & aiProcess_RemoveComponent) != 0; } // ------------------------------------------------------------------------------------------------ // Small helper function to delete all elements in a T** aray using delete template -inline void ArrayDelete(T**& in, unsigned int& num) -{ +inline void ArrayDelete(T **&in, unsigned int &num) { for (unsigned int i = 0; i < num; ++i) delete in[i]; delete[] in; - in = NULL; + in = nullptr; num = 0; } @@ -108,9 +102,9 @@ bool UpdateNodeGraph(aiNode* node,std::list& childsOfParent,bool root) { childsOfParent.insert(childsOfParent.end(),mine.begin(),mine.end()); - // set all children to NULL to make sure they are not deleted when we delete ourself + // 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] = NULL; + node->mChildren[i] = nullptr; } b = true; delete node; @@ -143,86 +137,74 @@ bool UpdateNodeGraph(aiNode* node,std::list& childsOfParent,bool root) // ------------------------------------------------------------------------------------------------ // Executes the post processing step on the given imported data. -void RemoveVCProcess::Execute( aiScene* pScene) -{ +void RemoveVCProcess::Execute(aiScene *pScene) { ASSIMP_LOG_DEBUG("RemoveVCProcess begin"); bool bHas = false; //,bMasked = false; mScene = pScene; // handle animations - if ( configDeleteFlags & aiComponent_ANIMATIONS) - { + if (configDeleteFlags & aiComponent_ANIMATIONS) { bHas = true; - ArrayDelete(pScene->mAnimations,pScene->mNumAnimations); + ArrayDelete(pScene->mAnimations, pScene->mNumAnimations); } // handle textures - if ( configDeleteFlags & aiComponent_TEXTURES) - { + if (configDeleteFlags & aiComponent_TEXTURES) { bHas = true; - ArrayDelete(pScene->mTextures,pScene->mNumTextures); + ArrayDelete(pScene->mTextures, pScene->mNumTextures); } // handle materials - if ( configDeleteFlags & aiComponent_MATERIALS && pScene->mNumMaterials) - { + if (configDeleteFlags & aiComponent_MATERIALS && pScene->mNumMaterials) { bHas = true; - for (unsigned int i = 1;i < pScene->mNumMaterials;++i) + for (unsigned int i = 1; i < pScene->mNumMaterials; ++i) delete pScene->mMaterials[i]; pScene->mNumMaterials = 1; - aiMaterial* helper = (aiMaterial*) pScene->mMaterials[0]; - ai_assert(NULL != helper); + aiMaterial *helper = (aiMaterial *)pScene->mMaterials[0]; + ai_assert(nullptr != helper); helper->Clear(); // gray - aiColor3D clr(0.6f,0.6f,0.6f); - helper->AddProperty(&clr,1,AI_MATKEY_COLOR_DIFFUSE); + aiColor3D clr(0.6f, 0.6f, 0.6f); + helper->AddProperty(&clr, 1, AI_MATKEY_COLOR_DIFFUSE); // add a small ambient color value - clr = aiColor3D(0.05f,0.05f,0.05f); - helper->AddProperty(&clr,1,AI_MATKEY_COLOR_AMBIENT); + clr = aiColor3D(0.05f, 0.05f, 0.05f); + helper->AddProperty(&clr, 1, AI_MATKEY_COLOR_AMBIENT); aiString s; s.Set("Dummy_MaterialsRemoved"); - helper->AddProperty(&s,AI_MATKEY_NAME); + helper->AddProperty(&s, AI_MATKEY_NAME); } // handle light sources - if ( configDeleteFlags & aiComponent_LIGHTS) - { - bHas = true; - ArrayDelete(pScene->mLights,pScene->mNumLights); + if (configDeleteFlags & aiComponent_LIGHTS) { + bHas = true; + ArrayDelete(pScene->mLights, pScene->mNumLights); } // handle camneras - if ( configDeleteFlags & aiComponent_CAMERAS) - { + if (configDeleteFlags & aiComponent_CAMERAS) { bHas = true; - ArrayDelete(pScene->mCameras,pScene->mNumCameras); + ArrayDelete(pScene->mCameras, pScene->mNumCameras); } // handle meshes - if (configDeleteFlags & aiComponent_MESHES) - { + if (configDeleteFlags & aiComponent_MESHES) { bHas = true; - ArrayDelete(pScene->mMeshes,pScene->mNumMeshes); - } - else - { - for( unsigned int a = 0; a < pScene->mNumMeshes; a++) - { - if( ProcessMesh( pScene->mMeshes[a])) + ArrayDelete(pScene->mMeshes, pScene->mNumMeshes); + } else { + for (unsigned int a = 0; a < pScene->mNumMeshes; a++) { + if (ProcessMesh(pScene->mMeshes[a])) bHas = true; } } - // now check whether the result is still a full scene - if (!pScene->mNumMeshes || !pScene->mNumMaterials) - { + if (!pScene->mNumMeshes || !pScene->mNumMaterials) { pScene->mFlags |= AI_SCENE_FLAGS_INCOMPLETE; ASSIMP_LOG_DEBUG("Setting AI_SCENE_FLAGS_INCOMPLETE flag"); @@ -240,63 +222,55 @@ void RemoveVCProcess::Execute( aiScene* pScene) // ------------------------------------------------------------------------------------------------ // Setup configuration properties for the step -void RemoveVCProcess::SetupProperties(const Importer* pImp) -{ - configDeleteFlags = pImp->GetPropertyInteger(AI_CONFIG_PP_RVC_FLAGS,0x0); - if (!configDeleteFlags) - { +void RemoveVCProcess::SetupProperties(const Importer *pImp) { + configDeleteFlags = pImp->GetPropertyInteger(AI_CONFIG_PP_RVC_FLAGS, 0x0); + if (!configDeleteFlags) { ASSIMP_LOG_WARN("RemoveVCProcess: AI_CONFIG_PP_RVC_FLAGS is zero."); } } // ------------------------------------------------------------------------------------------------ // Executes the post processing step on the given imported data. -bool RemoveVCProcess::ProcessMesh(aiMesh* pMesh) -{ +bool RemoveVCProcess::ProcessMesh(aiMesh *pMesh) { bool ret = false; // if all materials have been deleted let the material // index of the mesh point to the created default material - if ( configDeleteFlags & aiComponent_MATERIALS) + if (configDeleteFlags & aiComponent_MATERIALS) pMesh->mMaterialIndex = 0; // handle normals - if (configDeleteFlags & aiComponent_NORMALS && pMesh->mNormals) - { + if (configDeleteFlags & aiComponent_NORMALS && pMesh->mNormals) { delete[] pMesh->mNormals; - pMesh->mNormals = NULL; + pMesh->mNormals = nullptr; ret = true; } // handle tangents and bitangents - if (configDeleteFlags & aiComponent_TANGENTS_AND_BITANGENTS && pMesh->mTangents) - { + if (configDeleteFlags & aiComponent_TANGENTS_AND_BITANGENTS && pMesh->mTangents) { delete[] pMesh->mTangents; - pMesh->mTangents = NULL; + pMesh->mTangents = nullptr; delete[] pMesh->mBitangents; - pMesh->mBitangents = NULL; + pMesh->mBitangents = nullptr; ret = true; } // handle texture coordinates bool b = (0 != (configDeleteFlags & aiComponent_TEXCOORDS)); - for (unsigned int i = 0, real = 0; real < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++real) - { - if (!pMesh->mTextureCoords[i])break; - if (configDeleteFlags & aiComponent_TEXCOORDSn(real) || b) - { - delete [] pMesh->mTextureCoords[i]; - pMesh->mTextureCoords[i] = NULL; + for (unsigned int i = 0, real = 0; real < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++real) { + if (!pMesh->mTextureCoords[i]) break; + if (configDeleteFlags & aiComponent_TEXCOORDSn(real) || b) { + delete[] pMesh->mTextureCoords[i]; + pMesh->mTextureCoords[i] = nullptr; ret = true; - if (!b) - { + if (!b) { // collapse the rest of the array - for (unsigned int a = i+1; a < AI_MAX_NUMBER_OF_TEXTURECOORDS;++a) - pMesh->mTextureCoords[a-1] = pMesh->mTextureCoords[a]; + for (unsigned int a = i + 1; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a) + pMesh->mTextureCoords[a - 1] = pMesh->mTextureCoords[a]; - pMesh->mTextureCoords[AI_MAX_NUMBER_OF_TEXTURECOORDS-1] = NULL; + pMesh->mTextureCoords[AI_MAX_NUMBER_OF_TEXTURECOORDS - 1] = nullptr; continue; } } @@ -305,22 +279,19 @@ bool RemoveVCProcess::ProcessMesh(aiMesh* pMesh) // handle vertex colors b = (0 != (configDeleteFlags & aiComponent_COLORS)); - for (unsigned int i = 0, real = 0; real < AI_MAX_NUMBER_OF_COLOR_SETS; ++real) - { - if (!pMesh->mColors[i])break; - if (configDeleteFlags & aiComponent_COLORSn(i) || b) - { - delete [] pMesh->mColors[i]; - pMesh->mColors[i] = NULL; + for (unsigned int i = 0, real = 0; real < AI_MAX_NUMBER_OF_COLOR_SETS; ++real) { + if (!pMesh->mColors[i]) break; + if (configDeleteFlags & aiComponent_COLORSn(i) || b) { + delete[] pMesh->mColors[i]; + pMesh->mColors[i] = nullptr; ret = true; - if (!b) - { + if (!b) { // collapse the rest of the array - for (unsigned int a = i+1; a < AI_MAX_NUMBER_OF_COLOR_SETS;++a) - pMesh->mColors[a-1] = pMesh->mColors[a]; + for (unsigned int a = i + 1; a < AI_MAX_NUMBER_OF_COLOR_SETS; ++a) + pMesh->mColors[a - 1] = pMesh->mColors[a]; - pMesh->mColors[AI_MAX_NUMBER_OF_COLOR_SETS-1] = NULL; + pMesh->mColors[AI_MAX_NUMBER_OF_COLOR_SETS - 1] = nullptr; continue; } } @@ -328,9 +299,8 @@ bool RemoveVCProcess::ProcessMesh(aiMesh* pMesh) } // handle bones - if (configDeleteFlags & aiComponent_BONEWEIGHTS && pMesh->mBones) - { - ArrayDelete(pMesh->mBones,pMesh->mNumBones); + if (configDeleteFlags & aiComponent_BONEWEIGHTS && pMesh->mBones) { + ArrayDelete(pMesh->mBones, pMesh->mNumBones); ret = true; } return ret; diff --git a/code/PostProcessing/SortByPTypeProcess.cpp b/code/PostProcessing/SortByPTypeProcess.cpp index 87d34c162..c4f9c7e4d 100644 --- a/code/PostProcessing/SortByPTypeProcess.cpp +++ b/code/PostProcessing/SortByPTypeProcess.cpp @@ -45,111 +45,96 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SortByPTypeProcess post-process steps. */ - - // internal headers -#include "ProcessHelper.h" #include "SortByPTypeProcess.h" +#include "ProcessHelper.h" #include using namespace Assimp; // ------------------------------------------------------------------------------------------------ // Constructor to be privately used by Importer -SortByPTypeProcess::SortByPTypeProcess() -: mConfigRemoveMeshes( 0 ) { +SortByPTypeProcess::SortByPTypeProcess() : + mConfigRemoveMeshes(0) { // empty } // ------------------------------------------------------------------------------------------------ // Destructor, private as well -SortByPTypeProcess::~SortByPTypeProcess() -{ +SortByPTypeProcess::~SortByPTypeProcess() { // nothing to do here } // ------------------------------------------------------------------------------------------------ // Returns whether the processing step is present in the given flag field. -bool SortByPTypeProcess::IsActive( unsigned int pFlags) const -{ - return (pFlags & aiProcess_SortByPType) != 0; +bool SortByPTypeProcess::IsActive(unsigned int pFlags) const { + return (pFlags & aiProcess_SortByPType) != 0; } // ------------------------------------------------------------------------------------------------ -void SortByPTypeProcess::SetupProperties(const Importer* pImp) -{ - mConfigRemoveMeshes = pImp->GetPropertyInteger(AI_CONFIG_PP_SBP_REMOVE,0); +void SortByPTypeProcess::SetupProperties(const Importer *pImp) { + mConfigRemoveMeshes = pImp->GetPropertyInteger(AI_CONFIG_PP_SBP_REMOVE, 0); } // ------------------------------------------------------------------------------------------------ // Update changed meshes in all nodes -void UpdateNodes(const std::vector& replaceMeshIndex, aiNode* node) -{ - if (node->mNumMeshes) - { +void UpdateNodes(const std::vector &replaceMeshIndex, aiNode *node) { + if (node->mNumMeshes) { unsigned int newSize = 0; - for (unsigned int m = 0; m< node->mNumMeshes; ++m) - { - unsigned int add = node->mMeshes[m]<<2; - for (unsigned int i = 0; i < 4;++i) - { - if (UINT_MAX != replaceMeshIndex[add+i])++newSize; + for (unsigned int m = 0; m < node->mNumMeshes; ++m) { + unsigned int add = node->mMeshes[m] << 2; + for (unsigned int i = 0; i < 4; ++i) { + if (UINT_MAX != replaceMeshIndex[add + i]) ++newSize; } } - if (!newSize) - { + if (!newSize) { delete[] node->mMeshes; node->mNumMeshes = 0; - node->mMeshes = NULL; - } - else - { + node->mMeshes = nullptr; + } else { // Try to reuse the old array if possible - unsigned int* newMeshes = (newSize > node->mNumMeshes - ? new unsigned int[newSize] : node->mMeshes); + unsigned int *newMeshes = (newSize > node->mNumMeshes ? new unsigned int[newSize] : node->mMeshes); - for (unsigned int m = 0; m< node->mNumMeshes; ++m) - { - unsigned int add = node->mMeshes[m]<<2; - for (unsigned int i = 0; i < 4;++i) - { - if (UINT_MAX != replaceMeshIndex[add+i]) - *newMeshes++ = replaceMeshIndex[add+i]; + for (unsigned int m = 0; m < node->mNumMeshes; ++m) { + unsigned int add = node->mMeshes[m] << 2; + for (unsigned int i = 0; i < 4; ++i) { + if (UINT_MAX != replaceMeshIndex[add + i]) + *newMeshes++ = replaceMeshIndex[add + i]; } } if (newSize > node->mNumMeshes) delete[] node->mMeshes; - node->mMeshes = newMeshes-(node->mNumMeshes = newSize); + node->mMeshes = newMeshes - (node->mNumMeshes = newSize); } } // call all subnodes recursively for (unsigned int m = 0; m < node->mNumChildren; ++m) - UpdateNodes(replaceMeshIndex,node->mChildren[m]); + UpdateNodes(replaceMeshIndex, node->mChildren[m]); } // ------------------------------------------------------------------------------------------------ // Executes the post processing step on the given imported data. -void SortByPTypeProcess::Execute( aiScene* pScene) { - if ( 0 == pScene->mNumMeshes) { +void SortByPTypeProcess::Execute(aiScene *pScene) { + if (0 == pScene->mNumMeshes) { ASSIMP_LOG_DEBUG("SortByPTypeProcess skipped, there are no meshes"); return; } ASSIMP_LOG_DEBUG("SortByPTypeProcess begin"); - unsigned int aiNumMeshesPerPType[4] = {0,0,0,0}; + unsigned int aiNumMeshesPerPType[4] = { 0, 0, 0, 0 }; - std::vector outMeshes; - outMeshes.reserve(pScene->mNumMeshes<<1u); + std::vector outMeshes; + outMeshes.reserve(pScene->mNumMeshes << 1u); bool bAnyChanges = false; - std::vector replaceMeshIndex(pScene->mNumMeshes*4,UINT_MAX); + std::vector replaceMeshIndex(pScene->mNumMeshes * 4, UINT_MAX); std::vector::iterator meshIdx = replaceMeshIndex.begin(); for (unsigned int i = 0; i < pScene->mNumMeshes; ++i) { - aiMesh* const mesh = pScene->mMeshes[i]; + aiMesh *const mesh = pScene->mMeshes[i]; ai_assert(0 != mesh->mPrimitiveTypes); // if there's just one primitive type in the mesh there's nothing to do for us @@ -173,11 +158,11 @@ void SortByPTypeProcess::Execute( aiScene* pScene) { if (1 == num) { if (!(mConfigRemoveMeshes & mesh->mPrimitiveTypes)) { - *meshIdx = static_cast( outMeshes.size() ); + *meshIdx = static_cast(outMeshes.size()); outMeshes.push_back(mesh); } else { delete mesh; - pScene->mMeshes[ i ] = nullptr; + pScene->mMeshes[i] = nullptr; bAnyChanges = true; } @@ -188,32 +173,29 @@ void SortByPTypeProcess::Execute( aiScene* pScene) { // reuse our current mesh arrays for the submesh // with the largest number of primitives - unsigned int aiNumPerPType[4] = {0,0,0,0}; - aiFace* pFirstFace = mesh->mFaces; - aiFace* const pLastFace = pFirstFace + mesh->mNumFaces; + unsigned int aiNumPerPType[4] = { 0, 0, 0, 0 }; + aiFace *pFirstFace = mesh->mFaces; + aiFace *const pLastFace = pFirstFace + mesh->mNumFaces; unsigned int numPolyVerts = 0; - for (;pFirstFace != pLastFace; ++pFirstFace) { + for (; pFirstFace != pLastFace; ++pFirstFace) { if (pFirstFace->mNumIndices <= 3) - ++aiNumPerPType[pFirstFace->mNumIndices-1]; - else - { + ++aiNumPerPType[pFirstFace->mNumIndices - 1]; + else { ++aiNumPerPType[3]; - numPolyVerts += pFirstFace-> mNumIndices; + numPolyVerts += pFirstFace->mNumIndices; } } - VertexWeightTable* avw = ComputeVertexBoneWeightTable(mesh); - for (unsigned int real = 0; real < 4; ++real,++meshIdx) - { - if ( !aiNumPerPType[real] || mConfigRemoveMeshes & (1u << real)) - { + VertexWeightTable *avw = ComputeVertexBoneWeightTable(mesh); + for (unsigned int real = 0; real < 4; ++real, ++meshIdx) { + if (!aiNumPerPType[real] || mConfigRemoveMeshes & (1u << real)) { continue; } - *meshIdx = (unsigned int) outMeshes.size(); + *meshIdx = (unsigned int)outMeshes.size(); outMeshes.push_back(new aiMesh()); - aiMesh* out = outMeshes.back(); + aiMesh *out = outMeshes.back(); // the name carries the adjacency information between the meshes out->mName = mesh->mName; @@ -224,13 +206,13 @@ void SortByPTypeProcess::Execute( aiScene* pScene) { // allocate output storage out->mNumFaces = aiNumPerPType[real]; - aiFace* outFaces = out->mFaces = new aiFace[out->mNumFaces]; + aiFace *outFaces = out->mFaces = new aiFace[out->mNumFaces]; - out->mNumVertices = (3 == real ? numPolyVerts : out->mNumFaces * (real+1)); + out->mNumVertices = (3 == real ? numPolyVerts : out->mNumFaces * (real + 1)); aiVector3D *vert(nullptr), *nor(nullptr), *tan(nullptr), *bit(nullptr); - aiVector3D *uv [AI_MAX_NUMBER_OF_TEXTURECOORDS]; - aiColor4D *cols [AI_MAX_NUMBER_OF_COLOR_SETS]; + aiVector3D *uv[AI_MAX_NUMBER_OF_TEXTURECOORDS]; + aiColor4D *cols[AI_MAX_NUMBER_OF_COLOR_SETS]; if (mesh->mVertices) { vert = out->mVertices = new aiVector3D[out->mNumVertices]; @@ -241,11 +223,11 @@ void SortByPTypeProcess::Execute( aiScene* pScene) { } if (mesh->mTangents) { - tan = out->mTangents = new aiVector3D[out->mNumVertices]; + tan = out->mTangents = new aiVector3D[out->mNumVertices]; bit = out->mBitangents = new aiVector3D[out->mNumVertices]; } - for (unsigned int j = 0; j < AI_MAX_NUMBER_OF_TEXTURECOORDS;++j) { + for (unsigned int j = 0; j < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++j) { uv[j] = nullptr; if (mesh->mTextureCoords[j]) { uv[j] = out->mTextureCoords[j] = new aiVector3D[out->mNumVertices]; @@ -254,70 +236,60 @@ void SortByPTypeProcess::Execute( aiScene* pScene) { out->mNumUVComponents[j] = mesh->mNumUVComponents[j]; } - for (unsigned int j = 0; j < AI_MAX_NUMBER_OF_COLOR_SETS;++j) { + for (unsigned int j = 0; j < AI_MAX_NUMBER_OF_COLOR_SETS; ++j) { cols[j] = nullptr; if (mesh->mColors[j]) { cols[j] = out->mColors[j] = new aiColor4D[out->mNumVertices]; } } - typedef std::vector< aiVertexWeight > TempBoneInfo; - std::vector< TempBoneInfo > tempBones(mesh->mNumBones); + typedef std::vector TempBoneInfo; + std::vector tempBones(mesh->mNumBones); // try to guess how much storage we'll need - for (unsigned int q = 0; q < mesh->mNumBones;++q) - { - tempBones[q].reserve(mesh->mBones[q]->mNumWeights / (num-1)); + for (unsigned int q = 0; q < mesh->mNumBones; ++q) { + tempBones[q].reserve(mesh->mBones[q]->mNumWeights / (num - 1)); } unsigned int outIdx = 0; - for (unsigned int m = 0; m < mesh->mNumFaces; ++m) - { - aiFace& in = mesh->mFaces[m]; - if ((real == 3 && in.mNumIndices <= 3) || (real != 3 && in.mNumIndices != real+1)) - { + for (unsigned int m = 0; m < mesh->mNumFaces; ++m) { + aiFace &in = mesh->mFaces[m]; + if ((real == 3 && in.mNumIndices <= 3) || (real != 3 && in.mNumIndices != real + 1)) { continue; } outFaces->mNumIndices = in.mNumIndices; - outFaces->mIndices = in.mIndices; + outFaces->mIndices = in.mIndices; - for (unsigned int q = 0; q < in.mNumIndices; ++q) - { + for (unsigned int q = 0; q < in.mNumIndices; ++q) { unsigned int idx = in.mIndices[q]; // process all bones of this index - if (avw) - { - VertexWeightTable& tbl = avw[idx]; + if (avw) { + VertexWeightTable &tbl = avw[idx]; for (VertexWeightTable::const_iterator it = tbl.begin(), end = tbl.end(); - it != end; ++it) - { - tempBones[ (*it).first ].push_back( aiVertexWeight(outIdx, (*it).second) ); + it != end; ++it) { + tempBones[(*it).first].push_back(aiVertexWeight(outIdx, (*it).second)); } } - if (vert) - { + if (vert) { *vert++ = mesh->mVertices[idx]; //mesh->mVertices[idx].x = get_qnan(); } - if (nor )*nor++ = mesh->mNormals[idx]; - if (tan ) - { - *tan++ = mesh->mTangents[idx]; - *bit++ = mesh->mBitangents[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; + for (unsigned int pp = 0; pp < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++pp) { + 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; + for (unsigned int pp = 0; pp < AI_MAX_NUMBER_OF_COLOR_SETS; ++pp) { + if (!cols[pp]) break; *cols[pp]++ = mesh->mColors[pp][idx]; } @@ -330,23 +302,22 @@ void SortByPTypeProcess::Execute( aiScene* pScene) { ai_assert(outFaces == out->mFaces + out->mNumFaces); // now generate output bones - for (unsigned int q = 0; q < mesh->mNumBones; ++q) { - if (!tempBones[q].empty()) { - ++out->mNumBones; - } - } + for (unsigned int q = 0; q < mesh->mNumBones; ++q) { + if (!tempBones[q].empty()) { + ++out->mNumBones; + } + } if (out->mNumBones) { - out->mBones = new aiBone*[out->mNumBones]; - for (unsigned int q = 0, boneIdx = 0; q < mesh->mNumBones;++q) - { - TempBoneInfo& in = tempBones[q]; - if (in.empty()) { - continue; - } + out->mBones = new aiBone *[out->mNumBones]; + for (unsigned int q = 0, boneIdx = 0; q < mesh->mNumBones; ++q) { + TempBoneInfo &in = tempBones[q]; + if (in.empty()) { + continue; + } - aiBone* srcBone = mesh->mBones[q]; - aiBone *bone = out->mBones[boneIdx] = new aiBone(); + aiBone *srcBone = mesh->mBones[q]; + aiBone *bone = out->mBones[boneIdx] = new aiBone(); bone->mName = srcBone->mName; bone->mOffsetMatrix = srcBone->mOffsetMatrix; @@ -354,7 +325,7 @@ void SortByPTypeProcess::Execute( aiScene* pScene) { bone->mNumWeights = (unsigned int)in.size(); bone->mWeights = new aiVertexWeight[bone->mNumWeights]; - ::memcpy(bone->mWeights,&in[0],bone->mNumWeights*sizeof(aiVertexWeight)); + ::memcpy(bone->mWeights, &in[0], bone->mNumWeights * sizeof(aiVertexWeight)); ++boneIdx; } @@ -371,37 +342,32 @@ void SortByPTypeProcess::Execute( aiScene* pScene) { pScene->mMeshes[i] = nullptr; } - if (outMeshes.empty()) - { + if (outMeshes.empty()) { // This should not occur throw DeadlyImportError("No meshes remaining"); } // If we added at least one mesh process all nodes in the node // graph and update their respective mesh indices. - if (bAnyChanges) - { - UpdateNodes(replaceMeshIndex,pScene->mRootNode); + if (bAnyChanges) { + UpdateNodes(replaceMeshIndex, pScene->mRootNode); } - if (outMeshes.size() != pScene->mNumMeshes) - { + if (outMeshes.size() != pScene->mNumMeshes) { delete[] pScene->mMeshes; pScene->mNumMeshes = (unsigned int)outMeshes.size(); - pScene->mMeshes = new aiMesh*[pScene->mNumMeshes]; + pScene->mMeshes = new aiMesh *[pScene->mNumMeshes]; } - ::memcpy(pScene->mMeshes,&outMeshes[0],pScene->mNumMeshes*sizeof(void*)); + ::memcpy(pScene->mMeshes, &outMeshes[0], pScene->mNumMeshes * sizeof(void *)); - if (!DefaultLogger::isNullLogger()) - { + if (!DefaultLogger::isNullLogger()) { char buffer[1024]; - ::ai_snprintf(buffer,1024,"Points: %u%s, Lines: %u%s, Triangles: %u%s, Polygons: %u%s (Meshes, X = removed)", - aiNumMeshesPerPType[0], ((mConfigRemoveMeshes & aiPrimitiveType_POINT) ? "X" : ""), - aiNumMeshesPerPType[1], ((mConfigRemoveMeshes & aiPrimitiveType_LINE) ? "X" : ""), - aiNumMeshesPerPType[2], ((mConfigRemoveMeshes & aiPrimitiveType_TRIANGLE) ? "X" : ""), - aiNumMeshesPerPType[3], ((mConfigRemoveMeshes & aiPrimitiveType_POLYGON) ? "X" : "")); + ::ai_snprintf(buffer, 1024, "Points: %u%s, Lines: %u%s, Triangles: %u%s, Polygons: %u%s (Meshes, X = removed)", + aiNumMeshesPerPType[0], ((mConfigRemoveMeshes & aiPrimitiveType_POINT) ? "X" : ""), + aiNumMeshesPerPType[1], ((mConfigRemoveMeshes & aiPrimitiveType_LINE) ? "X" : ""), + aiNumMeshesPerPType[2], ((mConfigRemoveMeshes & aiPrimitiveType_TRIANGLE) ? "X" : ""), + aiNumMeshesPerPType[3], ((mConfigRemoveMeshes & aiPrimitiveType_POLYGON) ? "X" : "")); ASSIMP_LOG_INFO(buffer); ASSIMP_LOG_DEBUG("SortByPTypeProcess finished"); } } - diff --git a/code/PostProcessing/TextureTransform.cpp b/code/PostProcessing/TextureTransform.cpp index 654586111..e3683763a 100644 --- a/code/PostProcessing/TextureTransform.cpp +++ b/code/PostProcessing/TextureTransform.cpp @@ -508,7 +508,7 @@ void TextureTransformStep::Execute( aiScene* pScene) aiVector3D* dest, *end; dest = mesh->mTextureCoords[n]; - ai_assert(NULL != src); + ai_assert(nullptr != src); // Copy the data to the destination array if (dest != src) diff --git a/code/PostProcessing/TriangulateProcess.cpp b/code/PostProcessing/TriangulateProcess.cpp index cd9be0d21..8035b34f4 100644 --- a/code/PostProcessing/TriangulateProcess.cpp +++ b/code/PostProcessing/TriangulateProcess.cpp @@ -161,7 +161,7 @@ bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh) // Just another check whether aiMesh::mPrimitiveTypes is correct ai_assert(numOut != pMesh->mNumFaces); - aiVector3D* nor_out = NULL; + aiVector3D *nor_out = nullptr; // if we don't have normals yet, but expect them to be a cheap side // product of triangulation anyway, allocate storage for them. @@ -220,7 +220,7 @@ bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh) nface.mNumIndices = face.mNumIndices; nface.mIndices = face.mIndices; - face.mIndices = NULL; + face.mIndices = nullptr; continue; } // optimized code for quadrilaterals @@ -272,7 +272,7 @@ bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh) sface.mIndices[2] = temp[(start_vertex + 3) % 4]; // prevent double deletion of the indices field - face.mIndices = NULL; + face.mIndices = nullptr; continue; } else @@ -511,7 +511,7 @@ bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh) } delete[] face.mIndices; - face.mIndices = NULL; + face.mIndices = nullptr; } #ifdef AI_BUILD_TRIANGULATE_DEBUG_POLYS diff --git a/code/PostProcessing/ValidateDataStructure.cpp b/code/PostProcessing/ValidateDataStructure.cpp index 03989c1e5..a288e397d 100644 --- a/code/PostProcessing/ValidateDataStructure.cpp +++ b/code/PostProcessing/ValidateDataStructure.cpp @@ -48,9 +48,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // internal headers #include "ValidateDataStructure.h" +#include "ProcessHelper.h" #include #include -#include "ProcessHelper.h" #include // CRT headers @@ -61,80 +61,69 @@ using namespace Assimp; // ------------------------------------------------------------------------------------------------ // Constructor to be privately used by Importer ValidateDSProcess::ValidateDSProcess() : - mScene() -{} + mScene() {} // ------------------------------------------------------------------------------------------------ // Destructor, private as well -ValidateDSProcess::~ValidateDSProcess() -{} +ValidateDSProcess::~ValidateDSProcess() {} // ------------------------------------------------------------------------------------------------ // Returns whether the processing step is present in the given flag field. -bool ValidateDSProcess::IsActive( unsigned int pFlags) const -{ +bool ValidateDSProcess::IsActive(unsigned int pFlags) const { return (pFlags & aiProcess_ValidateDataStructure) != 0; } // ------------------------------------------------------------------------------------------------ -AI_WONT_RETURN void ValidateDSProcess::ReportError(const char* msg,...) -{ - ai_assert(NULL != msg); +AI_WONT_RETURN void ValidateDSProcess::ReportError(const char *msg, ...) { + ai_assert(nullptr != msg); va_list args; - va_start(args,msg); + va_start(args, msg); char szBuffer[3000]; - const int iLen = vsprintf(szBuffer,msg,args); + const int iLen = vsprintf(szBuffer, msg, args); ai_assert(iLen > 0); va_end(args); - throw DeadlyImportError("Validation failed: " + std::string(szBuffer,iLen)); + throw DeadlyImportError("Validation failed: " + std::string(szBuffer, iLen)); } // ------------------------------------------------------------------------------------------------ -void ValidateDSProcess::ReportWarning(const char* msg,...) -{ - ai_assert(NULL != msg); +void ValidateDSProcess::ReportWarning(const char *msg, ...) { + ai_assert(nullptr != msg); va_list args; - va_start(args,msg); + va_start(args, msg); char szBuffer[3000]; - const int iLen = vsprintf(szBuffer,msg,args); + const int iLen = vsprintf(szBuffer, msg, args); ai_assert(iLen > 0); va_end(args); - ASSIMP_LOG_WARN("Validation warning: " + std::string(szBuffer,iLen)); + ASSIMP_LOG_WARN("Validation warning: " + std::string(szBuffer, iLen)); } // ------------------------------------------------------------------------------------------------ -inline -int HasNameMatch(const aiString& in, aiNode* node) { - int result = (node->mName == in ? 1 : 0 ); - for (unsigned int i = 0; i < node->mNumChildren;++i) { - result += HasNameMatch(in,node->mChildren[i]); +inline int HasNameMatch(const aiString &in, aiNode *node) { + int result = (node->mName == in ? 1 : 0); + for (unsigned int i = 0; i < node->mNumChildren; ++i) { + result += HasNameMatch(in, node->mChildren[i]); } return result; } // ------------------------------------------------------------------------------------------------ template -inline -void ValidateDSProcess::DoValidation(T** parray, unsigned int size, const char* firstName, const char* secondName) { +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 NULL (aiScene::%s is %i)", - firstName, secondName, size); + 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 NULL (aiScene::%s is %i)", - firstName,i,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]); } @@ -143,32 +132,27 @@ void ValidateDSProcess::DoValidation(T** parray, unsigned int size, const char* // ------------------------------------------------------------------------------------------------ template -inline void ValidateDSProcess::DoValidationEx(T** parray, unsigned int size, - const char* firstName, const char* secondName) -{ +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 NULL (aiScene::%s is %i)", - firstName, secondName, size); + 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[%u] is NULL (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]); // 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); + 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); } } } @@ -177,29 +161,28 @@ inline void ValidateDSProcess::DoValidationEx(T** parray, unsigned int size, // ------------------------------------------------------------------------------------------------ template -inline -void ValidateDSProcess::DoValidationWithNameCheck(T** array, unsigned int size, const char* firstName, - const char* secondName) { +inline void ValidateDSProcess::DoValidationWithNameCheck(T **array, unsigned int size, const char *firstName, + const char *secondName) { // validate all entries - DoValidationEx(array,size,firstName,secondName); + DoValidationEx(array, size, firstName, secondName); - for (unsigned int i = 0; i < size;++i) { - int res = HasNameMatch(array[i]->mName,mScene->mRootNode); - if (0 == res) { - const std::string name = static_cast(array[i]->mName.data); + for (unsigned int i = 0; i < size; ++i) { + int res = HasNameMatch(array[i]->mName, mScene->mRootNode); + if (0 == res) { + const std::string name = static_cast(array[i]->mName.data); ReportError("aiScene::%s[%i] has no corresponding node in the scene graph (%s)", - firstName,i, name.c_str()); - } else if (1 != res) { - const std::string name = static_cast(array[i]->mName.data); + firstName, i, name.c_str()); + } else if (1 != res) { + const std::string name = static_cast(array[i]->mName.data); ReportError("aiScene::%s[%i]: there are more than one nodes with %s as name", - firstName,i, name.c_str()); + firstName, i, name.c_str()); } } } // ------------------------------------------------------------------------------------------------ // Executes the post processing step on the given imported data. -void ValidateDSProcess::Execute( aiScene* pScene) { +void ValidateDSProcess::Execute(aiScene *pScene) { mScene = pScene; ASSIMP_LOG_DEBUG("ValidateDataStructureProcess begin"); @@ -208,54 +191,48 @@ void ValidateDSProcess::Execute( aiScene* pScene) { // validate all meshes if (pScene->mNumMeshes) { - DoValidation(pScene->mMeshes,pScene->mNumMeshes,"mMeshes","mNumMeshes"); - } - else if (!(mScene->mFlags & AI_SCENE_FLAGS_INCOMPLETE)) { + DoValidation(pScene->mMeshes, pScene->mNumMeshes, "mMeshes", "mNumMeshes"); + } else if (!(mScene->mFlags & AI_SCENE_FLAGS_INCOMPLETE)) { ReportError("aiScene::mNumMeshes is 0. At least one mesh must be there"); - } - else if (pScene->mMeshes) { + } else if (pScene->mMeshes) { ReportError("aiScene::mMeshes is non-null although there are no meshes"); } // validate all animations if (pScene->mNumAnimations) { - DoValidation(pScene->mAnimations,pScene->mNumAnimations, - "mAnimations","mNumAnimations"); - } - else if (pScene->mAnimations) { + DoValidation(pScene->mAnimations, pScene->mNumAnimations, + "mAnimations", "mNumAnimations"); + } else if (pScene->mAnimations) { ReportError("aiScene::mAnimations is non-null although there are no animations"); } // validate all cameras if (pScene->mNumCameras) { - DoValidationWithNameCheck(pScene->mCameras,pScene->mNumCameras, - "mCameras","mNumCameras"); - } - else if (pScene->mCameras) { + DoValidationWithNameCheck(pScene->mCameras, pScene->mNumCameras, + "mCameras", "mNumCameras"); + } else if (pScene->mCameras) { ReportError("aiScene::mCameras is non-null although there are no cameras"); } // validate all lights if (pScene->mNumLights) { - DoValidationWithNameCheck(pScene->mLights,pScene->mNumLights, - "mLights","mNumLights"); - } - else if (pScene->mLights) { + DoValidationWithNameCheck(pScene->mLights, pScene->mNumLights, + "mLights", "mNumLights"); + } else if (pScene->mLights) { ReportError("aiScene::mLights is non-null although there are no lights"); } // validate all textures if (pScene->mNumTextures) { - DoValidation(pScene->mTextures,pScene->mNumTextures, - "mTextures","mNumTextures"); - } - else if (pScene->mTextures) { + DoValidation(pScene->mTextures, pScene->mNumTextures, + "mTextures", "mNumTextures"); + } else if (pScene->mTextures) { ReportError("aiScene::mTextures is non-null although there are no textures"); } // validate all materials if (pScene->mNumMaterials) { - DoValidation(pScene->mMaterials,pScene->mNumMaterials,"mMaterials","mNumMaterials"); + DoValidation(pScene->mMaterials, pScene->mNumMaterials, "mMaterials", "mNumMaterials"); } #if 0 // NOTE: ScenePreprocessor generates a default material if none is there @@ -263,104 +240,95 @@ void ValidateDSProcess::Execute( aiScene* pScene) { ReportError("aiScene::mNumMaterials is 0. At least one material must be there"); } #endif - else if (pScene->mMaterials) { + else if (pScene->mMaterials) { ReportError("aiScene::mMaterials is non-null although there are no materials"); } -// if (!has)ReportError("The aiScene data structure is empty"); + // if (!has)ReportError("The aiScene data structure is empty"); ASSIMP_LOG_DEBUG("ValidateDataStructureProcess end"); } // ------------------------------------------------------------------------------------------------ -void ValidateDSProcess::Validate( const aiLight* pLight) -{ +void ValidateDSProcess::Validate(const aiLight *pLight) { if (pLight->mType == aiLightSource_UNDEFINED) ReportWarning("aiLight::mType is aiLightSource_UNDEFINED"); if (!pLight->mAttenuationConstant && - !pLight->mAttenuationLinear && - !pLight->mAttenuationQuadratic) { + !pLight->mAttenuationLinear && + !pLight->mAttenuationQuadratic) { ReportWarning("aiLight::mAttenuationXXX - all are zero"); } if (pLight->mAngleInnerCone > pLight->mAngleOuterCone) ReportError("aiLight::mAngleInnerCone is larger than aiLight::mAngleOuterCone"); - if (pLight->mColorDiffuse.IsBlack() && pLight->mColorAmbient.IsBlack() - && pLight->mColorSpecular.IsBlack()) - { + if (pLight->mColorDiffuse.IsBlack() && pLight->mColorAmbient.IsBlack() && pLight->mColorSpecular.IsBlack()) { ReportWarning("aiLight::mColorXXX - all are black and won't have any influence"); } } // ------------------------------------------------------------------------------------------------ -void ValidateDSProcess::Validate( const aiCamera* pCamera) -{ +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. if (!pCamera->mHorizontalFOV || pCamera->mHorizontalFOV >= (float)AI_MATH_PI) - ReportWarning("%f is not a valid value for aiCamera::mHorizontalFOV",pCamera->mHorizontalFOV); + ReportWarning("%f is not a valid value for aiCamera::mHorizontalFOV", pCamera->mHorizontalFOV); } // ------------------------------------------------------------------------------------------------ -void ValidateDSProcess::Validate( const aiMesh* pMesh) -{ +void ValidateDSProcess::Validate(const aiMesh *pMesh) { // validate the material index of the mesh - if (mScene->mNumMaterials && pMesh->mMaterialIndex >= mScene->mNumMaterials) - { + if (mScene->mNumMaterials && pMesh->mMaterialIndex >= mScene->mNumMaterials) { ReportError("aiMesh::mMaterialIndex is invalid (value: %i maximum: %i)", - pMesh->mMaterialIndex,mScene->mNumMaterials-1); + pMesh->mMaterialIndex, mScene->mNumMaterials - 1); } Validate(&pMesh->mName); - for (unsigned int i = 0; i < pMesh->mNumFaces; ++i) - { - aiFace& face = pMesh->mFaces[i]; + for (unsigned int i = 0; i < pMesh->mNumFaces; ++i) { + aiFace &face = pMesh->mFaces[i]; - if (pMesh->mPrimitiveTypes) - { - switch (face.mNumIndices) - { + if (pMesh->mPrimitiveTypes) { + switch (face.mNumIndices) { case 0: - ReportError("aiMesh::mFaces[%i].mNumIndices is 0",i); + ReportError("aiMesh::mFaces[%i].mNumIndices is 0", i); break; case 1: - if (0 == (pMesh->mPrimitiveTypes & aiPrimitiveType_POINT)) - { + if (0 == (pMesh->mPrimitiveTypes & aiPrimitiveType_POINT)) { ReportError("aiMesh::mFaces[%i] is a POINT but aiMesh::mPrimitiveTypes " - "does not report the POINT flag",i); + "does not report the POINT flag", + i); } break; case 2: - if (0 == (pMesh->mPrimitiveTypes & aiPrimitiveType_LINE)) - { + if (0 == (pMesh->mPrimitiveTypes & aiPrimitiveType_LINE)) { ReportError("aiMesh::mFaces[%i] is a LINE but aiMesh::mPrimitiveTypes " - "does not report the LINE flag",i); + "does not report the LINE flag", + i); } break; case 3: - if (0 == (pMesh->mPrimitiveTypes & aiPrimitiveType_TRIANGLE)) - { + if (0 == (pMesh->mPrimitiveTypes & aiPrimitiveType_TRIANGLE)) { ReportError("aiMesh::mFaces[%i] is a TRIANGLE but aiMesh::mPrimitiveTypes " - "does not report the TRIANGLE flag",i); + "does not report the TRIANGLE flag", + i); } break; default: - if (0 == (pMesh->mPrimitiveTypes & aiPrimitiveType_POLYGON)) - { + if (0 == (pMesh->mPrimitiveTypes & aiPrimitiveType_POLYGON)) { this->ReportError("aiMesh::mFaces[%i] is a POLYGON but aiMesh::mPrimitiveTypes " - "does not report the POLYGON flag",i); + "does not report the POLYGON flag", + i); } break; }; } if (!face.mIndices) - ReportError("aiMesh::mFaces[%i].mIndices is NULL",i); + ReportError("aiMesh::mFaces[%i].mIndices is nullptr", i); } // positions must always be there ... @@ -369,42 +337,40 @@ void ValidateDSProcess::Validate( const aiMesh* pMesh) } if (pMesh->mNumVertices > AI_MAX_VERTICES) { - ReportError("Mesh has too many vertices: %u, but the limit is %u",pMesh->mNumVertices,AI_MAX_VERTICES); + ReportError("Mesh has too many vertices: %u, but the limit is %u", pMesh->mNumVertices, AI_MAX_VERTICES); } if (pMesh->mNumFaces > AI_MAX_FACES) { - ReportError("Mesh has too many faces: %u, but the limit is %u",pMesh->mNumFaces,AI_MAX_FACES); + ReportError("Mesh has too many faces: %u, but the limit is %u", pMesh->mNumFaces, AI_MAX_FACES); } // if tangents are there there must also be bitangent vectors ... - if ((pMesh->mTangents != NULL) != (pMesh->mBitangents != NULL)) { + if ((pMesh->mTangents != nullptr) != (pMesh->mBitangents != nullptr)) { ReportError("If there are tangents, bitangent vectors must be present as well"); } // faces, too - if (!pMesh->mNumFaces || (!pMesh->mFaces && !mScene->mFlags)) { + if (!pMesh->mNumFaces || (!pMesh->mFaces && !mScene->mFlags)) { ReportError("Mesh %s contains no faces", pMesh->mName.C_Str()); } // now check whether the face indexing layout is correct: // unique vertices, pseudo-indexed. std::vector abRefList; - abRefList.resize(pMesh->mNumVertices,false); - for (unsigned int i = 0; i < pMesh->mNumFaces;++i) - { - aiFace& face = pMesh->mFaces[i]; + abRefList.resize(pMesh->mNumVertices, false); + for (unsigned int i = 0; i < pMesh->mNumFaces; ++i) { + aiFace &face = pMesh->mFaces[i]; if (face.mNumIndices > AI_MAX_FACE_INDICES) { - ReportError("Face %u has too many faces: %u, but the limit is %u",i,face.mNumIndices,AI_MAX_FACE_INDICES); + ReportError("Face %u has too many faces: %u, but the limit is %u", i, face.mNumIndices, AI_MAX_FACE_INDICES); } - for (unsigned int a = 0; a < face.mNumIndices;++a) - { - if (face.mIndices[a] >= pMesh->mNumVertices) { - ReportError("aiMesh::mFaces[%i]::mIndices[%i] is out of range",i,a); + for (unsigned int a = 0; a < face.mNumIndices; ++a) { + 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) && + /*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 " @@ -416,168 +382,146 @@ void ValidateDSProcess::Validate( const aiMesh* pMesh) // check whether there are vertices that aren't referenced by a face bool b = false; - for (unsigned int i = 0; i < pMesh->mNumVertices;++i) { - if (!abRefList[i])b = true; + for (unsigned int i = 0; i < pMesh->mNumVertices; ++i) { + if (!abRefList[i]) b = true; } abRefList.clear(); if (b) { - ReportWarning("There are unreferenced vertices"); + ReportWarning("There are unreferenced vertices"); } // texture channel 2 may not be set if channel 1 is zero ... { unsigned int i = 0; - for (;i < AI_MAX_NUMBER_OF_TEXTURECOORDS;++i) - { - if (!pMesh->HasTextureCoords(i))break; + for (; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i) { + if (!pMesh->HasTextureCoords(i)) break; } - for (;i < AI_MAX_NUMBER_OF_TEXTURECOORDS;++i) - if (pMesh->HasTextureCoords(i)) - { + for (; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i) + if (pMesh->HasTextureCoords(i)) { ReportError("Texture coordinate channel %i exists " - "although the previous channel was NULL.",i); + "although the previous channel was nullptr.", + i); } } // the same for the vertex colors { unsigned int i = 0; - for (;i < AI_MAX_NUMBER_OF_COLOR_SETS;++i) - { - if (!pMesh->HasVertexColors(i))break; + for (; i < AI_MAX_NUMBER_OF_COLOR_SETS; ++i) { + if (!pMesh->HasVertexColors(i)) break; } - for (;i < AI_MAX_NUMBER_OF_COLOR_SETS;++i) - if (pMesh->HasVertexColors(i)) - { + for (; i < AI_MAX_NUMBER_OF_COLOR_SETS; ++i) + if (pMesh->HasVertexColors(i)) { ReportError("Vertex color channel %i is exists " - "although the previous channel was NULL.",i); + "although the previous channel was nullptr.", + i); } } - // now validate all bones - if (pMesh->mNumBones) - { - if (!pMesh->mBones) - { - ReportError("aiMesh::mBones is NULL (aiMesh::mNumBones is %i)", - pMesh->mNumBones); + if (pMesh->mNumBones) { + if (!pMesh->mBones) { + ReportError("aiMesh::mBones is nullptr (aiMesh::mNumBones is %i)", + pMesh->mNumBones); } std::unique_ptr afSum(nullptr); - if (pMesh->mNumVertices) - { + if (pMesh->mNumVertices) { afSum.reset(new float[pMesh->mNumVertices]); - for (unsigned int i = 0; i < pMesh->mNumVertices;++i) + for (unsigned int i = 0; i < pMesh->mNumVertices; ++i) afSum[i] = 0.0f; } // check whether there are duplicate bone names - for (unsigned int i = 0; i < pMesh->mNumBones;++i) - { - const aiBone* bone = pMesh->mBones[i]; + for (unsigned int i = 0; i < pMesh->mNumBones; ++i) { + const aiBone *bone = pMesh->mBones[i]; if (bone->mNumWeights > AI_MAX_BONE_WEIGHTS) { - ReportError("Bone %u has too many weights: %u, but the limit is %u",i,bone->mNumWeights,AI_MAX_BONE_WEIGHTS); + ReportError("Bone %u has too many weights: %u, but the limit is %u", i, bone->mNumWeights, AI_MAX_BONE_WEIGHTS); } - if (!pMesh->mBones[i]) - { - ReportError("aiMesh::mBones[%i] is NULL (aiMesh::mNumBones is %i)", - i,pMesh->mNumBones); + if (!pMesh->mBones[i]) { + ReportError("aiMesh::mBones[%i] is nullptr (aiMesh::mNumBones is %i)", + i, pMesh->mNumBones); } - Validate(pMesh,pMesh->mBones[i],afSum.get()); + Validate(pMesh, pMesh->mBones[i], afSum.get()); - for (unsigned int a = i+1; a < pMesh->mNumBones;++a) - { - if (pMesh->mBones[i]->mName == pMesh->mBones[a]->mName) - { + for (unsigned int a = i + 1; a < pMesh->mNumBones; ++a) { + if (pMesh->mBones[i]->mName == pMesh->mBones[a]->mName) { const char *name = "unknown"; - if (nullptr != pMesh->mBones[ i ]->mName.C_Str()) { - name = pMesh->mBones[ i ]->mName.C_Str(); + if (nullptr != pMesh->mBones[i]->mName.C_Str()) { + name = pMesh->mBones[i]->mName.C_Str(); } ReportError("aiMesh::mBones[%i], name = \"%s\" has the same name as " - "aiMesh::mBones[%i]", i, name, a ); + "aiMesh::mBones[%i]", + i, name, a); } } } // check whether all bone weights for a vertex sum to 1.0 ... - for (unsigned int i = 0; i < pMesh->mNumVertices;++i) - { + for (unsigned int i = 0; i < pMesh->mNumVertices; ++i) { if (afSum[i] && (afSum[i] <= 0.94 || afSum[i] >= 1.05)) { - ReportWarning("aiMesh::mVertices[%i]: bone weight sum != 1.0 (sum is %f)",i,afSum[i]); + ReportWarning("aiMesh::mVertices[%i]: bone weight sum != 1.0 (sum is %f)", i, afSum[i]); } } - } - else if (pMesh->mBones) - { + } else if (pMesh->mBones) { ReportError("aiMesh::mBones is non-null although there are no bones"); } } // ------------------------------------------------------------------------------------------------ -void ValidateDSProcess::Validate( const aiMesh* pMesh, const aiBone* pBone,float* afSum) { +void ValidateDSProcess::Validate(const aiMesh *pMesh, const aiBone *pBone, float *afSum) { this->Validate(&pBone->mName); - if (!pBone->mNumWeights) { + if (!pBone->mNumWeights) { //ReportError("aiBone::mNumWeights is zero"); } // check whether all vertices affected by this bone are valid - for (unsigned int i = 0; i < pBone->mNumWeights;++i) - { - if (pBone->mWeights[i].mVertexId >= pMesh->mNumVertices) { - ReportError("aiBone::mWeights[%i].mVertexId is out of range",i); - } - else if (!pBone->mWeights[i].mWeight || pBone->mWeights[i].mWeight > 1.0f) { - ReportWarning("aiBone::mWeights[%i].mWeight has an invalid value",i); + for (unsigned int i = 0; i < pBone->mNumWeights; ++i) { + if (pBone->mWeights[i].mVertexId >= pMesh->mNumVertices) { + ReportError("aiBone::mWeights[%i].mVertexId is out of range", i); + } else if (!pBone->mWeights[i].mWeight || pBone->mWeights[i].mWeight > 1.0f) { + ReportWarning("aiBone::mWeights[%i].mWeight has an invalid value", i); } afSum[pBone->mWeights[i].mVertexId] += pBone->mWeights[i].mWeight; } } // ------------------------------------------------------------------------------------------------ -void ValidateDSProcess::Validate( const aiAnimation* pAnimation) -{ +void ValidateDSProcess::Validate(const aiAnimation *pAnimation) { Validate(&pAnimation->mName); // validate all animations - if (pAnimation->mNumChannels || pAnimation->mNumMorphMeshChannels) - { + if (pAnimation->mNumChannels || pAnimation->mNumMorphMeshChannels) { if (!pAnimation->mChannels && pAnimation->mNumChannels) { - ReportError("aiAnimation::mChannels is NULL (aiAnimation::mNumChannels is %i)", - pAnimation->mNumChannels); + ReportError("aiAnimation::mChannels is nullptr (aiAnimation::mNumChannels is %i)", + pAnimation->mNumChannels); } if (!pAnimation->mMorphMeshChannels && pAnimation->mNumMorphMeshChannels) { - ReportError("aiAnimation::mMorphMeshChannels is NULL (aiAnimation::mNumMorphMeshChannels is %i)", - pAnimation->mNumMorphMeshChannels); + ReportError("aiAnimation::mMorphMeshChannels is nullptr (aiAnimation::mNumMorphMeshChannels is %i)", + pAnimation->mNumMorphMeshChannels); } - for (unsigned int i = 0; i < pAnimation->mNumChannels;++i) - { - if (!pAnimation->mChannels[i]) - { - ReportError("aiAnimation::mChannels[%i] is NULL (aiAnimation::mNumChannels is %i)", - i, pAnimation->mNumChannels); + for (unsigned int i = 0; i < pAnimation->mNumChannels; ++i) { + if (!pAnimation->mChannels[i]) { + ReportError("aiAnimation::mChannels[%i] is nullptr (aiAnimation::mNumChannels is %i)", + i, pAnimation->mNumChannels); } Validate(pAnimation, pAnimation->mChannels[i]); } - for (unsigned int i = 0; i < pAnimation->mNumMorphMeshChannels;++i) - { - if (!pAnimation->mMorphMeshChannels[i]) - { - ReportError("aiAnimation::mMorphMeshChannels[%i] is NULL (aiAnimation::mNumMorphMeshChannels is %i)", - i, pAnimation->mNumMorphMeshChannels); + for (unsigned int i = 0; i < pAnimation->mNumMorphMeshChannels; ++i) { + if (!pAnimation->mMorphMeshChannels[i]) { + ReportError("aiAnimation::mMorphMeshChannels[%i] is nullptr (aiAnimation::mNumMorphMeshChannels is %i)", + i, pAnimation->mNumMorphMeshChannels); } Validate(pAnimation, pAnimation->mMorphMeshChannels[i]); } - } - else { - ReportError("aiAnimation::mNumChannels is 0. At least one node animation channel must be there."); + } else { + ReportError("aiAnimation::mNumChannels is 0. At least one node animation channel must be there."); } } // ------------------------------------------------------------------------------------------------ -void ValidateDSProcess::SearchForInvalidTextures(const aiMaterial* pMaterial, - aiTextureType type) -{ - const char* szType = TextureTypeToString(type); +void ValidateDSProcess::SearchForInvalidTextures(const aiMaterial *pMaterial, + aiTextureType type) { + const char *szType = TextureTypeToString(type); // **************************************************************************** // Search all keys of the material ... @@ -587,11 +531,11 @@ void ValidateDSProcess::SearchForInvalidTextures(const aiMaterial* pMaterial, int iNumIndices = 0; int iIndex = -1; - for (unsigned int i = 0; i < pMaterial->mNumProperties;++i) { - aiMaterialProperty* prop = pMaterial->mProperties[ i ]; + for (unsigned int i = 0; i < pMaterial->mNumProperties; ++i) { + aiMaterialProperty *prop = pMaterial->mProperties[i]; ai_assert(nullptr != prop); - if ( !::strcmp(prop->mKey.data,"$tex.file") && prop->mSemantic == static_cast(type)) { - iIndex = std::max(iIndex, (int) prop->mIndex); + if (!::strcmp(prop->mKey.data, "$tex.file") && prop->mSemantic == static_cast(type)) { + iIndex = std::max(iIndex, (int)prop->mIndex); ++iNumIndices; if (aiPTI_String != prop->mType) { @@ -599,87 +543,75 @@ void ValidateDSProcess::SearchForInvalidTextures(const aiMaterial* pMaterial, } } } - if (iIndex +1 != iNumIndices) { + if (iIndex + 1 != iNumIndices) { ReportError("%s #%i is set, but there are only %i %s textures", - szType,iIndex,iNumIndices,szType); + szType, iIndex, iNumIndices, szType); + } + if (!iNumIndices) { + return; } - if (!iNumIndices) { - return; - } std::vector mappings(iNumIndices); // Now check whether all UV indices are valid ... bool bNoSpecified = true; - for (unsigned int i = 0; i < pMaterial->mNumProperties;++i) { - aiMaterialProperty* prop = pMaterial->mProperties[i]; - if (static_cast(prop->mSemantic) != type) { - continue; - } + for (unsigned int i = 0; i < pMaterial->mNumProperties; ++i) { + aiMaterialProperty *prop = pMaterial->mProperties[i]; + if (static_cast(prop->mSemantic) != type) { + continue; + } - if ((int)prop->mIndex >= iNumIndices) - { + if ((int)prop->mIndex >= iNumIndices) { ReportError("Found texture property with index %i, although there " - "are only %i textures of type %s", - prop->mIndex, iNumIndices, szType); + "are only %i textures of type %s", + prop->mIndex, iNumIndices, szType); } - if (!::strcmp(prop->mKey.data,"$tex.mapping")) { - if (aiPTI_Integer != prop->mType || prop->mDataLength < sizeof(aiTextureMapping)) - { + if (!::strcmp(prop->mKey.data, "$tex.mapping")) { + if (aiPTI_Integer != prop->mType || prop->mDataLength < sizeof(aiTextureMapping)) { ReportError("Material property %s%i is expected to be an integer (size is %i)", - prop->mKey.data,prop->mIndex,prop->mDataLength); + prop->mKey.data, prop->mIndex, prop->mDataLength); } - mappings[prop->mIndex] = *((aiTextureMapping*)prop->mData); - } - else if (!::strcmp(prop->mKey.data,"$tex.uvtrafo")) { - if (aiPTI_Float != prop->mType || prop->mDataLength < sizeof(aiUVTransform)) - { + mappings[prop->mIndex] = *((aiTextureMapping *)prop->mData); + } else if (!::strcmp(prop->mKey.data, "$tex.uvtrafo")) { + if (aiPTI_Float != prop->mType || prop->mDataLength < sizeof(aiUVTransform)) { ReportError("Material property %s%i is expected to be 5 floats large (size is %i)", - prop->mKey.data,prop->mIndex, prop->mDataLength); + prop->mKey.data, prop->mIndex, prop->mDataLength); } - //mappings[prop->mIndex] = ((aiUVTransform*)prop->mData); - } - else if (!::strcmp(prop->mKey.data,"$tex.uvwsrc")) { - if (aiPTI_Integer != prop->mType || sizeof(int) > prop->mDataLength) - { + //mappings[prop->mIndex] = ((aiUVTransform*)prop->mData); + } else if (!::strcmp(prop->mKey.data, "$tex.uvwsrc")) { + if (aiPTI_Integer != prop->mType || sizeof(int) > prop->mDataLength) { ReportError("Material property %s%i is expected to be an integer (size is %i)", - prop->mKey.data,prop->mIndex,prop->mDataLength); + prop->mKey.data, prop->mIndex, prop->mDataLength); } bNoSpecified = false; // Ignore UV indices for texture channels that are not there ... // Get the value - iIndex = *((unsigned int*)prop->mData); + iIndex = *((unsigned int *)prop->mData); // Check whether there is a mesh using this material // which has not enough UV channels ... - for (unsigned int a = 0; a < mScene->mNumMeshes;++a) - { - aiMesh* mesh = this->mScene->mMeshes[a]; - if(mesh->mMaterialIndex == (unsigned int)i) - { + for (unsigned int a = 0; a < mScene->mNumMeshes; ++a) { + aiMesh *mesh = this->mScene->mMeshes[a]; + if (mesh->mMaterialIndex == (unsigned int)i) { int iChannels = 0; - while (mesh->HasTextureCoords(iChannels))++iChannels; - if (iIndex >= iChannels) - { + while (mesh->HasTextureCoords(iChannels)) + ++iChannels; + if (iIndex >= iChannels) { ReportWarning("Invalid UV index: %i (key %s). Mesh %i has only %i UV channels", - iIndex,prop->mKey.data,a,iChannels); + iIndex, prop->mKey.data, a, iChannels); } } } } } - if (bNoSpecified) - { + if (bNoSpecified) { // Assume that all textures are using the first UV channel - for (unsigned int a = 0; a < mScene->mNumMeshes;++a) - { - aiMesh* mesh = mScene->mMeshes[a]; - if(mesh->mMaterialIndex == (unsigned int)iIndex && mappings[0] == aiTextureMapping_UV) - { - if (!mesh->mTextureCoords[0]) - { + for (unsigned int a = 0; a < mScene->mNumMeshes; ++a) { + aiMesh *mesh = mScene->mMeshes[a]; + if (mesh->mMaterialIndex == (unsigned int)iIndex && mappings[0] == aiTextureMapping_UV) { + if (!mesh->mTextureCoords[0]) { // This is a special case ... it could be that the // original mesh format intended the use of a special // mapping here. @@ -690,46 +622,43 @@ void ValidateDSProcess::SearchForInvalidTextures(const aiMaterial* pMaterial, } } // ------------------------------------------------------------------------------------------------ -void ValidateDSProcess::Validate( const aiMaterial* pMaterial) -{ +void ValidateDSProcess::Validate(const aiMaterial *pMaterial) { // check whether there are material keys that are obviously not legal - for (unsigned int i = 0; i < pMaterial->mNumProperties;++i) - { - const aiMaterialProperty* prop = pMaterial->mProperties[i]; - if (!prop) { - ReportError("aiMaterial::mProperties[%i] is NULL (aiMaterial::mNumProperties is %i)", - i,pMaterial->mNumProperties); + for (unsigned int i = 0; i < pMaterial->mNumProperties; ++i) { + const aiMaterialProperty *prop = pMaterial->mProperties[i]; + if (!prop) { + ReportError("aiMaterial::mProperties[%i] is nullptr (aiMaterial::mNumProperties is %i)", + i, pMaterial->mNumProperties); } if (!prop->mDataLength || !prop->mData) { ReportError("aiMaterial::mProperties[%i].mDataLength or " - "aiMaterial::mProperties[%i].mData is 0",i,i); + "aiMaterial::mProperties[%i].mData is 0", + i, i); } // check all predefined types - if (aiPTI_String == prop->mType) { + if (aiPTI_String == prop->mType) { // FIX: strings are now stored in a less expensive way, but we can't use the // validation routine for 'normal' aiStrings - if (prop->mDataLength < 5 || prop->mDataLength < 4 + (*reinterpret_cast(prop->mData)) + 1) { + if (prop->mDataLength < 5 || prop->mDataLength < 4 + (*reinterpret_cast(prop->mData)) + 1) { ReportError("aiMaterial::mProperties[%i].mDataLength is " - "too small to contain a string (%i, needed: %i)", - i,prop->mDataLength,static_cast(sizeof(aiString))); + "too small to contain a string (%i, needed: %i)", + i, prop->mDataLength, static_cast(sizeof(aiString))); } - if(prop->mData[prop->mDataLength-1]) { + if (prop->mData[prop->mDataLength - 1]) { ReportError("Missing null-terminator in string material property"); } - // Validate((const aiString*)prop->mData); - } - else if (aiPTI_Float == prop->mType) { - if (prop->mDataLength < sizeof(float)) { + // Validate((const aiString*)prop->mData); + } else if (aiPTI_Float == prop->mType) { + if (prop->mDataLength < sizeof(float)) { ReportError("aiMaterial::mProperties[%i].mDataLength is " - "too small to contain a float (%i, needed: %i)", - i,prop->mDataLength, static_cast(sizeof(float))); + "too small to contain a float (%i, needed: %i)", + i, prop->mDataLength, static_cast(sizeof(float))); } - } - else if (aiPTI_Integer == prop->mType) { - if (prop->mDataLength < sizeof(int)) { + } else if (aiPTI_Integer == prop->mType) { + if (prop->mDataLength < sizeof(int)) { ReportError("aiMaterial::mProperties[%i].mDataLength is " - "too small to contain an integer (%i, needed: %i)", - i,prop->mDataLength, static_cast(sizeof(int))); + "too small to contain an integer (%i, needed: %i)", + i, prop->mDataLength, static_cast(sizeof(int))); } } // TODO: check whether there is a key with an unknown name ... @@ -738,20 +667,19 @@ void ValidateDSProcess::Validate( const aiMaterial* pMaterial) // make some more specific tests ai_real fTemp; int iShading; - if (AI_SUCCESS == aiGetMaterialInteger( pMaterial,AI_MATKEY_SHADING_MODEL,&iShading)) { - switch ((aiShadingMode)iShading) - { + if (AI_SUCCESS == aiGetMaterialInteger(pMaterial, AI_MATKEY_SHADING_MODEL, &iShading)) { + switch ((aiShadingMode)iShading) { case aiShadingMode_Blinn: case aiShadingMode_CookTorrance: case aiShadingMode_Phong: - if (AI_SUCCESS != aiGetMaterialFloat(pMaterial,AI_MATKEY_SHININESS,&fTemp)) { + if (AI_SUCCESS != aiGetMaterialFloat(pMaterial, AI_MATKEY_SHININESS, &fTemp)) { ReportWarning("A specular shading model is specified but there is no " - "AI_MATKEY_SHININESS key"); + "AI_MATKEY_SHININESS key"); } - if (AI_SUCCESS == aiGetMaterialFloat(pMaterial,AI_MATKEY_SHININESS_STRENGTH,&fTemp) && !fTemp) { + if (AI_SUCCESS == aiGetMaterialFloat(pMaterial, AI_MATKEY_SHININESS_STRENGTH, &fTemp) && !fTemp) { ReportWarning("A specular shading model is specified but the value of the " - "AI_MATKEY_SHININESS_STRENGTH key is 0.0"); + "AI_MATKEY_SHININESS_STRENGTH key is 0.0"); } break; default: @@ -759,175 +687,160 @@ void ValidateDSProcess::Validate( const aiMaterial* pMaterial) } } - if (AI_SUCCESS == aiGetMaterialFloat( pMaterial,AI_MATKEY_OPACITY,&fTemp) && (!fTemp || fTemp > 1.01)) { + if (AI_SUCCESS == aiGetMaterialFloat(pMaterial, AI_MATKEY_OPACITY, &fTemp) && (!fTemp || fTemp > 1.01)) { ReportWarning("Invalid opacity value (must be 0 < opacity < 1.0)"); } // Check whether there are invalid texture keys // TODO: that's a relict of the past, where texture type and index were baked // into the material string ... we could do that in one single pass. - SearchForInvalidTextures(pMaterial,aiTextureType_DIFFUSE); - SearchForInvalidTextures(pMaterial,aiTextureType_SPECULAR); - SearchForInvalidTextures(pMaterial,aiTextureType_AMBIENT); - SearchForInvalidTextures(pMaterial,aiTextureType_EMISSIVE); - SearchForInvalidTextures(pMaterial,aiTextureType_OPACITY); - SearchForInvalidTextures(pMaterial,aiTextureType_SHININESS); - SearchForInvalidTextures(pMaterial,aiTextureType_HEIGHT); - SearchForInvalidTextures(pMaterial,aiTextureType_NORMALS); - SearchForInvalidTextures(pMaterial,aiTextureType_DISPLACEMENT); - SearchForInvalidTextures(pMaterial,aiTextureType_LIGHTMAP); - SearchForInvalidTextures(pMaterial,aiTextureType_REFLECTION); - SearchForInvalidTextures(pMaterial,aiTextureType_BASE_COLOR); - SearchForInvalidTextures(pMaterial,aiTextureType_NORMAL_CAMERA); - SearchForInvalidTextures(pMaterial,aiTextureType_EMISSION_COLOR); - SearchForInvalidTextures(pMaterial,aiTextureType_METALNESS); - SearchForInvalidTextures(pMaterial,aiTextureType_DIFFUSE_ROUGHNESS); - SearchForInvalidTextures(pMaterial,aiTextureType_AMBIENT_OCCLUSION); + SearchForInvalidTextures(pMaterial, aiTextureType_DIFFUSE); + SearchForInvalidTextures(pMaterial, aiTextureType_SPECULAR); + SearchForInvalidTextures(pMaterial, aiTextureType_AMBIENT); + SearchForInvalidTextures(pMaterial, aiTextureType_EMISSIVE); + SearchForInvalidTextures(pMaterial, aiTextureType_OPACITY); + SearchForInvalidTextures(pMaterial, aiTextureType_SHININESS); + SearchForInvalidTextures(pMaterial, aiTextureType_HEIGHT); + SearchForInvalidTextures(pMaterial, aiTextureType_NORMALS); + SearchForInvalidTextures(pMaterial, aiTextureType_DISPLACEMENT); + SearchForInvalidTextures(pMaterial, aiTextureType_LIGHTMAP); + SearchForInvalidTextures(pMaterial, aiTextureType_REFLECTION); + SearchForInvalidTextures(pMaterial, aiTextureType_BASE_COLOR); + SearchForInvalidTextures(pMaterial, aiTextureType_NORMAL_CAMERA); + SearchForInvalidTextures(pMaterial, aiTextureType_EMISSION_COLOR); + SearchForInvalidTextures(pMaterial, aiTextureType_METALNESS); + SearchForInvalidTextures(pMaterial, aiTextureType_DIFFUSE_ROUGHNESS); + SearchForInvalidTextures(pMaterial, aiTextureType_AMBIENT_OCCLUSION); } // ------------------------------------------------------------------------------------------------ -void ValidateDSProcess::Validate( const aiTexture* pTexture) -{ - // the data section may NEVER be NULL - if (!pTexture->pcData) { - ReportError("aiTexture::pcData is NULL"); +void ValidateDSProcess::Validate(const aiTexture *pTexture) { + // the data section may NEVER be nullptr + if (nullptr == pTexture->pcData) { + ReportError("aiTexture::pcData is nullptr"); } - if (pTexture->mHeight) - { - if (!pTexture->mWidth){ - ReportError("aiTexture::mWidth is zero (aiTexture::mHeight is %i, uncompressed texture)", - pTexture->mHeight); + if (pTexture->mHeight) { + if (!pTexture->mWidth) { + ReportError("aiTexture::mWidth is zero (aiTexture::mHeight is %i, uncompressed texture)", + pTexture->mHeight); } - } - else - { + } else { if (!pTexture->mWidth) { ReportError("aiTexture::mWidth is zero (compressed texture)"); } if ('\0' != pTexture->achFormatHint[HINTMAXTEXTURELEN - 1]) { ReportWarning("aiTexture::achFormatHint must be zero-terminated"); - } - else if ('.' == pTexture->achFormatHint[0]) { + } else if ('.' == pTexture->achFormatHint[0]) { ReportWarning("aiTexture::achFormatHint should contain a file extension " - "without a leading dot (format hint: %s).",pTexture->achFormatHint); + "without a leading dot (format hint: %s).", + pTexture->achFormatHint); } } - const char* sz = pTexture->achFormatHint; + const char *sz = pTexture->achFormatHint; if ((sz[0] >= 'A' && sz[0] <= 'Z') || - (sz[1] >= 'A' && sz[1] <= 'Z') || - (sz[2] >= 'A' && sz[2] <= 'Z') || - (sz[3] >= 'A' && sz[3] <= 'Z')) { + (sz[1] >= 'A' && sz[1] <= 'Z') || + (sz[2] >= 'A' && sz[2] <= 'Z') || + (sz[3] >= 'A' && sz[3] <= 'Z')) { ReportError("aiTexture::achFormatHint contains non-lowercase letters"); } } // ------------------------------------------------------------------------------------------------ -void ValidateDSProcess::Validate( const aiAnimation* pAnimation, - const aiNodeAnim* pNodeAnim) -{ +void ValidateDSProcess::Validate(const aiAnimation *pAnimation, + const aiNodeAnim *pNodeAnim) { Validate(&pNodeAnim->mNodeName); if (!pNodeAnim->mNumPositionKeys && !pNodeAnim->mScalingKeys && !pNodeAnim->mNumRotationKeys) { ReportError("Empty node animation channel"); } // otherwise check whether one of the keys exceeds the total duration of the animation - if (pNodeAnim->mNumPositionKeys) - { - if (!pNodeAnim->mPositionKeys) - { - ReportError("aiNodeAnim::mPositionKeys is NULL (aiNodeAnim::mNumPositionKeys is %i)", - pNodeAnim->mNumPositionKeys); + if (pNodeAnim->mNumPositionKeys) { + if (!pNodeAnim->mPositionKeys) { + ReportError("aiNodeAnim::mPositionKeys is nullptr (aiNodeAnim::mNumPositionKeys is %i)", + pNodeAnim->mNumPositionKeys); } double dLast = -10e10; - for (unsigned int i = 0; i < pNodeAnim->mNumPositionKeys;++i) - { + for (unsigned int i = 0; i < pNodeAnim->mNumPositionKeys; ++i) { // ScenePreprocessor will compute the duration if still the default value // (Aramis) Add small epsilon, comparison tended to fail if max_time == duration, // seems to be due the compilers register usage/width. - if (pAnimation->mDuration > 0. && pNodeAnim->mPositionKeys[i].mTime > pAnimation->mDuration+0.001) - { + if (pAnimation->mDuration > 0. && pNodeAnim->mPositionKeys[i].mTime > pAnimation->mDuration + 0.001) { ReportError("aiNodeAnim::mPositionKeys[%i].mTime (%.5f) is larger " - "than aiAnimation::mDuration (which is %.5f)",i, - (float)pNodeAnim->mPositionKeys[i].mTime, - (float)pAnimation->mDuration); + "than aiAnimation::mDuration (which is %.5f)", + i, + (float)pNodeAnim->mPositionKeys[i].mTime, + (float)pAnimation->mDuration); } - if (i && pNodeAnim->mPositionKeys[i].mTime <= dLast) - { + if (i && pNodeAnim->mPositionKeys[i].mTime <= dLast) { ReportWarning("aiNodeAnim::mPositionKeys[%i].mTime (%.5f) is smaller " - "than aiAnimation::mPositionKeys[%i] (which is %.5f)",i, - (float)pNodeAnim->mPositionKeys[i].mTime, - i-1, (float)dLast); + "than aiAnimation::mPositionKeys[%i] (which is %.5f)", + i, + (float)pNodeAnim->mPositionKeys[i].mTime, + i - 1, (float)dLast); } dLast = pNodeAnim->mPositionKeys[i].mTime; } } // rotation keys - if (pNodeAnim->mNumRotationKeys) - { - if (!pNodeAnim->mRotationKeys) - { - ReportError("aiNodeAnim::mRotationKeys is NULL (aiNodeAnim::mNumRotationKeys is %i)", - pNodeAnim->mNumRotationKeys); + if (pNodeAnim->mNumRotationKeys) { + if (!pNodeAnim->mRotationKeys) { + ReportError("aiNodeAnim::mRotationKeys is nullptr (aiNodeAnim::mNumRotationKeys is %i)", + pNodeAnim->mNumRotationKeys); } double dLast = -10e10; - for (unsigned int i = 0; i < pNodeAnim->mNumRotationKeys;++i) - { - if (pAnimation->mDuration > 0. && pNodeAnim->mRotationKeys[i].mTime > pAnimation->mDuration+0.001) - { + for (unsigned int i = 0; i < pNodeAnim->mNumRotationKeys; ++i) { + if (pAnimation->mDuration > 0. && pNodeAnim->mRotationKeys[i].mTime > pAnimation->mDuration + 0.001) { ReportError("aiNodeAnim::mRotationKeys[%i].mTime (%.5f) is larger " - "than aiAnimation::mDuration (which is %.5f)",i, - (float)pNodeAnim->mRotationKeys[i].mTime, - (float)pAnimation->mDuration); + "than aiAnimation::mDuration (which is %.5f)", + i, + (float)pNodeAnim->mRotationKeys[i].mTime, + (float)pAnimation->mDuration); } - if (i && pNodeAnim->mRotationKeys[i].mTime <= dLast) - { + if (i && pNodeAnim->mRotationKeys[i].mTime <= dLast) { ReportWarning("aiNodeAnim::mRotationKeys[%i].mTime (%.5f) is smaller " - "than aiAnimation::mRotationKeys[%i] (which is %.5f)",i, - (float)pNodeAnim->mRotationKeys[i].mTime, - i-1, (float)dLast); + "than aiAnimation::mRotationKeys[%i] (which is %.5f)", + i, + (float)pNodeAnim->mRotationKeys[i].mTime, + i - 1, (float)dLast); } dLast = pNodeAnim->mRotationKeys[i].mTime; } } // scaling keys - if (pNodeAnim->mNumScalingKeys) - { - if (!pNodeAnim->mScalingKeys) { - ReportError("aiNodeAnim::mScalingKeys is NULL (aiNodeAnim::mNumScalingKeys is %i)", - pNodeAnim->mNumScalingKeys); + if (pNodeAnim->mNumScalingKeys) { + if (!pNodeAnim->mScalingKeys) { + ReportError("aiNodeAnim::mScalingKeys is nullptr (aiNodeAnim::mNumScalingKeys is %i)", + pNodeAnim->mNumScalingKeys); } double dLast = -10e10; - for (unsigned int i = 0; i < pNodeAnim->mNumScalingKeys;++i) - { - if (pAnimation->mDuration > 0. && pNodeAnim->mScalingKeys[i].mTime > pAnimation->mDuration+0.001) - { + for (unsigned int i = 0; i < pNodeAnim->mNumScalingKeys; ++i) { + if (pAnimation->mDuration > 0. && pNodeAnim->mScalingKeys[i].mTime > pAnimation->mDuration + 0.001) { ReportError("aiNodeAnim::mScalingKeys[%i].mTime (%.5f) is larger " - "than aiAnimation::mDuration (which is %.5f)",i, - (float)pNodeAnim->mScalingKeys[i].mTime, - (float)pAnimation->mDuration); + "than aiAnimation::mDuration (which is %.5f)", + i, + (float)pNodeAnim->mScalingKeys[i].mTime, + (float)pAnimation->mDuration); } - if (i && pNodeAnim->mScalingKeys[i].mTime <= dLast) - { + if (i && pNodeAnim->mScalingKeys[i].mTime <= dLast) { ReportWarning("aiNodeAnim::mScalingKeys[%i].mTime (%.5f) is smaller " - "than aiAnimation::mScalingKeys[%i] (which is %.5f)",i, - (float)pNodeAnim->mScalingKeys[i].mTime, - i-1, (float)dLast); + "than aiAnimation::mScalingKeys[%i] (which is %.5f)", + i, + (float)pNodeAnim->mScalingKeys[i].mTime, + i - 1, (float)dLast); } dLast = pNodeAnim->mScalingKeys[i].mTime; } } if (!pNodeAnim->mNumScalingKeys && !pNodeAnim->mNumRotationKeys && - !pNodeAnim->mNumPositionKeys) - { + !pNodeAnim->mNumPositionKeys) { ReportError("A node animation channel must have at least one subtrack"); } } -void ValidateDSProcess::Validate( const aiAnimation* pAnimation, - const aiMeshMorphAnim* pMeshMorphAnim) -{ +void ValidateDSProcess::Validate(const aiAnimation *pAnimation, + const aiMeshMorphAnim *pMeshMorphAnim) { Validate(&pMeshMorphAnim->mName); if (!pMeshMorphAnim->mNumKeys) { @@ -935,32 +848,29 @@ void ValidateDSProcess::Validate( const aiAnimation* pAnimation, } // otherwise check whether one of the keys exceeds the total duration of the animation - if (pMeshMorphAnim->mNumKeys) - { - if (!pMeshMorphAnim->mKeys) - { - ReportError("aiMeshMorphAnim::mKeys is NULL (aiMeshMorphAnim::mNumKeys is %i)", - pMeshMorphAnim->mNumKeys); + if (pMeshMorphAnim->mNumKeys) { + if (!pMeshMorphAnim->mKeys) { + ReportError("aiMeshMorphAnim::mKeys is nullptr (aiMeshMorphAnim::mNumKeys is %i)", + pMeshMorphAnim->mNumKeys); } double dLast = -10e10; - for (unsigned int i = 0; i < pMeshMorphAnim->mNumKeys;++i) - { + for (unsigned int i = 0; i < pMeshMorphAnim->mNumKeys; ++i) { // ScenePreprocessor will compute the duration if still the default value // (Aramis) Add small epsilon, comparison tended to fail if max_time == duration, // seems to be due the compilers register usage/width. - if (pAnimation->mDuration > 0. && pMeshMorphAnim->mKeys[i].mTime > pAnimation->mDuration+0.001) - { + if (pAnimation->mDuration > 0. && pMeshMorphAnim->mKeys[i].mTime > pAnimation->mDuration + 0.001) { ReportError("aiMeshMorphAnim::mKeys[%i].mTime (%.5f) is larger " - "than aiAnimation::mDuration (which is %.5f)",i, - (float)pMeshMorphAnim->mKeys[i].mTime, - (float)pAnimation->mDuration); + "than aiAnimation::mDuration (which is %.5f)", + i, + (float)pMeshMorphAnim->mKeys[i].mTime, + (float)pAnimation->mDuration); } - if (i && pMeshMorphAnim->mKeys[i].mTime <= dLast) - { + if (i && pMeshMorphAnim->mKeys[i].mTime <= dLast) { ReportWarning("aiMeshMorphAnim::mKeys[%i].mTime (%.5f) is smaller " - "than aiMeshMorphAnim::mKeys[%i] (which is %.5f)",i, - (float)pMeshMorphAnim->mKeys[i].mTime, - i-1, (float)dLast); + "than aiMeshMorphAnim::mKeys[%i] (which is %.5f)", + i, + (float)pMeshMorphAnim->mKeys[i].mTime, + i - 1, (float)dLast); } dLast = pMeshMorphAnim->mKeys[i].mTime; } @@ -968,74 +878,62 @@ void ValidateDSProcess::Validate( const aiAnimation* pAnimation, } // ------------------------------------------------------------------------------------------------ -void ValidateDSProcess::Validate( const aiNode* pNode) -{ +void ValidateDSProcess::Validate(const aiNode *pNode) { if (!pNode) { - ReportError("A node of the scenegraph is NULL"); + ReportError("A node of the scene-graph is nullptr"); } // Validate node name string first so that it's safe to use in below expressions this->Validate(&pNode->mName); - const char* nodeName = (&pNode->mName)->C_Str(); - if (pNode != mScene->mRootNode && !pNode->mParent){ - ReportError("Non-root node %s lacks a valid parent (aiNode::mParent is NULL) ", nodeName); + const char *nodeName = (&pNode->mName)->C_Str(); + if (pNode != mScene->mRootNode && !pNode->mParent) { + ReportError("Non-root node %s lacks a valid parent (aiNode::mParent is nullptr) ", nodeName); } // validate all meshes - if (pNode->mNumMeshes) - { - if (!pNode->mMeshes) - { - ReportError("aiNode::mMeshes is NULL for node %s (aiNode::mNumMeshes is %i)", - nodeName, pNode->mNumMeshes); + if (pNode->mNumMeshes) { + if (!pNode->mMeshes) { + ReportError("aiNode::mMeshes is nullptr for node %s (aiNode::mNumMeshes is %i)", + nodeName, pNode->mNumMeshes); } std::vector abHadMesh; - abHadMesh.resize(mScene->mNumMeshes,false); - for (unsigned int i = 0; i < pNode->mNumMeshes;++i) - { - if (pNode->mMeshes[i] >= mScene->mNumMeshes) - { + abHadMesh.resize(mScene->mNumMeshes, false); + for (unsigned int i = 0; i < pNode->mNumMeshes; ++i) { + if (pNode->mMeshes[i] >= mScene->mNumMeshes) { ReportError("aiNode::mMeshes[%i] is out of range for node %s (maximum is %i)", - pNode->mMeshes[i], nodeName, mScene->mNumMeshes-1); + pNode->mMeshes[i], nodeName, mScene->mNumMeshes - 1); } - if (abHadMesh[pNode->mMeshes[i]]) - { + if (abHadMesh[pNode->mMeshes[i]]) { ReportError("aiNode::mMeshes[%i] is already referenced by this node %s (value: %i)", - i, nodeName, pNode->mMeshes[i]); + i, nodeName, pNode->mMeshes[i]); } abHadMesh[pNode->mMeshes[i]] = true; } } - if (pNode->mNumChildren) - { - if (!pNode->mChildren) { - ReportError("aiNode::mChildren is NULL for node %s (aiNode::mNumChildren is %i)", - nodeName, pNode->mNumChildren); + if (pNode->mNumChildren) { + if (!pNode->mChildren) { + ReportError("aiNode::mChildren is nullptr for node %s (aiNode::mNumChildren is %i)", + nodeName, pNode->mNumChildren); } - for (unsigned int i = 0; i < pNode->mNumChildren;++i) { + for (unsigned int i = 0; i < pNode->mNumChildren; ++i) { Validate(pNode->mChildren[i]); } } } // ------------------------------------------------------------------------------------------------ -void ValidateDSProcess::Validate( const aiString* pString) -{ - if (pString->length > MAXLEN) - { +void ValidateDSProcess::Validate(const aiString *pString) { + if (pString->length > MAXLEN) { ReportError("aiString::length is too large (%u, maximum is %lu)", - pString->length,MAXLEN); + pString->length, MAXLEN); } - const char* sz = pString->data; - while (true) - { - if ('\0' == *sz) - { - if (pString->length != (unsigned int)(sz-pString->data)) { + const char *sz = pString->data; + while (true) { + if ('\0' == *sz) { + if (pString->length != (unsigned int)(sz - pString->data)) { ReportError("aiString::data is invalid: the terminal zero is at a wrong offset"); } break; - } - else if (sz >= &pString->data[MAXLEN]) { + } else if (sz >= &pString->data[MAXLEN]) { ReportError("aiString::data is invalid. There is no terminal character"); } ++sz; diff --git a/contrib/Open3DGC/o3dgcSC3DMCDecoder.inl b/contrib/Open3DGC/o3dgcSC3DMCDecoder.inl index 326297426..c965fcd50 100644 --- a/contrib/Open3DGC/o3dgcSC3DMCDecoder.inl +++ b/contrib/Open3DGC/o3dgcSC3DMCDecoder.inl @@ -72,9 +72,12 @@ namespace o3dgc unsigned char mask = bstream.ReadUChar(m_iterator, m_streamType); ifs.SetCCW ((mask & 1) == 1); - ifs.SetSolid ((mask & 2) == 1); - ifs.SetConvex ((mask & 4) == 1); - ifs.SetIsTriangularMesh((mask & 8) == 1); + // (mask & 2) == 1 + ifs.SetSolid (false); + // (mask & 4) == 1 + ifs.SetConvex (false); + // (mask & 8) == 1 + ifs.SetIsTriangularMesh(false); //bool markerBit0 = (mask & 16 ) == 1; //bool markerBit1 = (mask & 32 ) == 1; //bool markerBit2 = (mask & 64 ) == 1; diff --git a/contrib/rapidjson/include/rapidjson/document.h b/contrib/rapidjson/include/rapidjson/document.h index 93b091f64..473d846e3 100644 --- a/contrib/rapidjson/include/rapidjson/document.h +++ b/contrib/rapidjson/include/rapidjson/document.h @@ -17,6 +17,11 @@ /*! \file document.h */ +#if (__GNUC__ >= 8 && __GNUC_MINOR__ >= 0) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wclass-memaccess" +#endif + #include "reader.h" #include "internal/meta.h" #include "internal/strfunc.h" @@ -2610,4 +2615,8 @@ private: RAPIDJSON_NAMESPACE_END RAPIDJSON_DIAG_POP +#if (__GNUC__ == 8 && __GNUC_MINOR__ >= 0) +#pragma GCC diagnostic pop +#endif + #endif // RAPIDJSON_DOCUMENT_H_ diff --git a/include/assimp/BaseImporter.h b/include/assimp/BaseImporter.h index 7cf835174..ed146168d 100644 --- a/include/assimp/BaseImporter.h +++ b/include/assimp/BaseImporter.h @@ -46,22 +46,22 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define INCLUDED_AI_BASEIMPORTER_H #ifdef __GNUC__ -# pragma GCC system_header +#pragma GCC system_header #endif #include "Exceptional.h" -#include -#include -#include +#include #include #include -#include +#include +#include +#include struct aiScene; struct aiImporterDesc; -namespace Assimp { +namespace Assimp { class Importer; class IOSystem; @@ -71,8 +71,7 @@ class IOStream; // utility to do char4 to uint32 in a portable manner #define AI_MAKE_MAGIC(string) ((uint32_t)((string[0] << 24) + \ - (string[1] << 16) + (string[2] << 8) + string[3])) - + (string[1] << 16) + (string[2] << 8) + string[3])) // --------------------------------------------------------------------------- /** FOR IMPORTER PLUGINS ONLY: The BaseImporter defines a common interface @@ -89,10 +88,9 @@ class ASSIMP_API BaseImporter { private: /* Pushes state into importer for the importer scale */ - virtual void UpdateImporterScale( Importer* pImp ); + virtual void UpdateImporterScale(Importer *pImp); public: - /** Constructor to be privately used by #Importer */ BaseImporter() AI_NO_EXCEPT; @@ -118,22 +116,21 @@ public: * @return true if the class can read this file, false if not. */ virtual bool CanRead( - const std::string& pFile, - IOSystem* pIOHandler, - bool checkSig - ) const = 0; + const std::string &pFile, + IOSystem *pIOHandler, + bool checkSig) const = 0; // ------------------------------------------------------------------- /** Imports the given file and returns the imported data. * If the import succeeds, ownership of the data is transferred to - * the caller. If the import fails, NULL is returned. The function + * the caller. If the import fails, nullptr is returned. The function * takes care that any partially constructed data is destroyed * beforehand. * * @param pImp #Importer object hosting this loader. * @param pFile Path of the file to be imported. * @param pIOHandler IO-Handler used to open this and possible other files. - * @return The imported data or NULL if failed. If it failed a + * @return The imported data or nullptr if failed. If it failed a * human-readable error description can be retrieved by calling * GetErrorText() * @@ -142,18 +139,17 @@ public: * in InternReadFile(), this function will catch it and transform it into * a suitable response to the caller. */ - aiScene* ReadFile( - Importer* pImp, - const std::string& pFile, - IOSystem* pIOHandler - ); + aiScene *ReadFile( + Importer *pImp, + const std::string &pFile, + IOSystem *pIOHandler); // ------------------------------------------------------------------- /** Returns the error description of the last error that occurred. * @return A description of the last error that occurred. An empty * string if there was no error. */ - const std::string& GetErrorText() const { + const std::string &GetErrorText() const { return m_ErrorText; } @@ -164,24 +160,21 @@ public: * @param pImp Importer instance */ virtual void SetupProperties( - const Importer* pImp - ); + const Importer *pImp); // ------------------------------------------------------------------- /** Called by #Importer::GetImporterInfo to get a description of * some loader features. Importers must provide this information. */ - virtual const aiImporterDesc* GetInfo() const = 0; + virtual const aiImporterDesc *GetInfo() const = 0; /** * Will be called only by scale process when scaling is requested. */ - virtual void SetFileScale(double scale) - { + virtual void SetFileScale(double scale) { fileScale = scale; } - virtual double GetFileScale() const - { + virtual double GetFileScale() const { return fileScale; } @@ -204,14 +197,12 @@ public: * */ std::map importerUnits; - virtual void SetApplicationUnits( const ImporterUnits& unit ) - { + virtual void SetApplicationUnits(const ImporterUnits &unit) { importerScale = importerUnits[unit]; applicationUnits = unit; } - virtual const ImporterUnits& GetApplicationUnits() - { + virtual const ImporterUnits &GetApplicationUnits() { return applicationUnits; } @@ -220,15 +211,13 @@ public: * Take the extension list contained in the structure returned by * #GetInfo and insert all file extensions into the given set. * @param extension set to collect file extensions in*/ - void GetExtensionList(std::set& extensions); - -protected: + void GetExtensionList(std::set &extensions); + +protected: ImporterUnits applicationUnits = ImporterUnits::M; double importerScale = 1.0; double fileScale = 1.0; - - // ------------------------------------------------------------------- /** Imports the given file into the given scene structure. The * function is expected to throw an ImportErrorException if there is @@ -249,7 +238,7 @@ protected: *
  • aiAnimation::mDuration may be -1. Assimp determines the length * of the animation automatically in this case as the length of * the longest animation channel.
  • - *
  • aiMesh::mBitangents may be NULL if tangents and normals are + *
  • aiMesh::mBitangents may be nullptr if tangents and normals are * given. In this case bitangents are computed as the cross product * between normal and tangent.
  • *
  • There needn't be a material. If none is there a default material @@ -270,17 +259,15 @@ protected: * * @param pFile Path of the file to be imported. * @param pScene The scene object to hold the imported data. - * NULL is not a valid parameter. + * nullptr is not a valid parameter. * @param pIOHandler The IO handler to use for any file access. - * NULL is not a valid parameter. */ + * nullptr is not a valid parameter. */ virtual void InternReadFile( - const std::string& pFile, - aiScene* pScene, - IOSystem* pIOHandler - ) = 0; + const std::string &pFile, + aiScene *pScene, + IOSystem *pIOHandler) = 0; public: // static utilities - // ------------------------------------------------------------------- /** A utility for CanRead(). * @@ -296,13 +283,13 @@ public: // static utilities * @param searchBytes Number of bytes to be searched for the tokens. */ static bool SearchFileHeaderForToken( - IOSystem* pIOSystem, - const std::string& file, - const char** tokens, - unsigned int numTokens, - unsigned int searchBytes = 200, - bool tokensSol = false, - bool noAlphaBeforeTokens = false); + IOSystem *pIOSystem, + const std::string &file, + const char **tokens, + unsigned int numTokens, + unsigned int searchBytes = 200, + bool tokensSol = false, + bool noAlphaBeforeTokens = false); // ------------------------------------------------------------------- /** @brief Check whether a file has a specific file extension @@ -312,19 +299,19 @@ public: // static utilities * @param ext2 Optional third extension * @note Case-insensitive */ - static bool SimpleExtensionCheck ( - const std::string& pFile, - const char* ext0, - const char* ext1 = NULL, - const char* ext2 = NULL); + static bool SimpleExtensionCheck( + const std::string &pFile, + const char *ext0, + const char *ext1 = nullptr, + const char *ext2 = nullptr); // ------------------------------------------------------------------- /** @brief Extract file extension from a string * @param pFile Input file * @return Extension without trailing dot, all lowercase */ - static std::string GetExtension ( - const std::string& pFile); + static std::string GetExtension( + const std::string &pFile); // ------------------------------------------------------------------- /** @brief Check whether a file starts with one or more magic tokens @@ -341,12 +328,12 @@ public: // static utilities * tokens of size 2,4. */ static bool CheckMagicToken( - IOSystem* pIOHandler, - const std::string& pFile, - const void* magic, - unsigned int num, - unsigned int offset = 0, - unsigned int size = 4); + IOSystem *pIOHandler, + const std::string &pFile, + const void *magic, + unsigned int num, + unsigned int offset = 0, + unsigned int size = 4); // ------------------------------------------------------------------- /** An utility for all text file loaders. It converts a file to our @@ -355,7 +342,7 @@ public: // static utilities * @param data File buffer to be converted to UTF8 data. The buffer * is resized as appropriate. */ static void ConvertToUTF8( - std::vector& data); + std::vector &data); // ------------------------------------------------------------------- /** An utility for all text file loaders. It converts a file from our @@ -364,13 +351,13 @@ public: // static utilities * @param data File buffer to be converted from UTF8 to ISO-8859-1. The buffer * is resized as appropriate. */ static void ConvertUTF8toISO8859_1( - std::string& data); + std::string &data); // ------------------------------------------------------------------- /// @brief Enum to define, if empty files are ok or not. - enum TextFileMode { + enum TextFileMode { ALLOW_EMPTY, - FORBID_EMPTY + FORBID_EMPTY }; // ------------------------------------------------------------------- @@ -383,22 +370,20 @@ public: // static utilities * a binary 0. * @param mode Whether it is OK to load empty text files. */ static void TextFileToBuffer( - IOStream* stream, - std::vector& data, - TextFileMode mode = FORBID_EMPTY); + IOStream *stream, + std::vector &data, + TextFileMode mode = FORBID_EMPTY); // ------------------------------------------------------------------- /** Utility function to move a std::vector into a aiScene array * @param vec The vector to be moved * @param out The output pointer to the allocated array. * @param numOut The output count of elements copied. */ - template - AI_FORCE_INLINE - static void CopyVector( - std::vector& vec, - T*& out, - unsigned int& outLength) - { + template + AI_FORCE_INLINE static void CopyVector( + std::vector &vec, + T *&out, + unsigned int &outLength) { outLength = unsigned(vec.size()); if (outLength) { out = new T[outLength]; @@ -410,11 +395,9 @@ protected: /// Error description in case there was one. std::string m_ErrorText; /// Currently set progress handler. - ProgressHandler* m_progress; + ProgressHandler *m_progress; }; - - } // end of namespace Assimp #endif // AI_BASEIMPORTER_H_INC diff --git a/include/assimp/BlobIOSystem.h b/include/assimp/BlobIOSystem.h index 30d9b1ac3..2bcc2074b 100644 --- a/include/assimp/BlobIOSystem.h +++ b/include/assimp/BlobIOSystem.h @@ -47,87 +47,74 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef AI_BLOBIOSYSTEM_H_INCLUDED #define AI_BLOBIOSYSTEM_H_INCLUDED -#include #include -#include -#include #include +#include +#include +#include #include #include -namespace Assimp { - class BlobIOSystem; +namespace Assimp { +class BlobIOSystem; // -------------------------------------------------------------------------------------------- /** Redirect IOStream to a blob */ // -------------------------------------------------------------------------------------------- -class BlobIOStream : public IOStream -{ +class BlobIOStream : public IOStream { public: - - BlobIOStream(BlobIOSystem* creator, const std::string& file, size_t initial = 4096) - : buffer() - , cur_size() - , file_size() - , cursor() - , initial(initial) - , file(file) - , creator(creator) - { + BlobIOStream(BlobIOSystem *creator, const std::string &file, size_t initial = 4096) : + buffer(), + cur_size(), + file_size(), + cursor(), + initial(initial), + file(file), + creator(creator) { + // empty } - virtual ~BlobIOStream(); public: - // ------------------------------------------------------------------- - aiExportDataBlob* GetBlob() - { - aiExportDataBlob* blob = new aiExportDataBlob(); + aiExportDataBlob *GetBlob() { + aiExportDataBlob *blob = new aiExportDataBlob(); blob->size = file_size; blob->data = buffer; - buffer = NULL; + buffer = nullptr; return blob; } - -public: - - // ------------------------------------------------------------------- - virtual size_t Read( void *, - size_t, - size_t ) - { + virtual size_t Read(void *, + size_t, + size_t) { return 0; } // ------------------------------------------------------------------- - virtual size_t Write(const void* pvBuffer, - size_t pSize, - size_t pCount) - { + virtual size_t Write(const void *pvBuffer, + size_t pSize, + size_t pCount) { pSize *= pCount; if (cursor + pSize > cur_size) { Grow(cursor + pSize); } - memcpy(buffer+cursor, pvBuffer, pSize); + memcpy(buffer + cursor, pvBuffer, pSize); cursor += pSize; - file_size = std::max(file_size,cursor); + file_size = std::max(file_size, cursor); return pCount; } // ------------------------------------------------------------------- virtual aiReturn Seek(size_t pOffset, - aiOrigin pOrigin) - { - switch(pOrigin) - { + aiOrigin pOrigin) { + switch (pOrigin) { case aiOrigin_CUR: cursor += pOffset; break; @@ -148,48 +135,41 @@ public: Grow(cursor); } - file_size = std::max(cursor,file_size); + file_size = std::max(cursor, file_size); return AI_SUCCESS; } // ------------------------------------------------------------------- - virtual size_t Tell() const - { + virtual size_t Tell() const { return cursor; } // ------------------------------------------------------------------- - virtual size_t FileSize() const - { + virtual size_t FileSize() const { return file_size; } // ------------------------------------------------------------------- - virtual void Flush() - { + virtual void Flush() { // ignore } - - private: - // ------------------------------------------------------------------- - void Grow(size_t need = 0) - { + void Grow(size_t need = 0) { // 1.5 and phi are very heap-friendly growth factors (the first // allows for frequent re-use of heap blocks, the second // forms a fibonacci sequence with similar characteristics - // since this heavily depends on the heap implementation // and other factors as well, i'll just go with 1.5 since // it is quicker to compute). - size_t new_size = std::max(initial, std::max( need, cur_size+(cur_size>>1) )); + size_t new_size = std::max(initial, std::max(need, cur_size + (cur_size >> 1))); - const uint8_t* const old = buffer; + const uint8_t *const old = buffer; buffer = new uint8_t[new_size]; if (old) { - memcpy(buffer,old,cur_size); + memcpy(buffer, old, cur_size); delete[] old; } @@ -197,54 +177,44 @@ private: } private: - - uint8_t* buffer; - size_t cur_size,file_size, cursor, initial; + uint8_t *buffer; + size_t cur_size, file_size, cursor, initial; const std::string file; - BlobIOSystem* const creator; + BlobIOSystem *const creator; }; - #define AI_BLOBIO_MAGIC "$blobfile" // -------------------------------------------------------------------------------------------- /** Redirect IOSystem to a blob */ // -------------------------------------------------------------------------------------------- -class BlobIOSystem : public IOSystem -{ +class BlobIOSystem : public IOSystem { friend class BlobIOStream; - typedef std::pair BlobEntry; + typedef std::pair BlobEntry; public: - - BlobIOSystem() - { + BlobIOSystem() { } - virtual ~BlobIOSystem() - { - for(BlobEntry& blobby : blobs) { + virtual ~BlobIOSystem() { + for (BlobEntry &blobby : blobs) { delete blobby.second; } } public: - // ------------------------------------------------------------------- - const char* GetMagicFileName() const - { + const char *GetMagicFileName() const { return AI_BLOBIO_MAGIC; } - // ------------------------------------------------------------------- - aiExportDataBlob* GetBlobChain() - { + aiExportDataBlob *GetBlobChain() { // one must be the master - aiExportDataBlob* master = NULL, *cur; - for(const BlobEntry& blobby : blobs) { + aiExportDataBlob *master = nullptr, *cur; + for (const BlobEntry &blobby : blobs) { if (blobby.first == AI_BLOBIO_MAGIC) { master = blobby.second; break; @@ -252,13 +222,13 @@ public: } if (!master) { ASSIMP_LOG_ERROR("BlobIOSystem: no data written or master file was not closed properly."); - return NULL; + return nullptr; } master->name.Set(""); cur = master; - for(const BlobEntry& blobby : blobs) { + for (const BlobEntry &blobby : blobs) { if (blobby.second == master) { continue; } @@ -268,7 +238,7 @@ public: // extract the file extension from the file written const std::string::size_type s = blobby.first.find_first_of('.'); - cur->name.Set(s == std::string::npos ? blobby.first : blobby.first.substr(s+1)); + cur->name.Set(s == std::string::npos ? blobby.first : blobby.first.substr(s + 1)); } // give up blob ownership @@ -277,62 +247,52 @@ public: } public: - // ------------------------------------------------------------------- - virtual bool Exists( const char* pFile) const { + virtual bool Exists(const char *pFile) const { return created.find(std::string(pFile)) != created.end(); } - // ------------------------------------------------------------------- virtual char getOsSeparator() const { return '/'; } - // ------------------------------------------------------------------- - virtual IOStream* Open(const char* pFile, - const char* pMode) - { + virtual IOStream *Open(const char *pFile, + const char *pMode) { if (pMode[0] != 'w') { - return NULL; + return nullptr; } created.insert(std::string(pFile)); - return new BlobIOStream(this,std::string(pFile)); + return new BlobIOStream(this, std::string(pFile)); } // ------------------------------------------------------------------- - virtual void Close( IOStream* pFile) - { + virtual void Close(IOStream *pFile) { delete pFile; } private: - // ------------------------------------------------------------------- - void OnDestruct(const std::string& filename, BlobIOStream* child) - { + void OnDestruct(const std::string &filename, BlobIOStream *child) { // we don't know in which the files are closed, so we // can't reliably say that the first must be the master // file ... - blobs.push_back( BlobEntry(filename,child->GetBlob()) ); + blobs.push_back(BlobEntry(filename, child->GetBlob())); } private: std::set created; - std::vector< BlobEntry > blobs; + std::vector blobs; }; - // -------------------------------------------------------------------------------------------- -BlobIOStream :: ~BlobIOStream() -{ - creator->OnDestruct(file,this); +BlobIOStream ::~BlobIOStream() { + creator->OnDestruct(file, this); delete[] buffer; } - -} // end Assimp +} // namespace Assimp #endif diff --git a/include/assimp/DefaultLogger.hpp b/include/assimp/DefaultLogger.hpp index c405a7409..fac40c7bf 100644 --- a/include/assimp/DefaultLogger.hpp +++ b/include/assimp/DefaultLogger.hpp @@ -45,12 +45,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef INCLUDED_AI_DEFAULTLOGGER #define INCLUDED_AI_DEFAULTLOGGER -#include "Logger.hpp" #include "LogStream.hpp" +#include "Logger.hpp" #include "NullLogger.hpp" #include -namespace Assimp { +namespace Assimp { // ------------------------------------------------------------------------------------ class IOStream; struct LogStreamInfo; @@ -71,11 +71,9 @@ struct LogStreamInfo; * If you wish to customize the logging at an even deeper level supply your own * implementation of #Logger to #set(). * @note The whole logging stuff causes a small extra overhead for all imports. */ -class ASSIMP_API DefaultLogger : - public Logger { +class ASSIMP_API DefaultLogger : public Logger { public: - // ---------------------------------------------------------------------- /** @brief Creates a logging instance. * @param name Name for log file. Only valid in combination @@ -86,12 +84,12 @@ public: * If #aiDefaultLogStream_FILE is specified but an empty string is * passed for 'name', no log file is created at all. * @param io IOSystem to be used to open external files (such as the - * log file). Pass NULL to rely on the default implementation. + * log file). Pass nullptr to rely on the default implementation. * This replaces the default #NullLogger with a #DefaultLogger instance. */ - static Logger *create(const char* name = ASSIMP_DEFAULT_LOG_NAME, - LogSeverity severity = NORMAL, - unsigned int defStreams = aiDefaultLogStream_DEBUGGER | aiDefaultLogStream_FILE, - IOSystem* io = NULL); + static Logger *create(const char *name = ASSIMP_DEFAULT_LOG_NAME, + LogSeverity severity = NORMAL, + unsigned int defStreams = aiDefaultLogStream_DEBUGGER | aiDefaultLogStream_FILE, + IOSystem *io = nullptr); // ---------------------------------------------------------------------- /** @brief Setup a custom #Logger implementation. @@ -101,7 +99,7 @@ public: * it's much easier to use #create() and to attach your own custom * output streams to it. * @param logger Pass NULL to setup a default NullLogger*/ - static void set (Logger *logger); + static void set(Logger *logger); // ---------------------------------------------------------------------- /** @brief Getter for singleton instance @@ -124,12 +122,12 @@ public: // ---------------------------------------------------------------------- /** @copydoc Logger::attachStream */ bool attachStream(LogStream *pStream, - unsigned int severity); + unsigned int severity); // ---------------------------------------------------------------------- /** @copydoc Logger::detachStream */ bool detachStream(LogStream *pStream, - unsigned int severity); + unsigned int severity); private: // ---------------------------------------------------------------------- @@ -142,23 +140,23 @@ private: ~DefaultLogger(); /** @brief Logs debug infos, only been written when severity level DEBUG or higher is set */ - void OnDebug(const char* message); + void OnDebug(const char *message); /** @brief Logs debug infos, only been written when severity level VERBOSE is set */ - void OnVerboseDebug(const char *message); + void OnVerboseDebug(const char *message); /** @brief Logs an info message */ - void OnInfo(const char* message); + void OnInfo(const char *message); /** @brief Logs a warning message */ - void OnWarn(const char* message); + void OnWarn(const char *message); /** @brief Logs an error message */ - void OnError(const char* message); + void OnError(const char *message); // ---------------------------------------------------------------------- /** @brief Writes a message to all streams */ - void WriteToStreams(const char* message, ErrorSeverity ErrorSev ); + void WriteToStreams(const char *message, ErrorSeverity ErrorSev); // ---------------------------------------------------------------------- /** @brief Returns the thread id. @@ -169,9 +167,9 @@ private: private: // Aliases for stream container - typedef std::vector StreamArray; - typedef std::vector::iterator StreamIt; - typedef std::vector::const_iterator ConstStreamIt; + typedef std::vector StreamArray; + typedef std::vector::iterator StreamIt; + typedef std::vector::const_iterator ConstStreamIt; //! only logging instance static Logger *m_pLogger; @@ -181,7 +179,7 @@ private: StreamArray m_StreamArray; bool noRepeatMsg; - char lastMsg[MAX_LOG_MESSAGE_LENGTH*2]; + char lastMsg[MAX_LOG_MESSAGE_LENGTH * 2]; size_t lastLen; }; // ------------------------------------------------------------------------------------ diff --git a/include/assimp/Exceptional.h b/include/assimp/Exceptional.h index 8970ade7c..c10b2f982 100644 --- a/include/assimp/Exceptional.h +++ b/include/assimp/Exceptional.h @@ -43,27 +43,27 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define AI_INCLUDED_EXCEPTIONAL_H #ifdef __GNUC__ -# pragma GCC system_header +#pragma GCC system_header #endif -#include #include +#include using std::runtime_error; #ifdef _MSC_VER -# pragma warning(disable : 4275) +#pragma warning(disable : 4275) #endif // --------------------------------------------------------------------------- /** FOR IMPORTER PLUGINS ONLY: Simple exception class to be thrown if an * unrecoverable error occurs while importing. Loading APIs return - * NULL instead of a valid aiScene then. */ + * nullptr instead of a valid aiScene then. */ class DeadlyImportError : public runtime_error { public: /** Constructor with arguments */ - explicit DeadlyImportError( const std::string& errorText) - : runtime_error(errorText) { + explicit DeadlyImportError(const std::string &errorText) : + runtime_error(errorText) { // empty } }; @@ -78,21 +78,21 @@ public: }; #ifdef _MSC_VER -# pragma warning(default : 4275) +#pragma warning(default : 4275) #endif // --------------------------------------------------------------------------- template -struct ExceptionSwallower { - T operator ()() const { +struct ExceptionSwallower { + T operator()() const { return T(); } }; // --------------------------------------------------------------------------- template -struct ExceptionSwallower { - T* operator ()() const { +struct ExceptionSwallower { + T *operator()() const { return nullptr; } }; @@ -100,14 +100,12 @@ struct ExceptionSwallower { // --------------------------------------------------------------------------- template <> struct ExceptionSwallower { - aiReturn operator ()() const { + aiReturn operator()() const { try { throw; - } - catch (std::bad_alloc&) { + } catch (std::bad_alloc &) { return aiReturn_OUTOFMEMORY; - } - catch (...) { + } catch (...) { return aiReturn_FAILURE; } } @@ -116,29 +114,32 @@ struct ExceptionSwallower { // --------------------------------------------------------------------------- template <> struct ExceptionSwallower { - void operator ()() const { + void operator()() const { return; } }; -#define ASSIMP_BEGIN_EXCEPTION_REGION()\ -{\ - try { +#define ASSIMP_BEGIN_EXCEPTION_REGION() \ + { \ + try { -#define ASSIMP_END_EXCEPTION_REGION_WITH_ERROR_STRING(type, ASSIMP_END_EXCEPTION_REGION_errorString)\ - } catch(const DeadlyImportError& e) {\ - ASSIMP_END_EXCEPTION_REGION_errorString = e.what();\ - return ExceptionSwallower()();\ - } catch(...) {\ - ASSIMP_END_EXCEPTION_REGION_errorString = "Unknown exception";\ - return ExceptionSwallower()();\ - }\ -} +#define ASSIMP_END_EXCEPTION_REGION_WITH_ERROR_STRING(type, ASSIMP_END_EXCEPTION_REGION_errorString) \ + } \ + catch (const DeadlyImportError &e) { \ + ASSIMP_END_EXCEPTION_REGION_errorString = e.what(); \ + return ExceptionSwallower()(); \ + } \ + catch (...) { \ + ASSIMP_END_EXCEPTION_REGION_errorString = "Unknown exception"; \ + return ExceptionSwallower()(); \ + } \ + } -#define ASSIMP_END_EXCEPTION_REGION(type)\ - } catch(...) {\ - return ExceptionSwallower()();\ - }\ -} +#define ASSIMP_END_EXCEPTION_REGION(type) \ + } \ + catch (...) { \ + return ExceptionSwallower()(); \ + } \ + } #endif // AI_INCLUDED_EXCEPTIONAL_H diff --git a/include/assimp/Exporter.hpp b/include/assimp/Exporter.hpp index dc6661c11..ed910d4d7 100644 --- a/include/assimp/Exporter.hpp +++ b/include/assimp/Exporter.hpp @@ -47,7 +47,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define AI_EXPORT_HPP_INC #ifdef __GNUC__ -# pragma GCC system_header +#pragma GCC system_header #endif #ifndef ASSIMP_BUILD_NO_EXPORT @@ -56,7 +56,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include namespace Assimp { - + class ExporterPimpl; class IOSystem; class ProgressHandler; @@ -84,7 +84,7 @@ class ASSIMP_API ExportProperties; class ASSIMP_API Exporter { public: /** Function pointer type of a Export worker function */ - typedef void (*fpExportFunc)(const char*, IOSystem*, const aiScene*, const ExportProperties*); + typedef void (*fpExportFunc)(const char *, IOSystem *, const aiScene *, const ExportProperties *); /** Internal description of an Assimp export format option */ struct ExportFormatEntry { @@ -98,8 +98,7 @@ public: unsigned int mEnforcePP; // Constructor to fill all entries - ExportFormatEntry( const char* pId, const char* pDesc, const char* pExtension, fpExportFunc pFunction, unsigned int pEnforcePP = 0u) - { + ExportFormatEntry(const char *pId, const char *pDesc, const char *pExtension, fpExportFunc pFunction, unsigned int pEnforcePP = 0u) { mDescription.id = pId; mDescription.description = pDesc; mDescription.fileExtension = pExtension; @@ -108,12 +107,10 @@ public: } ExportFormatEntry() : - mExportFunction() - , mEnforcePP() - { - mDescription.id = NULL; - mDescription.description = NULL; - mDescription.fileExtension = NULL; + mExportFunction(), mEnforcePP() { + mDescription.id = nullptr; + mDescription.description = nullptr; + mDescription.fileExtension = nullptr; } }; @@ -142,7 +139,7 @@ public: * * @param pIOHandler The IO handler to be used in all file accesses * of the Importer. */ - void SetIOHandler( IOSystem* pIOHandler); + void SetIOHandler(IOSystem *pIOHandler); // ------------------------------------------------------------------- /** Retrieves the IO handler that is currently set. @@ -150,8 +147,8 @@ public: * interface is the default IO handler provided by ASSIMP. The default * handler is active as long the application doesn't supply its own * custom IO handler via #SetIOHandler(). - * @return A valid IOSystem interface, never NULL. */ - IOSystem* GetIOHandler() const; + * @return A valid IOSystem interface, never nullptr. */ + IOSystem *GetIOHandler() const; // ------------------------------------------------------------------- /** Checks whether a default IO handler is active @@ -171,7 +168,7 @@ public: * disable progress reporting. * @note Progress handlers can be used to abort the loading * at almost any time.*/ - void SetProgressHandler(ProgressHandler* pHandler); + void SetProgressHandler(ProgressHandler *pHandler); // ------------------------------------------------------------------- /** Exports the given scene to a chosen file format. Returns the exported @@ -185,22 +182,22 @@ public: * #GetExportFormatCount / #GetExportFormatDescription to learn which * export formats are available. * @param pPreprocessing See the documentation for #Export - * @return the exported data or NULL in case of error. + * @return the exported data or nullptr in case of error. * @note If the Exporter instance did already hold a blob from * a previous call to #ExportToBlob, it will be disposed. * Any IO handlers set via #SetIOHandler are ignored here. * @note Use aiCopyScene() to get a modifiable copy of a previously * imported scene. */ - const aiExportDataBlob* ExportToBlob(const aiScene* pScene, const char* pFormatId, - unsigned int pPreprocessing = 0u, const ExportProperties* pProperties = nullptr); - const aiExportDataBlob* ExportToBlob( const aiScene* pScene, const std::string& pFormatId, - unsigned int pPreprocessing = 0u, const ExportProperties* pProperties = nullptr); + const aiExportDataBlob *ExportToBlob(const aiScene *pScene, const char *pFormatId, + unsigned int pPreprocessing = 0u, const ExportProperties *pProperties = nullptr); + const aiExportDataBlob *ExportToBlob(const aiScene *pScene, const std::string &pFormatId, + unsigned int pPreprocessing = 0u, const ExportProperties *pProperties = nullptr); // ------------------------------------------------------------------- /** Convenience function to export directly to a file. Use * #SetIOSystem to supply a custom IOSystem to gain fine-grained control * about the output data flow of the export process. - * @param pBlob A data blob obtained from a previous call to #aiExportScene. Must not be NULL. + * @param pBlob A data blob obtained from a previous call to #aiExportScene. Must not be nullptr. * @param pPath Full target file name. Target must be accessible. * @param pPreprocessing Accepts any choice of the #aiPostProcessSteps enumerated * flags, but in reality only a subset of them makes sense here. Specifying @@ -229,10 +226,10 @@ public: * @return AI_SUCCESS if everything was fine. * @note Use aiCopyScene() to get a modifiable copy of a previously * imported scene.*/ - aiReturn Export( const aiScene* pScene, const char* pFormatId, const char* pPath, - unsigned int pPreprocessing = 0u, const ExportProperties* pProperties = nullptr); - aiReturn Export( const aiScene* pScene, const std::string& pFormatId, const std::string& pPath, - unsigned int pPreprocessing = 0u, const ExportProperties* pProperties = nullptr); + aiReturn Export(const aiScene *pScene, const char *pFormatId, const char *pPath, + unsigned int pPreprocessing = 0u, const ExportProperties *pProperties = nullptr); + aiReturn Export(const aiScene *pScene, const std::string &pFormatId, const std::string &pPath, + unsigned int pPreprocessing = 0u, const ExportProperties *pProperties = nullptr); // ------------------------------------------------------------------- /** Returns an error description of an error that occurred in #Export @@ -240,21 +237,21 @@ public: * * Returns an empty string if no error occurred. * @return A description of the last error, an empty string if no - * error occurred. The string is never NULL. + * error occurred. The string is never nullptr. * * @note The returned function remains valid until one of the * following methods is called: #Export, #ExportToBlob, #FreeBlob */ - const char* GetErrorString() const; + const char *GetErrorString() const; // ------------------------------------------------------------------- /** Return the blob obtained from the last call to #ExportToBlob */ - const aiExportDataBlob* GetBlob() const; + const aiExportDataBlob *GetBlob() const; // ------------------------------------------------------------------- /** Orphan the blob from the last call to #ExportToBlob. This means * the caller takes ownership and is thus responsible for calling * the C API function #aiReleaseExportBlob to release it. */ - const aiExportDataBlob* GetOrphanedBlob() const; + const aiExportDataBlob *GetOrphanedBlob() const; // ------------------------------------------------------------------- /** Frees the current blob. @@ -264,7 +261,7 @@ public: * automatically by the destructor. The only reason to call * it manually would be to reclaim as much storage as possible * without giving up the #Exporter instance yet. */ - void FreeBlob( ); + void FreeBlob(); // ------------------------------------------------------------------- /** Returns the number of export file formats available in the current @@ -289,8 +286,8 @@ public: * @param pIndex Index of the export format to retrieve information * for. Valid range is 0 to #Exporter::GetExportFormatCount * @return A description of that specific export format. - * NULL if pIndex is out of range. */ - const aiExportFormatDesc* GetExportFormatDescription( size_t pIndex ) const; + * nullptr if pIndex is out of range. */ + const aiExportFormatDesc *GetExportFormatDescription(size_t pIndex) const; // ------------------------------------------------------------------- /** Register a custom exporter. Custom export formats are limited to @@ -303,7 +300,7 @@ public: * registered. A common cause that would prevent an exporter * from being registered is that its format id is already * occupied by another format. */ - aiReturn RegisterExporter(const ExportFormatEntry& desc); + aiReturn RegisterExporter(const ExportFormatEntry &desc); // ------------------------------------------------------------------- /** Remove an export format previously registered with #RegisterExporter @@ -314,11 +311,11 @@ public: * 'id' field of #aiExportFormatDesc. * @note Calling this method on a format description not yet registered * has no effect.*/ - void UnregisterExporter(const char* id); + void UnregisterExporter(const char *id); protected: // Just because we don't want you to know how we're hacking around. - ExporterPimpl* pimpl; + ExporterPimpl *pimpl; }; class ASSIMP_API ExportProperties { @@ -345,7 +342,7 @@ public: * This copies the configuration properties of another ExportProperties. * @see ExportProperties(const ExportProperties& other) */ - ExportProperties(const ExportProperties& other); + ExportProperties(const ExportProperties &other); // ------------------------------------------------------------------- /** Set an integer configuration property. @@ -360,7 +357,7 @@ public: * floating-point property has no effect - the loader will call * GetPropertyFloat() to read the property, but it won't be there. */ - bool SetPropertyInteger(const char* szName, int iValue); + bool SetPropertyInteger(const char *szName, int iValue); // ------------------------------------------------------------------- /** Set a boolean configuration property. Boolean properties @@ -369,27 +366,27 @@ public: * #GetPropertyBool and vice versa. * @see SetPropertyInteger() */ - bool SetPropertyBool(const char* szName, bool value) { - return SetPropertyInteger(szName,value); + bool SetPropertyBool(const char *szName, bool value) { + return SetPropertyInteger(szName, value); } // ------------------------------------------------------------------- /** Set a floating-point configuration property. * @see SetPropertyInteger() */ - bool SetPropertyFloat(const char* szName, ai_real fValue); + bool SetPropertyFloat(const char *szName, ai_real fValue); // ------------------------------------------------------------------- /** Set a string configuration property. * @see SetPropertyInteger() */ - bool SetPropertyString(const char* szName, const std::string& sValue); + bool SetPropertyString(const char *szName, const std::string &sValue); // ------------------------------------------------------------------- /** Set a matrix configuration property. * @see SetPropertyInteger() */ - bool SetPropertyMatrix(const char* szName, const aiMatrix4x4& sValue); + bool SetPropertyMatrix(const char *szName, const aiMatrix4x4 &sValue); // ------------------------------------------------------------------- /** Get a configuration property. @@ -404,8 +401,8 @@ public: * floating-point property has no effect - the loader will call * GetPropertyFloat() to read the property, but it won't be there. */ - int GetPropertyInteger(const char* szName, - int iErrorReturn = 0xffffffff) const; + int GetPropertyInteger(const char *szName, + int iErrorReturn = 0xffffffff) const; // ------------------------------------------------------------------- /** Get a boolean configuration property. Boolean properties @@ -414,16 +411,16 @@ public: * #GetPropertyBool and vice versa. * @see GetPropertyInteger() */ - bool GetPropertyBool(const char* szName, bool bErrorReturn = false) const { - return GetPropertyInteger(szName,bErrorReturn)!=0; + bool GetPropertyBool(const char *szName, bool bErrorReturn = false) const { + return GetPropertyInteger(szName, bErrorReturn) != 0; } // ------------------------------------------------------------------- /** Get a floating-point configuration property * @see GetPropertyInteger() */ - ai_real GetPropertyFloat(const char* szName, - ai_real fErrorReturn = 10e10f) const; + ai_real GetPropertyFloat(const char *szName, + ai_real fErrorReturn = 10e10f) const; // ------------------------------------------------------------------- /** Get a string configuration property @@ -431,8 +428,8 @@ public: * The return value remains valid until the property is modified. * @see GetPropertyInteger() */ - const std::string GetPropertyString(const char* szName, - const std::string& sErrorReturn = "") const; + const std::string GetPropertyString(const char *szName, + const std::string &sErrorReturn = "") const; // ------------------------------------------------------------------- /** Get a matrix configuration property @@ -440,37 +437,36 @@ public: * The return value remains valid until the property is modified. * @see GetPropertyInteger() */ - const aiMatrix4x4 GetPropertyMatrix(const char* szName, - const aiMatrix4x4& sErrorReturn = aiMatrix4x4()) const; + const aiMatrix4x4 GetPropertyMatrix(const char *szName, + const aiMatrix4x4 &sErrorReturn = aiMatrix4x4()) const; // ------------------------------------------------------------------- /** Determine a integer configuration property has been set. * @see HasPropertyInteger() */ - bool HasPropertyInteger(const char* szName) const; + bool HasPropertyInteger(const char *szName) const; /** Determine a boolean configuration property has been set. * @see HasPropertyBool() */ - bool HasPropertyBool(const char* szName) const; + bool HasPropertyBool(const char *szName) const; /** Determine a boolean configuration property has been set. * @see HasPropertyFloat() */ - bool HasPropertyFloat(const char* szName) const; + bool HasPropertyFloat(const char *szName) const; /** Determine a String configuration property has been set. * @see HasPropertyString() */ - bool HasPropertyString(const char* szName) const; + bool HasPropertyString(const char *szName) const; /** Determine a Matrix configuration property has been set. * @see HasPropertyMatrix() */ - bool HasPropertyMatrix(const char* szName) const; + bool HasPropertyMatrix(const char *szName) const; protected: - /** List of integer properties */ IntPropertyMap mIntProperties; @@ -485,20 +481,16 @@ protected: }; // ---------------------------------------------------------------------------------- -inline -const aiExportDataBlob* Exporter::ExportToBlob( const aiScene* pScene, const std::string& pFormatId, - unsigned int pPreprocessing, const ExportProperties* pProperties) -{ - return ExportToBlob(pScene,pFormatId.c_str(),pPreprocessing, pProperties); +inline const aiExportDataBlob *Exporter::ExportToBlob(const aiScene *pScene, const std::string &pFormatId, + unsigned int pPreprocessing, const ExportProperties *pProperties) { + return ExportToBlob(pScene, pFormatId.c_str(), pPreprocessing, pProperties); } // ---------------------------------------------------------------------------------- -inline -aiReturn Exporter :: Export( const aiScene* pScene, const std::string& pFormatId, - const std::string& pPath, unsigned int pPreprocessing, - const ExportProperties* pProperties) -{ - return Export(pScene,pFormatId.c_str(),pPath.c_str(),pPreprocessing, pProperties); +inline aiReturn Exporter ::Export(const aiScene *pScene, const std::string &pFormatId, + const std::string &pPath, unsigned int pPreprocessing, + const ExportProperties *pProperties) { + return Export(pScene, pFormatId.c_str(), pPath.c_str(), pPreprocessing, pProperties); } } // namespace Assimp diff --git a/include/assimp/GenericProperty.h b/include/assimp/GenericProperty.h index c1891c7b6..e12a443b0 100644 --- a/include/assimp/GenericProperty.h +++ b/include/assimp/GenericProperty.h @@ -87,7 +87,7 @@ inline const T &GetGenericProperty(const std::map &list, // ------------------------------------------------------------------------------------------------ // Special version for pointer types - they will be deleted when replaced with another value -// passing NULL removes the whole property +// passing nullptr removes the whole property template inline void SetGenericPropertyPtr(std::map &list, const char *szName, T *value, bool *bWasExisting = nullptr) { diff --git a/include/assimp/Importer.hpp b/include/assimp/Importer.hpp index ca3964c7d..80eae78b3 100644 --- a/include/assimp/Importer.hpp +++ b/include/assimp/Importer.hpp @@ -49,39 +49,39 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define AI_ASSIMP_HPP_INC #ifdef __GNUC__ -# pragma GCC system_header +#pragma GCC system_header #endif #ifndef __cplusplus -# error This header requires C++ to be used. Use assimp.h for plain C. +#error This header requires C++ to be used. Use assimp.h for plain C. #endif // __cplusplus // Public ASSIMP data structures #include namespace Assimp { - // ======================================================================= - // Public interface to Assimp - class Importer; - class IOStream; - class IOSystem; - class ProgressHandler; +// ======================================================================= +// Public interface to Assimp +class Importer; +class IOStream; +class IOSystem; +class ProgressHandler; - // ======================================================================= - // Plugin development - // - // Include the following headers for the declarations: - // BaseImporter.h - // BaseProcess.h - class BaseImporter; - class BaseProcess; - class SharedPostProcessInfo; - class BatchLoader; +// ======================================================================= +// Plugin development +// +// Include the following headers for the declarations: +// BaseImporter.h +// BaseProcess.h +class BaseImporter; +class BaseProcess; +class SharedPostProcessInfo; +class BatchLoader; - // ======================================================================= - // Holy stuff, only for members of the high council of the Jedi. - class ImporterPimpl; -} //! namespace Assimp +// ======================================================================= +// Holy stuff, only for members of the high council of the Jedi. +class ImporterPimpl; +} // namespace Assimp #define AI_PROPERTY_WAS_NOT_EXISTING 0xffffffff @@ -91,7 +91,7 @@ struct aiScene; struct aiImporterDesc; /** @namespace Assimp Assimp's CPP-API and all internal APIs */ -namespace Assimp { +namespace Assimp { // ---------------------------------------------------------------------------------- /** CPP-API: The Importer class forms an C++ interface to the functionality of the @@ -101,7 +101,7 @@ namespace Assimp { * If the import succeeds, the function returns a pointer to the imported data. * The data remains property of the object, it is intended to be accessed * read-only. The imported data will be destroyed along with the Importer -* object. If the import fails, ReadFile() returns a NULL pointer. In this +* object. If the import fails, ReadFile() returns a nullptr pointer. In this * case you can retrieve a human-readable error description be calling * GetErrorString(). You can call ReadFile() multiple times with a single Importer * instance. Actually, constructing Importer objects involves quite many @@ -117,7 +117,7 @@ namespace Assimp { * @note One Importer instance is not thread-safe. If you use multiple * threads for loading, each thread should maintain its own Importer instance. */ -class ASSIMP_API Importer { +class ASSIMP_API Importer { public: /** * @brief The upper limit for hints. @@ -125,7 +125,6 @@ public: static const unsigned int MaxLenHint = 200; public: - // ------------------------------------------------------------------- /** Constructor. Creates an empty importer object. * @@ -141,7 +140,7 @@ public: * If this Importer owns a scene it won't be copied. * Call ReadFile() to start the import process. */ - Importer(const Importer& other)=delete; + Importer(const Importer &other) = delete; // ------------------------------------------------------------------- /** Assignment operator has been deleted @@ -154,7 +153,6 @@ public: */ ~Importer(); - // ------------------------------------------------------------------- /** Registers a new loader. * @@ -164,7 +162,7 @@ public: * @return AI_SUCCESS if the loader has been added. The registration * fails if there is already a loader for a specific file extension. */ - aiReturn RegisterLoader(BaseImporter* pImp); + aiReturn RegisterLoader(BaseImporter *pImp); // ------------------------------------------------------------------- /** Unregisters a loader. @@ -175,7 +173,7 @@ public: * if the #Importer instance is used by more than one thread) or * if it has not yet been registered. */ - aiReturn UnregisterLoader(BaseImporter* pImp); + aiReturn UnregisterLoader(BaseImporter *pImp); // ------------------------------------------------------------------- /** Registers a new post-process step. @@ -188,7 +186,7 @@ public: * deleted with the Importer instance. * @return AI_SUCCESS if the step has been added correctly. */ - aiReturn RegisterPPStep(BaseProcess* pImp); + aiReturn RegisterPPStep(BaseProcess *pImp); // ------------------------------------------------------------------- /** Unregisters a post-process step. @@ -199,7 +197,7 @@ public: * if the #Importer instance is used by more than one thread) or * if it has not yet been registered. */ - aiReturn UnregisterPPStep(BaseProcess* pImp); + aiReturn UnregisterPPStep(BaseProcess *pImp); // ------------------------------------------------------------------- /** Set an integer configuration property. @@ -214,7 +212,7 @@ public: * floating-point property has no effect - the loader will call * GetPropertyFloat() to read the property, but it won't be there. */ - bool SetPropertyInteger(const char* szName, int iValue); + bool SetPropertyInteger(const char *szName, int iValue); // ------------------------------------------------------------------- /** Set a boolean configuration property. Boolean properties @@ -223,27 +221,27 @@ public: * #GetPropertyBool and vice versa. * @see SetPropertyInteger() */ - bool SetPropertyBool(const char* szName, bool value) { - return SetPropertyInteger(szName,value); + bool SetPropertyBool(const char *szName, bool value) { + return SetPropertyInteger(szName, value); } // ------------------------------------------------------------------- /** Set a floating-point configuration property. * @see SetPropertyInteger() */ - bool SetPropertyFloat(const char* szName, ai_real fValue); + bool SetPropertyFloat(const char *szName, ai_real fValue); // ------------------------------------------------------------------- /** Set a string configuration property. * @see SetPropertyInteger() */ - bool SetPropertyString(const char* szName, const std::string& sValue); + bool SetPropertyString(const char *szName, const std::string &sValue); // ------------------------------------------------------------------- /** Set a matrix configuration property. * @see SetPropertyInteger() */ - bool SetPropertyMatrix(const char* szName, const aiMatrix4x4& sValue); + bool SetPropertyMatrix(const char *szName, const aiMatrix4x4 &sValue); // ------------------------------------------------------------------- /** Get a configuration property. @@ -258,8 +256,8 @@ public: * floating-point property has no effect - the loader will call * GetPropertyFloat() to read the property, but it won't be there. */ - int GetPropertyInteger(const char* szName, - int iErrorReturn = 0xffffffff) const; + int GetPropertyInteger(const char *szName, + int iErrorReturn = 0xffffffff) const; // ------------------------------------------------------------------- /** Get a boolean configuration property. Boolean properties @@ -268,16 +266,16 @@ public: * #GetPropertyBool and vice versa. * @see GetPropertyInteger() */ - bool GetPropertyBool(const char* szName, bool bErrorReturn = false) const { - return GetPropertyInteger(szName,bErrorReturn)!=0; + bool GetPropertyBool(const char *szName, bool bErrorReturn = false) const { + return GetPropertyInteger(szName, bErrorReturn) != 0; } // ------------------------------------------------------------------- /** Get a floating-point configuration property * @see GetPropertyInteger() */ - ai_real GetPropertyFloat(const char* szName, - ai_real fErrorReturn = 10e10) const; + ai_real GetPropertyFloat(const char *szName, + ai_real fErrorReturn = 10e10) const; // ------------------------------------------------------------------- /** Get a string configuration property @@ -285,8 +283,8 @@ public: * The return value remains valid until the property is modified. * @see GetPropertyInteger() */ - std::string GetPropertyString(const char* szName, - const std::string& sErrorReturn = "") const; + std::string GetPropertyString(const char *szName, + const std::string &sErrorReturn = "") const; // ------------------------------------------------------------------- /** Get a matrix configuration property @@ -294,8 +292,8 @@ public: * The return value remains valid until the property is modified. * @see GetPropertyInteger() */ - aiMatrix4x4 GetPropertyMatrix(const char* szName, - const aiMatrix4x4& sErrorReturn = aiMatrix4x4()) const; + aiMatrix4x4 GetPropertyMatrix(const char *szName, + const aiMatrix4x4 &sErrorReturn = aiMatrix4x4()) const; // ------------------------------------------------------------------- /** Supplies a custom IO handler to the importer to use to open and @@ -306,13 +304,13 @@ public: * * The Importer takes ownership of the object and will destroy it * afterwards. The previously assigned handler will be deleted. - * Pass NULL to take again ownership of your IOSystem and reset Assimp + * Pass nullptr to take again ownership of your IOSystem and reset Assimp * to use its default implementation. * * @param pIOHandler The IO handler to be used in all file accesses * of the Importer. */ - void SetIOHandler( IOSystem* pIOHandler); + void SetIOHandler(IOSystem *pIOHandler); // ------------------------------------------------------------------- /** Retrieves the IO handler that is currently set. @@ -320,9 +318,9 @@ public: * interface is the default IO handler provided by ASSIMP. The default * handler is active as long the application doesn't supply its own * custom IO handler via #SetIOHandler(). - * @return A valid IOSystem interface, never NULL. + * @return A valid IOSystem interface, never nullptr. */ - IOSystem* GetIOHandler() const; + IOSystem *GetIOHandler() const; // ------------------------------------------------------------------- /** Checks whether a default IO handler is active @@ -339,11 +337,11 @@ public: * isn't as periodically as you'd like it to have ...). * This can be used to implement progress bars and loading * timeouts. - * @param pHandler Progress callback interface. Pass NULL to + * @param pHandler Progress callback interface. Pass nullptr to * disable progress reporting. * @note Progress handlers can be used to abort the loading * at almost any time.*/ - void SetProgressHandler ( ProgressHandler* pHandler ); + void SetProgressHandler(ProgressHandler *pHandler); // ------------------------------------------------------------------- /** Retrieves the progress handler that is currently set. @@ -351,9 +349,9 @@ public: * interface is the default handler provided by ASSIMP. The default * handler is active as long the application doesn't supply its own * custom handler via #SetProgressHandler(). - * @return A valid ProgressHandler interface, never NULL. + * @return A valid ProgressHandler interface, never nullptr. */ - ProgressHandler* GetProgressHandler() const; + ProgressHandler *GetProgressHandler() const; // ------------------------------------------------------------------- /** Checks whether a default progress handler is active @@ -383,7 +381,7 @@ public: * If the call succeeds, the contents of the file are returned as a * pointer to an aiScene object. The returned data is intended to be * read-only, the importer object keeps ownership of the data and will - * destroy it upon destruction. If the import fails, NULL is returned. + * destroy it upon destruction. If the import fails, nullptr is returned. * A human-readable error description can be retrieved by calling * GetErrorString(). The previous scene will be deleted during this call. * @param pFile Path and filename to the file to be imported. @@ -392,16 +390,16 @@ public: * #aiPostProcessSteps flags. If you wish to inspect the imported * scene first in order to fine-tune your post-processing setup, * consider to use #ApplyPostProcessing(). - * @return A pointer to the imported data, NULL if the import failed. + * @return A pointer to the imported data, nullptr if the import failed. * The pointer to the scene remains in possession of the Importer * instance. Use GetOrphanedScene() to take ownership of it. * * @note Assimp is able to determine the file format of a file * automatically. */ - const aiScene* ReadFile( - const char* pFile, - unsigned int pFlags); + const aiScene *ReadFile( + const char *pFile, + unsigned int pFlags); // ------------------------------------------------------------------- /** Reads the given file from a memory buffer and returns its @@ -410,7 +408,7 @@ public: * If the call succeeds, the contents of the file are returned as a * pointer to an aiScene object. The returned data is intended to be * read-only, the importer object keeps ownership of the data and will - * destroy it upon destruction. If the import fails, NULL is returned. + * destroy it upon destruction. If the import fails, nullptr is returned. * A human-readable error description can be retrieved by calling * GetErrorString(). The previous scene will be deleted during this call. * Calling this method doesn't affect the active IOSystem. @@ -428,7 +426,7 @@ public: * the request, the library continues and tries to determine the * file format on its own, a task that may or may not be successful. * Check the return value, and you'll know ... - * @return A pointer to the imported data, NULL if the import failed. + * @return A pointer to the imported data, nullptr if the import failed. * The pointer to the scene remains in possession of the Importer * instance. Use GetOrphanedScene() to take ownership of it. * @@ -440,11 +438,11 @@ public: * a custom IOSystem to make Assimp find these files and use * the regular ReadFile() API. */ - const aiScene* ReadFileFromMemory( - const void* pBuffer, - size_t pLength, - unsigned int pFlags, - const char* pHint = ""); + const aiScene *ReadFileFromMemory( + const void *pBuffer, + size_t pLength, + unsigned int pFlags, + const char *pHint = ""); // ------------------------------------------------------------------- /** Apply post-processing to an already-imported scene. @@ -456,17 +454,17 @@ public: * #aiPostProcessSteps flags. * @return A pointer to the post-processed data. This is still the * same as the pointer returned by #ReadFile(). However, if - * post-processing fails, the scene could now be NULL. + * post-processing fails, the scene could now be nullptr. * That's quite a rare case, post processing steps are not really * designed to 'fail'. To be exact, the #aiProcess_ValidateDS * flag is currently the only post processing step which can actually - * cause the scene to be reset to NULL. + * cause the scene to be reset to nullptr. * * @note The method does nothing if no scene is currently bound * to the #Importer instance. */ - const aiScene* ApplyPostProcessing(unsigned int pFlags); + const aiScene *ApplyPostProcessing(unsigned int pFlags); - const aiScene* ApplyCustomizedPostProcessing( BaseProcess *rootProcess, bool requestValidation ); + const aiScene *ApplyCustomizedPostProcessing(BaseProcess *rootProcess, bool requestValidation); // ------------------------------------------------------------------- /** @brief Reads the given file and returns its contents if successful. @@ -474,9 +472,9 @@ public: * This function is provided for backward compatibility. * See the const char* version for detailed docs. * @see ReadFile(const char*, pFlags) */ - const aiScene* ReadFile( - const std::string& pFile, - unsigned int pFlags); + const aiScene *ReadFile( + const std::string &pFile, + unsigned int pFlags); // ------------------------------------------------------------------- /** Frees the current scene. @@ -484,33 +482,33 @@ public: * The function does nothing if no scene has previously been * read via ReadFile(). FreeScene() is called automatically by the * destructor and ReadFile() itself. */ - void FreeScene( ); + void FreeScene(); // ------------------------------------------------------------------- /** Returns an error description of an error that occurred in ReadFile(). * * Returns an empty string if no error occurred. * @return A description of the last error, an empty string if no - * error occurred. The string is never NULL. + * error occurred. The string is never nullptr. * * @note The returned function remains valid until one of the * following methods is called: #ReadFile(), #FreeScene(). */ - const char* GetErrorString() const; + const char *GetErrorString() const; // ------------------------------------------------------------------- /** Returns the scene loaded by the last successful call to ReadFile() * - * @return Current scene or NULL if there is currently no scene loaded */ - const aiScene* GetScene() const; + * @return Current scene or nullptr if there is currently no scene loaded */ + const aiScene *GetScene() const; // ------------------------------------------------------------------- /** Returns the scene loaded by the last successful call to ReadFile() * and releases the scene from the ownership of the Importer * instance. The application is now responsible for deleting the * scene. Any further calls to GetScene() or GetOrphanedScene() - * will return NULL - until a new scene has been loaded via ReadFile(). + * will return nullptr - until a new scene has been loaded via ReadFile(). * - * @return Current scene or NULL if there is currently no scene loaded + * @return Current scene or nullptr if there is currently no scene loaded * @note Use this method with maximal caution, and only if you have to. * By design, aiScene's are exclusively maintained, allocated and * deallocated by Assimp and no one else. The reasoning behind this @@ -522,7 +520,7 @@ public: * On Windows, it's typically fine provided everything is linked * against the multithreaded-dll version of the runtime library. * It will work as well for static linkage with Assimp.*/ - aiScene* GetOrphanedScene(); + aiScene *GetOrphanedScene(); // ------------------------------------------------------------------- /** Returns whether a given file extension is supported by ASSIMP. @@ -531,7 +529,7 @@ public: * Must include a trailing dot '.'. Example: ".3ds", ".md3". * Cases-insensitive. * @return true if the extension is supported, false otherwise */ - bool IsExtensionSupported(const char* szExtension) const; + bool IsExtensionSupported(const char *szExtension) const; // ------------------------------------------------------------------- /** @brief Returns whether a given file extension is supported by ASSIMP. @@ -539,7 +537,7 @@ public: * This function is provided for backward compatibility. * See the const char* version for detailed and up-to-date docs. * @see IsExtensionSupported(const char*) */ - inline bool IsExtensionSupported(const std::string& szExtension) const; + inline bool IsExtensionSupported(const std::string &szExtension) const; // ------------------------------------------------------------------- /** Get a full list of all file extensions supported by ASSIMP. @@ -551,7 +549,7 @@ public: * @param szOut String to receive the extension list. * Format of the list: "*.3ds;*.obj;*.dae". This is useful for * use with the WinAPI call GetOpenFileName(Ex). */ - void GetExtensionList(aiString& szOut) const; + void GetExtensionList(aiString &szOut) const; // ------------------------------------------------------------------- /** @brief Get a full list of all file extensions supported by ASSIMP. @@ -559,7 +557,7 @@ public: * This function is provided for backward compatibility. * See the aiString version for detailed and up-to-date docs. * @see GetExtensionList(aiString&)*/ - inline void GetExtensionList(std::string& szOut) const; + inline void GetExtensionList(std::string &szOut) const; // ------------------------------------------------------------------- /** Get the number of importers currently registered with Assimp. */ @@ -570,18 +568,18 @@ public: * * For the declaration of #aiImporterDesc, include . * @param index Index to query, must be within [0,GetImporterCount()) - * @return Importer meta data structure, NULL if the index does not + * @return Importer meta data structure, nullptr if the index does not * exist or if the importer doesn't offer meta information ( * importers may do this at the cost of being hated by their peers).*/ - const aiImporterDesc* GetImporterInfo(size_t index) const; + const aiImporterDesc *GetImporterInfo(size_t index) const; // ------------------------------------------------------------------- /** Find the importer corresponding to a specific index. * * @param index Index to query, must be within [0,GetImporterCount()) - * @return Importer instance. NULL if the index does not + * @return Importer instance. nullptr if the index does not * exist. */ - BaseImporter* GetImporter(size_t index) const; + BaseImporter *GetImporter(size_t index) const; // ------------------------------------------------------------------- /** Find the importer corresponding to a specific file extension. @@ -592,8 +590,8 @@ public: * are recognized (BAH being the file extension): "BAH" (comparison * is case-insensitive), ".bah", "*.bah" (wild card and dot * characters at the beginning of the extension are skipped). - * @return NULL if no importer is found*/ - BaseImporter* GetImporter (const char* szExtension) const; + * @return nullptr if no importer is found*/ + BaseImporter *GetImporter(const char *szExtension) const; // ------------------------------------------------------------------- /** Find the importer index corresponding to a specific file extension. @@ -603,7 +601,7 @@ public: * is case-insensitive), ".bah", "*.bah" (wild card and dot * characters at the beginning of the extension are skipped). * @return (size_t)-1 if no importer is found */ - size_t GetImporterIndex (const char* szExtension) const; + size_t GetImporterIndex(const char *szExtension) const; // ------------------------------------------------------------------- /** Returns the storage allocated by ASSIMP to hold the scene data @@ -614,7 +612,7 @@ public: * @note The returned memory statistics refer to the actual * size of the use data of the aiScene. Heap-related overhead * is (naturally) not included.*/ - void GetMemoryRequirements(aiMemoryInfo& in) const; + void GetMemoryRequirements(aiMemoryInfo &in) const; // ------------------------------------------------------------------- /** Enables "extra verbose" mode. @@ -627,16 +625,14 @@ public: // ------------------------------------------------------------------- /** Private, do not use. */ - ImporterPimpl* Pimpl() { return pimpl; } - const ImporterPimpl* Pimpl() const { return pimpl; } + ImporterPimpl *Pimpl() { return pimpl; } + const ImporterPimpl *Pimpl() const { return pimpl; } protected: - // Just because we don't want you to know how we're hacking around. - ImporterPimpl* pimpl; + ImporterPimpl *pimpl; }; //! class Importer - // ---------------------------------------------------------------------------- // For compatibility, the interface of some functions taking a std::string was // changed to const char* to avoid crashes between binary incompatible STL @@ -644,20 +640,20 @@ protected: // ---------------------------------------------------------------------------- // ---------------------------------------------------------------------------- -AI_FORCE_INLINE const aiScene* Importer::ReadFile( const std::string& pFile,unsigned int pFlags){ - return ReadFile(pFile.c_str(),pFlags); +AI_FORCE_INLINE const aiScene *Importer::ReadFile(const std::string &pFile, unsigned int pFlags) { + return ReadFile(pFile.c_str(), pFlags); } // ---------------------------------------------------------------------------- -AI_FORCE_INLINE void Importer::GetExtensionList(std::string& szOut) const { +AI_FORCE_INLINE void Importer::GetExtensionList(std::string &szOut) const { aiString s; GetExtensionList(s); szOut = s.data; } // ---------------------------------------------------------------------------- -AI_FORCE_INLINE bool Importer::IsExtensionSupported(const std::string& szExtension) const { +AI_FORCE_INLINE bool Importer::IsExtensionSupported(const std::string &szExtension) const { return IsExtensionSupported(szExtension.c_str()); } -} // !namespace Assimp +} // namespace Assimp #endif // AI_ASSIMP_HPP_INC diff --git a/include/assimp/LogStream.hpp b/include/assimp/LogStream.hpp index 243f13ee6..18b473430 100644 --- a/include/assimp/LogStream.hpp +++ b/include/assimp/LogStream.hpp @@ -48,7 +48,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "types.h" -namespace Assimp { +namespace Assimp { class IOSystem; @@ -60,7 +60,7 @@ class IOSystem; * are not enough for your purpose. */ class ASSIMP_API LogStream #ifndef SWIG - : public Intern::AllocateFromAssimpHeap + : public Intern::AllocateFromAssimpHeap #endif { protected: @@ -80,28 +80,26 @@ public: * #DefaultLogger:set(). Usually you can *expect* that a log message * is exactly one line and terminated with a single \n character. * @param message Message to be written */ - virtual void write(const char* message) = 0; + virtual void write(const char *message) = 0; // ------------------------------------------------------------------- /** @brief Creates a default log stream * @param streams Type of the default stream * @param name For aiDefaultLogStream_FILE: name of the output file * @param io For aiDefaultLogStream_FILE: IOSystem to be used to open the output - * file. Pass NULL for the default implementation. + * file. Pass nullptr for the default implementation. * @return New LogStream instance. */ - static LogStream* createDefaultStream(aiDefaultLogStream stream, - const char* name = "AssimpLog.txt", - IOSystem* io = nullptr ); + static LogStream *createDefaultStream(aiDefaultLogStream stream, + const char *name = "AssimpLog.txt", + IOSystem *io = nullptr); }; // !class LogStream -inline -LogStream::LogStream() AI_NO_EXCEPT { +inline LogStream::LogStream() AI_NO_EXCEPT { // empty } -inline -LogStream::~LogStream() { +inline LogStream::~LogStream() { // empty } diff --git a/include/assimp/ProgressHandler.hpp b/include/assimp/ProgressHandler.hpp index 45d3f57cd..9b5becfa8 100644 --- a/include/assimp/ProgressHandler.hpp +++ b/include/assimp/ProgressHandler.hpp @@ -91,7 +91,7 @@ public: * occasion (loaders and Assimp are generally allowed to perform * all needed cleanup tasks prior to returning control to the * caller). If the loading is aborted, #Importer::ReadFile() - * returns always NULL. + * returns always nullptr. * */ virtual bool Update(float percentage = -1.f) = 0; diff --git a/include/assimp/SceneCombiner.h b/include/assimp/SceneCombiner.h index 40aad0890..ff347d4fa 100644 --- a/include/assimp/SceneCombiner.h +++ b/include/assimp/SceneCombiner.h @@ -48,17 +48,17 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define AI_SCENE_COMBINER_H_INC #ifdef __GNUC__ -# pragma GCC system_header +#pragma GCC system_header #endif +#include #include #include -#include #include -#include -#include #include +#include +#include #include struct aiScene; @@ -75,68 +75,58 @@ struct aiAnimation; struct aiNodeAnim; struct aiMeshMorphAnim; -namespace Assimp { +namespace Assimp { // --------------------------------------------------------------------------- /** \brief Helper data structure for SceneCombiner. * * Describes to which node a scene must be attached to. */ -struct AttachmentInfo -{ - AttachmentInfo() - : scene (NULL) - , attachToNode (NULL) - {} +struct AttachmentInfo { + AttachmentInfo() : + scene(nullptr), + attachToNode(nullptr) {} - AttachmentInfo(aiScene* _scene, aiNode* _attachToNode) - : scene (_scene) - , attachToNode (_attachToNode) - {} + AttachmentInfo(aiScene *_scene, aiNode *_attachToNode) : + scene(_scene), attachToNode(_attachToNode) {} - aiScene* scene; - aiNode* attachToNode; + aiScene *scene; + aiNode *attachToNode; }; // --------------------------------------------------------------------------- -struct NodeAttachmentInfo -{ - NodeAttachmentInfo() - : node (NULL) - , attachToNode (NULL) - , resolved (false) - , src_idx (SIZE_MAX) - {} +struct NodeAttachmentInfo { + NodeAttachmentInfo() : + node(nullptr), + attachToNode(nullptr), + resolved(false), + src_idx(SIZE_MAX) {} - NodeAttachmentInfo(aiNode* _scene, aiNode* _attachToNode,size_t idx) - : node (_scene) - , attachToNode (_attachToNode) - , resolved (false) - , src_idx (idx) - {} + NodeAttachmentInfo(aiNode *_scene, aiNode *_attachToNode, size_t idx) : + node(_scene), attachToNode(_attachToNode), resolved(false), src_idx(idx) {} - aiNode* node; - aiNode* attachToNode; - bool resolved; - size_t src_idx; + aiNode *node; + aiNode *attachToNode; + bool resolved; + size_t src_idx; }; // --------------------------------------------------------------------------- /** @def AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES * Generate unique names for all named scene items */ -#define AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES 0x1 +#define AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES 0x1 /** @def AI_INT_MERGE_SCENE_GEN_UNIQUE_MATNAMES * Generate unique names for materials, too. * This is not absolutely required to pass the validation. */ -#define AI_INT_MERGE_SCENE_GEN_UNIQUE_MATNAMES 0x2 +#define AI_INT_MERGE_SCENE_GEN_UNIQUE_MATNAMES 0x2 /** @def AI_INT_MERGE_SCENE_DUPLICATES_DEEP_CPY * Use deep copies of duplicate scenes */ -#define AI_INT_MERGE_SCENE_DUPLICATES_DEEP_CPY 0x4 +#define AI_INT_MERGE_SCENE_DUPLICATES_DEEP_CPY 0x4 /** @def AI_INT_MERGE_SCENE_RESOLVE_CROSS_ATTACHMENTS * If attachment nodes are not found in the given master scene, @@ -151,44 +141,39 @@ struct NodeAttachmentInfo */ #define AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES_IF_NECESSARY 0x10 -typedef std::pair BoneSrcIndex; +typedef std::pair BoneSrcIndex; // --------------------------------------------------------------------------- /** @brief Helper data structure for SceneCombiner::MergeBones. */ -struct BoneWithHash : public std::pair { +struct BoneWithHash : public std::pair { std::vector pSrcBones; }; // --------------------------------------------------------------------------- /** @brief Utility for SceneCombiner */ -struct SceneHelper -{ - SceneHelper () - : scene (NULL) - , idlen (0) - { +struct SceneHelper { + SceneHelper() : + scene(nullptr), + idlen(0) { id[0] = 0; } - explicit SceneHelper (aiScene* _scene) - : scene (_scene) - , idlen (0) - { + explicit SceneHelper(aiScene *_scene) : + scene(_scene), idlen(0) { id[0] = 0; } - AI_FORCE_INLINE aiScene* operator-> () const - { + AI_FORCE_INLINE aiScene *operator->() const { return scene; } // scene we're working on - aiScene* scene; + aiScene *scene; // prefix to be added to all identifiers in the scene ... - char id [32]; + char id[32]; // and its strlen() unsigned int idlen; @@ -220,21 +205,21 @@ public: /** Merges two or more scenes. * * @param dest Receives a pointer to the destination scene. If the - * pointer doesn't point to NULL when the function is called, the + * pointer doesn't point to nullptr when the function is called, the * existing scene is cleared and refilled. * @param src Non-empty list of scenes to be merged. The function * deletes the input scenes afterwards. There may be duplicate scenes. * @param flags Combination of the AI_INT_MERGE_SCENE flags defined above */ - static void MergeScenes(aiScene** dest,std::vector& src, - unsigned int flags = 0); + static void MergeScenes(aiScene **dest, std::vector &src, + unsigned int flags = 0); // ------------------------------------------------------------------- /** Merges two or more scenes and attaches all scenes to a specific * position in the node graph of the master scene. * * @param dest Receives a pointer to the destination scene. If the - * pointer doesn't point to NULL when the function is called, the + * pointer doesn't point to nullptr when the function is called, the * existing scene is cleared and refilled. * @param master Master scene. It will be deleted afterwards. All * other scenes will be inserted in its node graph. @@ -243,9 +228,9 @@ public: * deletes the input scenes afterwards. There may be duplicate scenes. * @param flags Combination of the AI_INT_MERGE_SCENE flags defined above */ - static void MergeScenes(aiScene** dest, aiScene* master, - std::vector& src, - unsigned int flags = 0); + static void MergeScenes(aiScene **dest, aiScene *master, + std::vector &src, + unsigned int flags = 0); // ------------------------------------------------------------------- /** Merges two or more meshes @@ -261,9 +246,9 @@ public: * @param begin First mesh to be processed * @param end Points to the mesh after the last mesh to be processed */ - static void MergeMeshes(aiMesh** dest,unsigned int flags, - std::vector::const_iterator begin, - std::vector::const_iterator end); + static void MergeMeshes(aiMesh **dest, unsigned int flags, + std::vector::const_iterator begin, + std::vector::const_iterator end); // ------------------------------------------------------------------- /** Merges two or more bones @@ -273,8 +258,8 @@ public: * @param begin First mesh to be processed * @param end Points to the mesh after the last mesh to be processed */ - static void MergeBones(aiMesh* out,std::vector::const_iterator it, - std::vector::const_iterator end); + static void MergeBones(aiMesh *out, std::vector::const_iterator it, + std::vector::const_iterator end); // ------------------------------------------------------------------- /** Merges two or more materials @@ -287,9 +272,9 @@ public: * @param begin First material to be processed * @param end Points to the material after the last material to be processed */ - static void MergeMaterials(aiMaterial** dest, - std::vector::const_iterator begin, - std::vector::const_iterator end); + static void MergeMaterials(aiMaterial **dest, + std::vector::const_iterator begin, + std::vector::const_iterator end); // ------------------------------------------------------------------- /** Builds a list of uniquely named bones in a mesh list @@ -298,9 +283,9 @@ public: * @param it First mesh to be processed * @param end Last mesh to be processed */ - static void BuildUniqueBoneList(std::list& asBones, - std::vector::const_iterator it, - std::vector::const_iterator end); + static void BuildUniqueBoneList(std::list &asBones, + std::vector::const_iterator it, + std::vector::const_iterator end); // ------------------------------------------------------------------- /** Add a name prefix to all nodes in a scene. @@ -309,8 +294,8 @@ public: * @param prefix Prefix to be added to all nodes * @param len STring length */ - static void AddNodePrefixes(aiNode* node, const char* prefix, - unsigned int len); + static void AddNodePrefixes(aiNode *node, const char *prefix, + unsigned int len); // ------------------------------------------------------------------- /** Add an offset to all mesh indices in a node graph @@ -318,7 +303,7 @@ public: * @param Current node. This function is called recursively. * @param offset Offset to be added to all mesh indices */ - static void OffsetNodeMeshIndices (aiNode* node, unsigned int offset); + static void OffsetNodeMeshIndices(aiNode *node, unsigned int offset); // ------------------------------------------------------------------- /** Attach a list of node graphs to well-defined nodes in a master @@ -326,18 +311,17 @@ public: * * @param master Master scene * @param srcList List of source scenes along with their attachment - * points. If an attachment point is NULL (or does not exist in + * points. If an attachment point is nullptr (or does not exist in * the master graph), a scene is attached to the root of the master * graph (as an additional child node) * @duplicates List of duplicates. If elem[n] == n the scene is not * a duplicate. Otherwise elem[n] links scene n to its first occurrence. */ - static void AttachToGraph ( aiScene* master, - std::vector& srcList); - - static void AttachToGraph (aiNode* attach, - std::vector& srcList); + static void AttachToGraph(aiScene *master, + std::vector &srcList); + static void AttachToGraph(aiNode *attach, + std::vector &srcList); // ------------------------------------------------------------------- /** Get a deep copy of a scene @@ -345,21 +329,19 @@ public: * @param dest Receives a pointer to the destination scene * @param src Source scene - remains unmodified. */ - static void CopyScene(aiScene** dest,const aiScene* source,bool allocate = true); - + static void CopyScene(aiScene **dest, const aiScene *source, bool allocate = true); // ------------------------------------------------------------------- /** Get a flat copy of a scene * * Only the first hierarchy layer is copied. All pointer members of * aiScene are shared by source and destination scene. If the - * pointer doesn't point to NULL when the function is called, the + * pointer doesn't point to nullptr when the function is called, the * existing scene is cleared and refilled. * @param dest Receives a pointer to the destination scene * @param src Source scene - remains unmodified. */ - static void CopySceneFlat(aiScene** dest,const aiScene* source); - + static void CopySceneFlat(aiScene **dest, const aiScene *source); // ------------------------------------------------------------------- /** Get a deep copy of a mesh @@ -367,44 +349,41 @@ public: * @param dest Receives a pointer to the destination mesh * @param src Source mesh - remains unmodified. */ - static void Copy (aiMesh** dest, const aiMesh* src); + static void Copy(aiMesh **dest, const aiMesh *src); // similar to Copy(): - static void Copy (aiAnimMesh** dest, const aiAnimMesh* src); - static void Copy (aiMaterial** dest, const aiMaterial* src); - static void Copy (aiTexture** dest, const aiTexture* src); - static void Copy (aiAnimation** dest, const aiAnimation* src); - static void Copy (aiCamera** dest, const aiCamera* src); - static void Copy (aiBone** dest, const aiBone* src); - static void Copy (aiLight** dest, const aiLight* src); - static void Copy (aiNodeAnim** dest, const aiNodeAnim* src); - static void Copy (aiMeshMorphAnim** dest, const aiMeshMorphAnim* src); - static void Copy (aiMetadata** dest, const aiMetadata* src); + static void Copy(aiAnimMesh **dest, const aiAnimMesh *src); + static void Copy(aiMaterial **dest, const aiMaterial *src); + static void Copy(aiTexture **dest, const aiTexture *src); + static void Copy(aiAnimation **dest, const aiAnimation *src); + static void Copy(aiCamera **dest, const aiCamera *src); + static void Copy(aiBone **dest, const aiBone *src); + static void Copy(aiLight **dest, const aiLight *src); + static void Copy(aiNodeAnim **dest, const aiNodeAnim *src); + static void Copy(aiMeshMorphAnim **dest, const aiMeshMorphAnim *src); + static void Copy(aiMetadata **dest, const aiMetadata *src); // recursive, of course - static void Copy (aiNode** dest, const aiNode* src); - + static void Copy(aiNode **dest, const aiNode *src); private: - // ------------------------------------------------------------------- // Same as AddNodePrefixes, but with an additional check - static void AddNodePrefixesChecked(aiNode* node, const char* prefix, - unsigned int len, - std::vector& input, - unsigned int cur); + static void AddNodePrefixesChecked(aiNode *node, const char *prefix, + unsigned int len, + std::vector &input, + unsigned int cur); // ------------------------------------------------------------------- // Add node identifiers to a hashing set - static void AddNodeHashes(aiNode* node, std::set& hashes); - + static void AddNodeHashes(aiNode *node, std::set &hashes); // ------------------------------------------------------------------- // Search for duplicate names - static bool FindNameMatch(const aiString& name, - std::vector& input, unsigned int cur); + static bool FindNameMatch(const aiString &name, + std::vector &input, unsigned int cur); }; -} +} // namespace Assimp #endif // !! AI_SCENE_COMBINER_H_INC diff --git a/include/assimp/SkeletonMeshBuilder.h b/include/assimp/SkeletonMeshBuilder.h index 8e1a9830f..f477850a9 100644 --- a/include/assimp/SkeletonMeshBuilder.h +++ b/include/assimp/SkeletonMeshBuilder.h @@ -52,17 +52,17 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define AI_SKELETONMESHBUILDER_H_INC #ifdef __GNUC__ -# pragma GCC system_header +#pragma GCC system_header #endif -#include #include +#include struct aiMaterial; struct aiScene; struct aiNode; -namespace Assimp { +namespace Assimp { // --------------------------------------------------------------------------- /** @@ -70,57 +70,56 @@ namespace Assimp { * the resembles the node hierarchy. This is useful for file formats * that don't carry any mesh data but only animation data. */ -class ASSIMP_API SkeletonMeshBuilder -{ +class ASSIMP_API SkeletonMeshBuilder { public: - // ------------------------------------------------------------------- /** The constructor processes the given scene and adds a mesh there. * * Does nothing if the scene already has mesh data. * @param pScene The scene for which a skeleton mesh should be constructed. - * @param root The node to start with. NULL is the scene root + * @param root The node to start with. nullptr is the scene root * @param bKnobsOnly Set this to true if you don't want the connectors * between the knobs representing the nodes. */ - SkeletonMeshBuilder( aiScene* pScene, aiNode* root = NULL, - bool bKnobsOnly = false); + SkeletonMeshBuilder(aiScene *pScene, aiNode *root = nullptr, + bool bKnobsOnly = false); protected: - // ------------------------------------------------------------------- /** Recursively builds a simple mesh representation for the given node * and also creates a joint for the node that affects this part of * the mesh. * @param pNode The node to build geometry for. */ - void CreateGeometry( const aiNode* pNode); + void CreateGeometry(const aiNode *pNode); // ------------------------------------------------------------------- /** Creates the mesh from the internally accumulated stuff and returns it. */ - aiMesh* CreateMesh(); + aiMesh *CreateMesh(); // ------------------------------------------------------------------- /** Creates a dummy material and returns it. */ - aiMaterial* CreateMaterial(); + aiMaterial *CreateMaterial(); protected: /** space to assemble the mesh data: points */ std::vector mVertices; /** faces */ - struct Face - { + struct Face { unsigned int mIndices[3]; Face(); - Face( unsigned int p0, unsigned int p1, unsigned int p2) - { mIndices[0] = p0; mIndices[1] = p1; mIndices[2] = p2; } + Face(unsigned int p0, unsigned int p1, unsigned int p2) { + mIndices[0] = p0; + mIndices[1] = p1; + mIndices[2] = p2; + } }; std::vector mFaces; /** bones */ - std::vector mBones; + std::vector mBones; bool mKnobsOnly; }; diff --git a/include/assimp/StandardShapes.h b/include/assimp/StandardShapes.h index 79bdae859..7734138a6 100644 --- a/include/assimp/StandardShapes.h +++ b/include/assimp/StandardShapes.h @@ -52,6 +52,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endif #include +#include #include struct aiMesh; diff --git a/include/assimp/StringComparison.h b/include/assimp/StringComparison.h index d7b8972e3..255123c0e 100644 --- a/include/assimp/StringComparison.h +++ b/include/assimp/StringComparison.h @@ -54,18 +54,18 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define INCLUDED_AI_STRING_WORKERS_H #ifdef __GNUC__ -# pragma GCC system_header +#pragma GCC system_header #endif +#include #include #include -#include -#include #include +#include #include -namespace Assimp { +namespace Assimp { // ------------------------------------------------------------------------------- /** @brief itoa with a fixed base 10 @@ -79,12 +79,12 @@ namespace Assimp { * @return Length of the output string, excluding the '\0' */ AI_FORCE_INLINE -unsigned int ASSIMP_itoa10( char* out, unsigned int max, int32_t number) { - ai_assert(NULL != out); +unsigned int ASSIMP_itoa10(char *out, unsigned int max, int32_t number) { + ai_assert(nullptr != out); // write the unary minus to indicate we have a negative number unsigned int written = 1u; - if (number < 0 && written < max) { + if (number < 0 && written < max) { *out++ = '-'; ++written; number = -number; @@ -93,17 +93,17 @@ unsigned int ASSIMP_itoa10( char* out, unsigned int max, int32_t number) { // We begin with the largest number that is not zero. int32_t cur = 1000000000; // 2147483648 bool mustPrint = false; - while (written < max) { + while (written < max) { const unsigned int digit = number / cur; if (mustPrint || digit > 0 || 1 == cur) { // print all future zeroe's from now mustPrint = true; - *out++ = '0'+static_cast(digit); + *out++ = '0' + static_cast(digit); ++written; - number -= digit*cur; + number -= digit * cur; if (1 == cur) { break; } @@ -113,7 +113,7 @@ unsigned int ASSIMP_itoa10( char* out, unsigned int max, int32_t number) { // append a terminal zero *out++ = '\0'; - return written-1; + return written - 1; } // ------------------------------------------------------------------------------- @@ -122,9 +122,8 @@ unsigned int ASSIMP_itoa10( char* out, unsigned int max, int32_t number) { * size of the array automatically. */ template -AI_FORCE_INLINE -unsigned int ASSIMP_itoa10( char(& out)[length], int32_t number) { - return ASSIMP_itoa10(out,length,number); +AI_FORCE_INLINE unsigned int ASSIMP_itoa10(char (&out)[length], int32_t number) { + return ASSIMP_itoa10(out, length, number); } // ------------------------------------------------------------------------------- @@ -140,23 +139,22 @@ unsigned int ASSIMP_itoa10( char(& out)[length], int32_t number) { */ AI_FORCE_INLINE int ASSIMP_stricmp(const char *s1, const char *s2) { - ai_assert( NULL != s1 ); - ai_assert( NULL != s2 ); + ai_assert(nullptr != s1); + ai_assert(nullptr != s2); #if (defined _MSC_VER) - return ::_stricmp(s1,s2); -#elif defined( __GNUC__ ) + return ::_stricmp(s1, s2); +#elif defined(__GNUC__) - return ::strcasecmp(s1,s2); + return ::strcasecmp(s1, s2); #else char c1, c2; - do { + do { c1 = tolower(*s1++); c2 = tolower(*s2++); - } - while ( c1 && (c1 == c2) ); + } while (c1 && (c1 == c2)); return c1 - c2; #endif } @@ -169,9 +167,9 @@ int ASSIMP_stricmp(const char *s1, const char *s2) { * @return 0 if a == b */ AI_FORCE_INLINE -int ASSIMP_stricmp(const std::string& a, const std::string& b) { - int i = (int)b.length()-(int)a.length(); - return (i ? i : ASSIMP_stricmp(a.c_str(),b.c_str())); +int ASSIMP_stricmp(const std::string &a, const std::string &b) { + int i = (int)b.length() - (int)a.length(); + return (i ? i : ASSIMP_stricmp(a.c_str(), b.c_str())); } // ------------------------------------------------------------------------------- @@ -188,51 +186,48 @@ int ASSIMP_stricmp(const std::string& a, const std::string& b) { */ AI_FORCE_INLINE int ASSIMP_strincmp(const char *s1, const char *s2, unsigned int n) { - ai_assert( NULL != s1 ); - ai_assert( NULL != s2 ); - if ( !n ) { + ai_assert(nullptr != s1); + ai_assert(nullptr != s2); + if (!n) { return 0; } #if (defined _MSC_VER) - return ::_strnicmp(s1,s2,n); + return ::_strnicmp(s1, s2, n); -#elif defined( __GNUC__ ) +#elif defined(__GNUC__) - return ::strncasecmp(s1,s2, n); + return ::strncasecmp(s1, s2, n); #else char c1, c2; unsigned int p = 0; - do - { - if (p++ >= n)return 0; + do { + if (p++ >= n) return 0; c1 = tolower(*s1++); c2 = tolower(*s2++); - } - while ( c1 && (c1 == c2) ); + } while (c1 && (c1 == c2)); return c1 - c2; #endif } - // ------------------------------------------------------------------------------- /** @brief Evaluates an integer power * * todo: move somewhere where it fits better in than here */ AI_FORCE_INLINE -unsigned int integer_pow( unsigned int base, unsigned int power ) { +unsigned int integer_pow(unsigned int base, unsigned int power) { unsigned int res = 1; - for ( unsigned int i = 0; i < power; ++i ) { + for (unsigned int i = 0; i < power; ++i) { res *= base; } return res; } -} // end of namespace +} // namespace Assimp #endif // ! AI_STRINGCOMPARISON_H_INC diff --git a/include/assimp/ai_assert.h b/include/assimp/ai_assert.h index f018163bf..8b2b396f4 100644 --- a/include/assimp/ai_assert.h +++ b/include/assimp/ai_assert.h @@ -42,14 +42,17 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef AI_ASSERT_H_INC #define AI_ASSERT_H_INC -#ifdef __GNUC__ -# pragma GCC system_header -#endif +#if defined(ASSIMP_BUILD_DEBUG) + +namespace Assimp +{ + // Assert violation behavior can be customized: see AssertHandler.h. + void aiAssertViolation(const char* failedExpression, const char* file, int line); +} + +# define ai_assert(expression) (void)((!!(expression)) || (Assimp::aiAssertViolation(#expression, __FILE__, __LINE__), 0)) +# define ai_assert_entry() ai_assert(false) -#ifdef ASSIMP_BUILD_DEBUG -# include -# define ai_assert(expression) assert( expression ) -# define ai_assert_entry() assert( false ) #else # define ai_assert(expression) # define ai_assert_entry() diff --git a/include/assimp/anim.h b/include/assimp/anim.h index b43991b80..ea26d0bc4 100644 --- a/include/assimp/anim.h +++ b/include/assimp/anim.h @@ -348,7 +348,7 @@ struct aiMeshAnim { /** Size of the #mKeys array. Must be 1, at least. */ unsigned int mNumKeys; - /** Key frames of the animation. May not be NULL. */ + /** Key frames of the animation. May not be nullptr. */ C_STRUCT aiMeshKey *mKeys; #ifdef __cplusplus @@ -376,7 +376,7 @@ struct aiMeshMorphAnim { /** Size of the #mKeys array. Must be 1, at least. */ unsigned int mNumKeys; - /** Key frames of the animation. May not be NULL. */ + /** Key frames of the animation. May not be nullptr. */ C_STRUCT aiMeshMorphKey *mKeys; #ifdef __cplusplus diff --git a/include/assimp/importerdesc.h b/include/assimp/importerdesc.h index e0f22a9d6..f731ed1c4 100644 --- a/include/assimp/importerdesc.h +++ b/include/assimp/importerdesc.h @@ -49,10 +49,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define AI_IMPORTER_DESC_H_INC #ifdef __GNUC__ -# pragma GCC system_header +#pragma GCC system_header #endif - /** Mixed set of flags for #aiImporterDesc, indicating some features * common to many importers*/ enum aiImporterFlags { @@ -81,7 +80,6 @@ enum aiImporterFlags { aiImporterFlags_Experimental = 0x10 }; - /** Meta information about a particular importer. Importers need to fill * this structure, but they can freely decide how talkative they are. * A common use case for loader meta info is a user interface @@ -92,16 +90,16 @@ enum aiImporterFlags { * characteristics. */ struct aiImporterDesc { /** Full name of the importer (i.e. Blender3D importer)*/ - const char* mName; + const char *mName; /** Original author (left blank if unknown or whole assimp team) */ - const char* mAuthor; + const char *mAuthor; /** Current maintainer, left blank if the author maintains */ - const char* mMaintainer; + const char *mMaintainer; /** Implementation comments, i.e. unimplemented features*/ - const char* mComments; + const char *mComments; /** These flags indicate some characteristics common to many importers. */ @@ -134,15 +132,15 @@ struct aiImporterDesc { other methods to quickly reject files (i.e. magic words) so this does not mean that common or generic file extensions such as XML would be tediously slow. */ - const char* mFileExtensions; + const char *mFileExtensions; }; /** \brief Returns the Importer description for a given extension. -Will return a NULL-pointer if no assigned importer desc. was found for the given extension +Will return a nullptr if no assigned importer desc. was found for the given extension \param extension [in] The extension to look for \return A pointer showing to the ImporterDesc, \see aiImporterDesc. */ -ASSIMP_API const C_STRUCT aiImporterDesc* aiGetImporterDesc( const char *extension ); +ASSIMP_API const C_STRUCT aiImporterDesc *aiGetImporterDesc(const char *extension); #endif // AI_IMPORTER_DESC_H_INC diff --git a/include/assimp/irrXMLWrapper.h b/include/assimp/irrXMLWrapper.h new file mode 100644 index 000000000..52c174791 --- /dev/null +++ b/include/assimp/irrXMLWrapper.h @@ -0,0 +1,149 @@ +/* +Open Asset Import Library (assimp) +---------------------------------------------------------------------- + +Copyright (c) 2006-2020, 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. + +---------------------------------------------------------------------- +*/ + +#ifndef INCLUDED_AI_IRRXML_WRAPPER +#define INCLUDED_AI_IRRXML_WRAPPER + +// some long includes .... +#ifdef ASSIMP_USE_HUNTER +# include +#else +# include +#endif +#include "IOStream.hpp" +#include "BaseImporter.h" +#include + +namespace Assimp { + +// --------------------------------------------------------------------------------- +/** @brief Utility class to make IrrXML work together with our custom IO system + * See the IrrXML docs for more details. + * + * Construct IrrXML-Reader in BaseImporter::InternReadFile(): + * @code + * // open the file + * std::unique_ptr file( pIOHandler->Open( pFile)); + * if( file.get() == nullptr ) { + * throw DeadlyImportError( "Failed to open file " + pFile + "."); + * } + * + * // generate a XML reader for it + * std::unique_ptr mIOWrapper( new CIrrXML_IOStreamReader( file.get())); + * mReader = irr::io::createIrrXMLReader( mIOWrapper.get()); + * if( !mReader) { + * ThrowException( "xxxx: Unable to open file."); + * } + * @endcode + **/ +class CIrrXML_IOStreamReader : public irr::io::IFileReadCallBack { +public: + + // ---------------------------------------------------------------------------------- + //! Construction from an existing IOStream + explicit CIrrXML_IOStreamReader(IOStream* _stream) + : stream (_stream) + , t (0) + { + + // Map the buffer into memory and convert it to UTF8. IrrXML provides its + // own conversion, which is merely a cast from uintNN_t to uint8_t. Thus, + // it is not suitable for our purposes and we have to do it BEFORE IrrXML + // gets the buffer. Sadly, this forces us to map the whole file into + // memory. + + data.resize(stream->FileSize()); + stream->Read(&data[0],data.size(),1); + + // Remove null characters from the input sequence otherwise the parsing will utterly fail + // std::find is usually much faster than manually iterating + // It is very unlikely that there will be any null characters + auto null_char_iter = std::find(data.begin(), data.end(), '\0'); + + while (null_char_iter != data.end()) + { + null_char_iter = data.erase(null_char_iter); + null_char_iter = std::find(null_char_iter, data.end(), '\0'); + } + + BaseImporter::ConvertToUTF8(data); + } + + // ---------------------------------------------------------------------------------- + //! Virtual destructor + virtual ~CIrrXML_IOStreamReader() {} + + // ---------------------------------------------------------------------------------- + //! Reads an amount of bytes from the file. + /** @param buffer: Pointer to output buffer. + * @param sizeToRead: Amount of bytes to read + * @return Returns how much bytes were read. */ + virtual int read(void* buffer, int sizeToRead) { + if(sizeToRead<0) { + return 0; + } + if(t+sizeToRead>data.size()) { + sizeToRead = static_cast(data.size()-t); + } + + memcpy(buffer,&data.front()+t,sizeToRead); + + t += sizeToRead; + return sizeToRead; + } + + // ---------------------------------------------------------------------------------- + //! Returns size of file in bytes + virtual int getSize() { + return (int)data.size(); + } + +private: + IOStream* stream; + std::vector data; + size_t t; + +}; // ! class CIrrXML_IOStreamReader + +} // ! Assimp + +#endif // !! INCLUDED_AI_IRRXML_WRAPPER diff --git a/include/assimp/metadata.h b/include/assimp/metadata.h index 684508a71..52121fbf1 100644 --- a/include/assimp/metadata.h +++ b/include/assimp/metadata.h @@ -69,7 +69,8 @@ typedef enum aiMetadataType { AI_DOUBLE = 4, AI_AISTRING = 5, AI_AIVECTOR3D = 6, - AI_META_MAX = 7, + AI_AIMETADATA = 7, + AI_META_MAX = 8, #ifndef SWIG FORCE_32BIT = INT_MAX @@ -100,6 +101,8 @@ struct aiMetadataEntry { #include +struct aiMetadata; + // ------------------------------------------------------------------------------- /** * Helper functions to get the aiType enum entry for a type @@ -127,6 +130,9 @@ inline aiMetadataType GetAiType(const aiString &) { inline aiMetadataType GetAiType(const aiVector3D &) { return AI_AIVECTOR3D; } +inline aiMetadataType GetAiType(const aiMetadata &) { + return AI_AIMETADATA; +} #endif // __cplusplus @@ -204,6 +210,11 @@ struct aiMetadata { rhs.Get(mKeys[i], v); mValues[i].mData = new aiVector3D(v); } break; + case AI_AIMETADATA: { + aiMetadata v; + rhs.Get(mKeys[i], v); + mValues[i].mData = new aiMetadata(v); + } break; #ifndef SWIG case FORCE_32BIT: #endif @@ -213,7 +224,15 @@ struct aiMetadata { } } - /** + aiMetadata &operator=(aiMetadata rhs) { + using std::swap; + swap(mNumProperties, rhs.mNumProperties); + swap(mKeys, rhs.mKeys); + swap(mValues, rhs.mValues); + return *this; + } + + /** * @brief The destructor. */ ~aiMetadata() { @@ -245,6 +264,9 @@ struct aiMetadata { case AI_AIVECTOR3D: delete static_cast(data); break; + case AI_AIMETADATA: + delete static_cast(data); + break; #ifndef SWIG case FORCE_32BIT: #endif @@ -323,8 +345,10 @@ struct aiMetadata { mValues[index].mType = GetAiType(value); // Copy the given value to the dynamic storage - if (nullptr != mValues[index].mData) { + if (nullptr != mValues[index].mData && AI_AIMETADATA != mValues[index].mType) { ::memcpy(mValues[index].mData, &value, sizeof(T)); + } else if (nullptr != mValues[index].mData && AI_AIMETADATA == mValues[index].mType) { + *static_cast(mValues[index].mData) = value; } else { mValues[index].mData = new T(value); } @@ -418,6 +442,89 @@ struct aiMetadata { return false; } + friend bool CompareKeys(const aiMetadata &lhs, const aiMetadata &rhs) { + if (lhs.mNumProperties != rhs.mNumProperties) { + return false; + } + + for (unsigned int i = 0; i < lhs.mNumProperties; ++i) { + if (lhs.mKeys[i] != rhs.mKeys[i]) { + return false; + } + } + return true; + } + + friend bool CompareValues(const aiMetadata &lhs, const aiMetadata &rhs) { + if (lhs.mNumProperties != rhs.mNumProperties) { + return false; + } + + for (unsigned int i = 0; i < lhs.mNumProperties; ++i) { + if (lhs.mValues[i].mType != rhs.mValues[i].mType) { + return false; + } + + switch (lhs.mValues[i].mType) { + case AI_BOOL: { + if (*static_cast(lhs.mValues[i].mData) != *static_cast(rhs.mValues[i].mData)) { + return false; + } + } break; + case AI_INT32: { + if (*static_cast(lhs.mValues[i].mData) != *static_cast(rhs.mValues[i].mData)) { + return false; + } + } break; + case AI_UINT64: { + if (*static_cast(lhs.mValues[i].mData) != *static_cast(rhs.mValues[i].mData)) { + return false; + } + } break; + case AI_FLOAT: { + if (*static_cast(lhs.mValues[i].mData) != *static_cast(rhs.mValues[i].mData)) { + return false; + } + } break; + case AI_DOUBLE: { + if (*static_cast(lhs.mValues[i].mData) != *static_cast(rhs.mValues[i].mData)) { + return false; + } + } break; + case AI_AISTRING: { + if (*static_cast(lhs.mValues[i].mData) != *static_cast(rhs.mValues[i].mData)) { + return false; + } + } break; + case AI_AIVECTOR3D: { + if (*static_cast(lhs.mValues[i].mData) != *static_cast(rhs.mValues[i].mData)) { + return false; + } + } break; + case AI_AIMETADATA: { + if (*static_cast(lhs.mValues[i].mData) != *static_cast(rhs.mValues[i].mData)) { + return false; + } + } break; +#ifndef SWIG + case FORCE_32BIT: +#endif + default: + break; + } + } + + return true; + } + + friend bool operator==(const aiMetadata &lhs, const aiMetadata &rhs) { + return CompareKeys(lhs, rhs) && CompareValues(lhs, rhs); + } + + friend bool operator!=(const aiMetadata &lhs, const aiMetadata &rhs) { + return !(lhs == rhs); + } + #endif // __cplusplus }; diff --git a/port/PyAssimp/README.md b/port/PyAssimp/README.md index d64d72763..c9944f717 100644 --- a/port/PyAssimp/README.md +++ b/port/PyAssimp/README.md @@ -42,17 +42,14 @@ substituted by assertions ...): ```python -from pyassimp import * -scene = load('hello.3ds') +from pyassimp import load +with load('hello.3ds') as scene: -assert len(scene.meshes) -mesh = scene.meshes[0] + assert len(scene.meshes) + mesh = scene.meshes[0] -assert len(mesh.vertices) -print(mesh.vertices[0]) - -# don't forget this one, or you will leak! -release(scene) + assert len(mesh.vertices) + print(mesh.vertices[0]) ``` @@ -61,13 +58,11 @@ scene: ```python -from pyassimp import * -scene = load('hello.3ds') +from pyassimp import load +with load('hello.3ds') as scene: -for c in scene.rootnode.children: - print(str(c)) - -release(scene) + for c in scene.rootnode.children: + print(str(c)) ``` diff --git a/port/PyAssimp/README.rst b/port/PyAssimp/README.rst index f909e2cd0..03b7968f1 100644 --- a/port/PyAssimp/README.rst +++ b/port/PyAssimp/README.rst @@ -49,30 +49,27 @@ substituted by assertions ...): .. code:: python - from pyassimp import * - scene = load('hello.3ds') + from pyassimp import load + with load('hello.3ds') as scene: - assert len(scene.meshes) - mesh = scene.meshes[0] + assert len(scene.meshes) + mesh = scene.meshes[0] - assert len(mesh.vertices) - print(mesh.vertices[0]) + assert len(mesh.vertices) + print(mesh.vertices[0]) - # don't forget this one, or you will leak! - release(scene) Another example to list the 'top nodes' in a scene: .. code:: python - from pyassimp import * - scene = load('hello.3ds') + from pyassimp import load + with load('hello.3ds') as scene: - for c in scene.rootnode.children: - print(str(c)) + for c in scene.rootnode.children: + print(str(c)) - release(scene) INSTALL ------- diff --git a/port/PyAssimp/pyassimp/core.py b/port/PyAssimp/pyassimp/core.py index 85cfe8233..37beac886 100644 --- a/port/PyAssimp/pyassimp/core.py +++ b/port/PyAssimp/pyassimp/core.py @@ -14,10 +14,13 @@ if sys.version_info >= (3,0): xrange = range -try: import numpy -except ImportError: numpy = None +try: + import numpy +except ImportError: + numpy = None import logging import ctypes +from contextlib import contextmanager logger = logging.getLogger("pyassimp") # attach default null handler to logger so it doesn't complain # even if you don't attach another handler to logger @@ -272,6 +275,13 @@ def recur_pythonize(node, scene): for c in node.children: recur_pythonize(c, scene) +def release(scene): + ''' + Release resources of a loaded scene. + ''' + _assimp_lib.release(ctypes.pointer(scene)) + +@contextmanager def load(filename, file_type = None, processing = postprocess.aiProcess_Triangulate): @@ -319,7 +329,10 @@ def load(filename, raise AssimpError('Could not import file!') scene = _init(model.contents) recur_pythonize(scene.rootnode, scene) - return scene + try: + yield scene + finally: + release(scene) def export(scene, filename, @@ -373,9 +386,6 @@ def export_blob(scene, raise AssimpError('Could not export scene to blob!') return exportBlobPtr -def release(scene): - _assimp_lib.release(ctypes.pointer(scene)) - def _finalize_texture(tex, target): setattr(target, "achformathint", tex.achFormatHint) if numpy: diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index a5f8086e9..8e1746ce2 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -87,6 +87,7 @@ SET( COMMON unit/Common/uiScene.cpp unit/Common/utLineSplitter.cpp unit/Common/utSpatialSort.cpp + unit/Common/utAssertHandler.cpp ) SET( IMPORTERS diff --git a/test/models/glTF2/issue_3269/texcoord_crash.gltf b/test/models/glTF2/issue_3269/texcoord_crash.gltf new file mode 100644 index 000000000..bc5d13f31 --- /dev/null +++ b/test/models/glTF2/issue_3269/texcoord_crash.gltf @@ -0,0 +1,610 @@ +{ + "accessors" : [ + { + "bufferView" : 0, + "componentType" : 5121, + "count" : 6, + "max" : [ + 3 + ], + "min" : [ + 0 + ], + "type" : "SCALAR" + }, + { + "bufferView" : 1, + "componentType" : 5126, + "count" : 4, + "max" : [ + 1.2000000476837158, + 1.2000001668930054, + -5.205485820169997e-08 + ], + "min" : [ + 0.19999980926513672, + 0.20000004768371582, + -1.5933926533762133e-07 + ], + "type" : "VEC3" + }, + { + "bufferView" : 2, + "componentType" : 5126, + "count" : 4, + "max" : [ + -2.1316282072803006e-14, + 1.0728441424134871e-07, + 1.0 + ], + "min" : [ + -2.1316282072803006e-14, + 1.0728441424134871e-07, + 1.0 + ], + "type" : "VEC3" + }, + { + "name": "TopRight_TEXCOORD_0", + "bufferView" : 3, + "componentType" : 5126, + "count" : 4, + "max" : [ + 1.0, + 0.3999999761581421 + ], + "min" : [ + 0.6000000238418579, + 0.0 + ], + "type" : "VEC2" + }, + { + "bufferView" : 4, + "componentType" : 5121, + "count" : 6, + "max" : [ + 3 + ], + "min" : [ + 0 + ], + "type" : "SCALAR" + }, + { + "bufferView" : 5, + "componentType" : 5126, + "count" : 4, + "max" : [ + -0.20000006258487701, + 1.2000000476837158, + 1.2601539367551595e-07 + ], + "min" : [ + -1.2000001668930054, + 0.19999974966049194, + -3.3740951721483725e-07 + ], + "type" : "VEC3" + }, + { + "bufferView" : 6, + "componentType" : 5126, + "count" : 4, + "max" : [ + 1.7807019503379706e-07, + 2.853547016457014e-07, + 1.0 + ], + "min" : [ + 1.7807019503379706e-07, + 2.853547016457014e-07, + 1.0 + ], + "type" : "VEC3" + }, + { + "name": "TopLeft_TEXCOORD_0", + "bufferView" : 7, + "componentType" : 5126, + "count" : 4, + "max" : [ + 0.3999999463558197, + 0.3999999761581421 + ], + "min" : [ + 7.915305388905836e-08, + 0.0 + ], + "type" : "VEC2" + }, + { + "bufferView" : 8, + "componentType" : 5121, + "count" : 6, + "max" : [ + 3 + ], + "min" : [ + 0 + ], + "type" : "SCALAR" + }, + { + "bufferView" : 9, + "componentType" : 5126, + "count" : 4, + "max" : [ + 1.2000001668930054, + -0.1999996304512024, + 5.255118367131217e-07 + ], + "min" : [ + 0.2000000923871994, + -1.2000000476837158, + 6.20869826661874e-08 + ], + "type" : "VEC3" + }, + { + "bufferView" : 10, + "componentType" : 5126, + "count" : 4, + "max" : [ + -1.7807025187721592e-07, + 2.853545879588637e-07, + 1.0 + ], + "min" : [ + -1.7807025187721592e-07, + 2.853545879588637e-07, + 1.0 + ], + "type" : "VEC3" + }, + { + "name": "BottomRight_TEXCOORD_0", + "bufferView" : 11, + "componentType" : 5126, + "count" : 4, + "max" : [ + 0.9999998807907104, + 1.0 + ], + "min" : [ + 0.6000000834465027, + 0.599999874830246 + ], + "type" : "VEC2" + }, + { + "bufferView" : 12, + "componentType" : 5121, + "count" : 6, + "max" : [ + 3 + ], + "min" : [ + 0 + ], + "type" : "SCALAR" + }, + { + "bufferView" : 13, + "componentType" : 5126, + "count" : 4, + "max" : [ + 1.0000001192092896, + 1.0000001192092896, + -0.052591003477573395 + ], + "min" : [ + -1.0000001192092896, + -1.0000001192092896, + -0.05259115248918533 + ], + "type" : "VEC3" + }, + { + "bufferView" : 14, + "componentType" : 5126, + "count" : 4, + "max" : [ + 1.0658142730467397e-14, + -7.450581307466564e-08, + -1.0 + ], + "min" : [ + 1.0658142730467397e-14, + -7.450581307466564e-08, + -1.0 + ], + "type" : "VEC3" + }, + { + "bufferView" : 15, + "componentType" : 5121, + "count" : 6, + "max" : [ + 3 + ], + "min" : [ + 0 + ], + "type" : "SCALAR" + }, + { + "bufferView" : 16, + "componentType" : 5126, + "count" : 4, + "max" : [ + -0.19999969005584717, + -0.2000000774860382, + 5.255118367131217e-07 + ], + "min" : [ + -1.2000000476837158, + -1.2000001668930054, + 6.208701108789683e-08 + ], + "type" : "VEC3" + }, + { + "bufferView" : 17, + "componentType" : 5126, + "count" : 4, + "max" : [ + -8.526512829121202e-14, + 4.6342486825778906e-07, + 1.0 + ], + "min" : [ + -8.526512829121202e-14, + 4.6342486825778906e-07, + 1.0 + ], + "type" : "VEC3" + }, + { + "name": "BottomLeft_TEXCOORD_0", + "bufferView" : 18, + "componentType" : 5126, + "count" : 4, + "max" : [ + 0.40000009536743164, + 0.9999999208469248 + ], + "min" : [ + 0.0, + 0.6000000536441803 + ], + "type" : "VEC2" + } + ], + "asset" : { + "copyright" : "Copyright 2017-2018 Analytical Graphics, Inc., CC-BY 4.0 https://creativecommons.org/licenses/by/4.0/ - Mesh and textures by Ed Mackey.", + "generator" : "Khronos Blender glTF 2.0 exporter, plus hand-edits", + "version" : "2.0" + }, + "bufferViews" : [ + { + "buffer" : 0, + "byteLength" : 6, + "byteOffset" : 0, + "target" : 34963 + }, + { + "buffer" : 0, + "byteLength" : 48, + "byteOffset" : 8, + "target" : 34962 + }, + { + "buffer" : 0, + "byteLength" : 48, + "byteOffset" : 56, + "target" : 34962 + }, + { + "buffer" : 0, + "byteLength" : 32, + "byteOffset" : 104, + "target" : 34962 + }, + { + "buffer" : 0, + "byteLength" : 6, + "byteOffset" : 136, + "target" : 34963 + }, + { + "buffer" : 0, + "byteLength" : 48, + "byteOffset" : 144, + "target" : 34962 + }, + { + "buffer" : 0, + "byteLength" : 48, + "byteOffset" : 192, + "target" : 34962 + }, + { + "buffer" : 0, + "byteLength" : 32, + "byteOffset" : 240, + "target" : 34962 + }, + { + "buffer" : 0, + "byteLength" : 6, + "byteOffset" : 272, + "target" : 34963 + }, + { + "buffer" : 0, + "byteLength" : 48, + "byteOffset" : 280, + "target" : 34962 + }, + { + "buffer" : 0, + "byteLength" : 48, + "byteOffset" : 328, + "target" : 34962 + }, + { + "buffer" : 0, + "byteLength" : 32, + "byteOffset" : 376, + "target" : 34962 + }, + { + "buffer" : 0, + "byteLength" : 6, + "byteOffset" : 408, + "target" : 34963 + }, + { + "buffer" : 0, + "byteLength" : 48, + "byteOffset" : 416, + "target" : 34962 + }, + { + "buffer" : 0, + "byteLength" : 48, + "byteOffset" : 464, + "target" : 34962 + }, + { + "buffer" : 0, + "byteLength" : 6, + "byteOffset" : 512, + "target" : 34963 + }, + { + "buffer" : 0, + "byteLength" : 48, + "byteOffset" : 520, + "target" : 34962 + }, + { + "buffer" : 0, + "byteLength" : 48, + "byteOffset" : 568, + "target" : 34962 + }, + { + "buffer" : 0, + "byteLength" : 32, + "byteOffset" : 616, + "target" : 34962 + } + ], + "buffers" : [ + { + "byteLength" : 648, + "uri" : "data:application/octet-stream;base64,AAECAwEAAACamZk/2sxMPuySX7PAzEw+mZmZP9gWK7TKzEw+0MxMPuySX7OYmZk/m5mZP9gWK7QAAMCoO2TmMwAAgD8AAMCoO2TmMwAAgD8AAMCoO2TmMwAAgD8AAMCoO2TmMwAAgD8AAIA/zMzMPpqZGT8AAAAAmpkZP8zMzD4AAIA/AAAAAAABAgMBAAAA0cxMvsnMTD7okl+zm5mZv5iZmT/aFiu0mZmZv7zMTD7ZTgc03sxMvpqZmT82JbW0kDM/NNoymTQAAIA/kDM/NNoymTQAAIA/kDM/NNoymTQAAIA/kDM/NNoymTQAAIA/y8zMPszMzD7a+qkzAAAAANr6qTPMzMw+y8zMPgAAAAAAAQIDAQAAAJuZmT+YmZm/5hANNdPMTD7HzEy+rlSFM+bMTD6amZm/Boi6NJmZmT+0zEy+8u6ANJQzP7TWMpk0AACAP5QzP7TWMpk0AACAP5QzP7TWMpk0AACAP5QzP7TWMpk0AACAP/3/fz8AAIA/m5kZP5iZGT+cmRk/AACAP/7/fz+YmRk/AAECAAMBAAABAIC//f9/P9JpV70BAIA//f9/v6ppV739/3+/AQCAv6ppV739/38/AQCAP9JpV70CAEAoAQCgswAAgL8CAEAoAQCgswAAgL8CAEAoAQCgswAAgL8CAEAoAQCgswAAgL8AAQIDAQAAALjMTL6ZmZm/5hANNZqZmb/izEy+uFSFM5iZmb+bmZm/5hANNcjMTL7SzEy+slSFMwAAwKmhzPg0AACAPwAAwKmhzPg0AACAPwAAwKmhzPg0AACAPwAAwKmhzPg0AACAP9DMzD7//38/AACAM5qZGT8AAAAA//9/P83MzD6amRk/" + } + ], + "images" : [ + { + "uri" : "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAgAAAAIACAYAAAD0eNT6AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH4QYcDhkW4QlOQwAAHBNJREFUeNrt3XuMlNX9P/DP4u7OLkshVEGkgKyVWzTNsloTbYtGaIgmRGM1tRq1TbVSaqm2qdREwbSJoQlQGm9NiNSmCSyRRhNtm0YTTUyq1jWhtFDF2lKrqcKuCsJegfP74/vbDbC3mZ2Zvcy8Xslkk5lnn3l2zjPn8z7nuWxFSikFAFBWJvgIAEAAAAAEAABAAAAABAAAQAAAAAQAAEAAAAAEAABg9FRmu2BFRUVWy7mxIAAUXqHrcOVY/kOECQBKvWiPVq2rLPUPV4gAQH0pwQBQzAYWHgD08aWq0u5R2J1KaADQ7woADLrj2mkBfaO+UQCg3y+DLwKgP0MA4JQvlC8ToE9iuNwIqIS+hNleIwqgn0EAKPFU7ssK6EPot41TgedsCnmnokLcQCGf6ziHc/lILmepZnPyy2DH0Pqbeut5LqUUFRUVpuSAvPrznr6kv35msD4pm/4sl75xOP1uPn18IepLIWtdtusyA0BRdhZAH0LpcBKgLyyAfkUAwJcSQN8jAOCLBqC/EgDwZQHQ5wkA2MEB9KMCgJ0QAH21AGDHAEB9EAA0DgACxDgNAIW66xEAkFvdLHQNdidAAChDAgAACAAAgAAAAAgAAIAAAAAIAACAAAAAjFk53QgomxsMuFkQAORmNGqnGQAAKEMCAAAIAACAAAAACAAAgAAAAAgAAIAAAACMWZW5/sJQNytwkx8AyE0hbrSXa/01AwAAZUgAAAABAAAQAAAAAQAASklFRUVW/4lPAGDEHTt2LNatWxf19fWRyWRizpw5PhQg74KX7WO0ty+TycTnPve5uP7666O5uXlUC3iphYWKlON1A6N9GWCuH/5IX5bYs32Fet/169fHfffd1+dvKvT7AOUTAMZDH9qfqqqqeOaZZ+Lqq68uWJ+by++Pdr876pcBppQGfYy1NDnePfnkkxERsXXr1ujo6FDwgbz0129n89pobWdHR0f8/e9/j69//evR3d3d74CoVPrFoernUPU3VxPsvGPb/v37o6qqKr75zW9GJpPRewEjpru7OzZt2hSNjY1RV1cXdXV10djYGJs3b45jx471W7w+/PDDWLlyZcyYMSNqa2vjS1/6Urz22mvD3oZMJhMXXHBBPPLIIxERsW/fvn7f92Tt7e2xdu3aqK+vj6qqqpg7d2488MADMWnSpAEHou+++27ceuutMXXq1JgxY0bcdddd0dHR0e/ou2QGtqnAImLQRzEMtO6urq60cePGtHjx4jRx4sQ0ceLEtHjx4vSLX/widXd397uODz74IN15553p7LPPTjU1Nemyyy5Lr776at7bcrqdO3emZcuWpalTp6aqqqp07rnnptWrV6eWlpZBP8uhPmOAQvShXV1dadmyZQP2NcuXLz+lH+15fsqUKX2WraurS2+//XZefeg//vGPFBGpvr5+0OW7urrSV77ylaz7yZ7nzjzzzD7LrVu3LqvaNl7rZ8kGgLG2857sjjvuGHC75s+fnz755BMBABjVALBhw4YUEWn69OmpqakptbS0pJaWlrRt27Y0bdq0FBFp06ZNfdZx/fXXp1dffTW1t7en3bt3p8bGxhQR6dvf/vawtuXQoUPpxRdf7F3P2rVrB13+l7/8Ze92P/300+nw4cPp4MGDaefOnYMGgMsvvzzt2rUrHTp0KK1ZsyZFRJo3b96wBngCwCgHgLGy857uySefTBGRZs2alXbs2JEOHDiQ2traUnNzc7riiitSRKT77rtvyPUp+EAx+9CGhoYUEempp57qs3xTU1OKiLR48eIh+6SXX36535H7cGrIddddlzo6Ogbd9osvvjhFRNq+fXtWf2fPc8ePH+997sMPP0wRkTKZjAAwHgPAaO+8A7n00ktTRKTm5uY+r/33v/9NEZEWLVokAACjGgBqa2tTRKTW1tY+y7e0tKSISBMnThyyT/r0009TRKTq6uq8asj69euz2va6uroUEengwYM5BYCTdXd3Z73seK6fJXsfgLfeeisiIq688so+ry1btuyUZQbT0NAQERHvv/9+QbZr9+7dERFx8cUX9zmRZPbs2RER8e9//9vZR8CYOfE6m+cG0nMiXVVV1bBO+H700UcjImLz5s2xf//+IX+vq6srIiJqa2uH/TdXVlaWRdtOsPMWZ+cdyIkTJ7J+T4DRMn/+/IiIeP755/u89sILL0RExIIFC4Zcz0svvRQREYsWLRrWdqxatSruueee+OCDD+Kqq66Kjz76aNDlZ86cecpgqxg6OzvLNwCM5HWK433nPd3ChQsjIuKdd94pyOdUKjsiMLbccsstERGxevXqaGpqitbW1mhtbY2mpqZYvXr1Kcuc7Pe//3188sknceTIkXjuued6l73pppuGvS0bNmyIa6+9Nt5888245pprBu33emZ977777tizZ08cPXo0mpub47bbbsv7M+kJFw899FC0tbUVZcCahnmfneG+YUGPU4y1M1inTZuWtm/f3nsS4Pbt2wc9CfC5555LH3/8cfr000/Ts88+m84555w+y+ZzDsBjjz2WIiLNnj07PfHEE+k///lPam9vT21tbWnPnj3p0UcfTRdddNGQ65s5c2bvGbFHjx51EBMoaB/a1dWVli5dmvOVVP09LrvsstTZ2ZlXH3r06NHeE/xuuOGGdOLEiX6X37dvX5o0aVKfbaiurs7puH5/z69cuXJU616ha2/JBoDR3nkHehw/fjx961vfyvpkj4E+19HeEYHSDgA9/ejGjRtTQ0NDqq2tTbW1tamhoSFt2rRpwHuprFmzJn3+859PmUwmzZo1K/34xz9OR44cyXtbUkrpf//7X5ozZ06KiHT33XcPuPzrr7+elixZkmpqatLkyZPTihUr0htvvJEiItXU1Aw7ABw5ciTde++96bzzzkuZTCZNmTIlXXLJJeM2AOT8vwB6DgHkcsy92Aa6P3N3d3c8/PDD8dvf/rb3hL8FCxbErbfeGt///vdPOdGjZx1r1qyJnTt3xnvvvRfTpk2Lb3zjG7Fu3bqoq6vL+7M5eRv/+Mc/xhNPPBGvvfZaHDhwICoqKqK+vj6WLl0aN954Y3z5y18e9G87evRo/PSnP42dO3fG+++/HzU1NbFgwYK87rgFUOh+eKzYs2dPXHjhhTFv3rw+dxMcb59xoWpvSQSActh5AfShuevu7o69e/fGqlWr4s9//nPcdddd8fDDDwsAAoAAAFBqfehANWrGjBnxxhtv9J7MV+4BYILdFoBSsmLFipg9e3bU1tZGdXV1zJ07N+688854/fXXx23xL0qgSAWOa+N1dsAMAAClNsofTKWPe+yHEwAoNIcAAEAAAAAEAABAAAAABAAAYJwa9lUAA12q4Gx6ABiewWpooeuuGQAAKEMCAAAIAACAAAAACAAAQGkY9lUAA5116OoAABi+kaqjZgAAoAwJAAAgAAAAAgAAIAAAAKWhMp9f7u9MRWf7A8Dw5XKVXT411wwAAJQhAQAABAAAQAAAAEpSXicB9nfygRMDASA/I1FLzQAAQBkSAABAAAAABAAAoCRV5ruC009UcMIfAOQnm5Ps8623ZgAAoAwJAAAgAAAA5SDvcwBOPwbhnAAAyF+x66kZAAAoQwIAAAgAAEA5qCzESk4+TuGYPwDkb7Bz7ApRa80AAEAZEgAAoAwV5BDAyVMRDgcAQGEUs6aaAQCAMiQAAEAZqizUinqmKUz7A0Bh9HeIvVB11gwAAJgByD+lmAkAgMIpVl01AwAAZgDyTylG/gBQOCfPsBeyxk4o9Eae/u8LAYCxN8CeMNY3EADMAhR+gF2RVGwAKDtOAgQAAQAAEAAAAAEAABAAAAABAAAQAAAAAQAAEAAAAAEAABAAAAABAAAQAAAAAQAAEAAAAAEAABAAAAABAAAEAABAAAAABAAAQAAAAAQAAEAAAAAEAABAAAAABAAAQAAAAAQAAEAAAAAEAABAAAAABAAAQAAAAAQAABAAAAABAAAQAAAAAQAAEAAAAAEAABAAAAABAAAQAAAAAQAAEAAAAAEAABAAAAABAAAQAAAAAQAAEAAAQAAAAAQAAEAAAAAEAABAAAAABAAAQAAAAAQAAEAAAAAEAABAAAAAiqTSRwBDq6io6Pf5lJIPR7uAGQAolwKT6zJoFxAAYBwVmWxGkiklxUa7gAAApSLbApJtQUK7gAAARppoFxAAwEgT7QICABhpol1AAAAjTbQLCABgpKldtAsIAGCkqV20CwgAYKSpXbQLCABgpKldAAEAjDS1CyAAgJGmdgEBAMpg5Jjrz1xHmrn+RLuAAABFLjI9BSHXn6O5bu2iXaBo379kjgyyHqX2N8pEu4AAAOOoSIwV5foV1C4wuhwCAAABAAAQAAAAAQAAEAAAgHHKVQCQzRfF5WbaBcwAwPgtFMW4M1wx161dtAsIAJCH4d4RLpdbzhZj3dpFu0DRArhDADD4KHKw28MqGtoFzABAiRaZbEeaaBcQAKAE+Lez2gUEADDSNNLULiAAgJGmkaZ2AQEAjDSNNLULCABgpIl2AQEAjDTRLiAAgJEm2gUEADDSRLuAAABGmmgXEADASBPtAgIAGGmiXUAAgBEpNoVYBu0CY43/BggAZgAAAAEAABAAAAABAAAQAAAAAQAAEAAAAAEAABAAAAABAAAQAAAAAQAAEAAAAAEAABAAAAABAAAQAABAAAAABAAAQAAAAAQAAEAAAAAEAABAAAAABAAAQAAAAAQAAEAAAAAEAABAAAAABAAAQAAAAAQAAEAAAAABAAAQAAAAAQAAEAAAAAEAABAAAAABAAAQAAAAAQAAEAAAAAEAABAAAAABAAAQAAAAAQAAEAAAAAEAAAQAAEAAAAAEAABAAAAABAAAQAAAAAQAAEAAAAAEAABAAAAARkaljwCGVlFR0e/zKSUfjnYBMwBQLgUm12XQLiAAwDgqMtmMJFNKio12AQEASkW2BSTbgoR2AQEAjDTRLiAAgJEm2gUEADDSRLuAAABGmmgXEADASFO7aBcQAMBIU7toFxAAwEhTu2gXEADASFO7AAIAGGlqF0AAACNN7QICAJTByDHXn7mONHP9iXYBAQCKXGR6CkKuP0dz3dpFu0DRvn/JHBlkPUrtb5SJdgEBAMZRkRgryvUrqF1gdDkEAAACAAAgAAAAAgAAIAAAAOOUqwAgmy+Ky820C5gBgPFbKIpxZ7hirlu7aBcQACAPw70jXC63nC3GurWLdoGiBXCHAGDwUeRgt4dVNLQLmAGAEi0y2Y400S4gAEAJ8G9ntQsIAGCkaaSpXUAAACNNI03tAgIAGGkaaWoXEADASBPtAgIAGGmiXUAAACNNtAsIAGCkiXYBAQCMNNEuIACAkSbaBQQAMNJEu4AAACNSbAqxDNoFxhr/DRAAzAAAAAIAACAAAAACAAAgAAAAAgAAIAAAAAIAACAAAAACAAAgAAAAAgAAIAAAAAIAACAAAAACAAAgAACAAAAACAAAgAAAAAgAAIAAAAAIAACAAAAACAAAgAAAAAgAAIAAAAAIAACAAAAACAAAgAAAAAgAAIAAAAACAAAgAAAAAgAAIAAAAAIAACAAAAACAAAgAAAAAgAAIAAAAAIAACAAAAACAAAgAAAAAgAAIAAAAAIAAAgAAIAAAAAIAACAAAAACAAAgAAAAAgAAIAAAAAIAACAAAAACAAAgAAAAIzJAFBRUeETBYAiKHSNLWgASCkJAQBQhOKfUhrbMwCF3kAAKHfFGGBXFmsDBQEAKMzguhh11UmAAFCGCjYDYOQPAIXXU1cLXWfNAACAGYDCJRSzAQCQn2LWVDMAAFCGBAAAKEMFOQRg2h8ACu/kmlroWmsGAADKkAAAAGWoIIcABpqiOP01ACA7xa6nZgAAoAwJAAAgAAAA5SDvcwAc8weAwju9nha63poBAIAyJAAAgAAAAJSDvM8BGOoYRX/LAAADG4laagYAAMqQAAAAAgAAIAAAACUpr5MAnfAHAIXXXy0tdM01AwAAZUgAAAABAAAQAACAkpTXSYDZnqQw0LIAwOjUUTMAAFCGBAAAEAAAAAFgDKqoqDjlUVNTE+eff3786Ec/ikOHDuW93lxfA0AfPS7bKhX4rIJin7wwWCNfc8018cwzz+S13sFObHQiI4A+erQ+wzFzEuDpKa/nkVLq91FoKaU4ceJEfPrpp/H4449HRMSf/vQn3z6AMUAfnd9n199joLo74gFgrKSkSZMmxc033xwREdOnTz/l9e7u7ti0aVM0NjZGXV1d1NXVRWNjY2zevDmOHTvWb9oa7MPt7/ls3+P0dezevTuuvfbamDx5ckyePDluuumm+Pjjj+Oll16K5cuXx2c+85mYMWNGrFy5Mtrb230jAH20PrrgSWNYIqLfR7Gd/j6HDx9O999/f4qItGXLlt7nu7q60rJlywbczuXLl6fu7u5B/5ahHrm8x+nbP2HChD7Lz507t9/13H///QlgPNBHF/+zLVTdHbcB4PRHY2Njev/993uX27BhQ4qINH369NTU1JRaWlpSS0tL2rZtW5o2bVqKiLRp06YBd9rBdujhvsfJ61qyZEnatWtX6ujoSA8++GC/z69duzZFRDr//PP1KsC4CgD6aAFgxD6AiEhTp05Nu3btSiml1NDQkCIiPfXUU33W0dTUlCIiLV68OK+dK9f3OHldx48f733uwIEDKSJSVVXVKc9/+OGHKSJSJpPRqwDjOgDoowWAgk8vdXV1pf3796fbb7+9d0onpZRqa2tTRKTW1tY+62hpaUkRkSZOnJjXzpXrewy0rmPHjuX0PMBYDwD66LEfACbkce5ATmcpFusazaqqqjj33HNj48aNERHx6quvDnnZRCrwVQn5vscZZ5yR0/MA44U+OvcTJ0fqKruSuRPg4cOHT2nU+fPnR0TE888/32fZF154ISIiFixY0Oe1zs7OAd/j9NeG+x4A5UYfPfaM+wDQ1dUVu3fvjttvvz0iIpYsWRIREbfccktERKxevTqampqitbU1Wltbo6mpKVavXn3KMhERM2fOjIiIhx56KNra2k55j4Fey/U9AMqNPnoMG8kTQIq9/smTJ6e//e1vvcedli5dmvXlHytXrhxwmwd6Ldf3GOxYVa7PA4y3kwD10aNfQwtyEuBYCQBnnHFGOuecc9LNN9+c3n777VOW7erqShs3bkwNDQ2ptrY21dbWpoaGhrRp06Y+jX7kyJF07733pvPOOy9lMpk0ZcqUdMkllwz5Wi7vIQAA5RYA9NFjNwCM2P8COPnYDwAwujXUvwMGgDJUaZQPAGPDYDW00LXXDAAAlCEBAAAEAABAAAAABAAAQAAoCceOHYt169ZFfX19ZDKZmDNnjr0CoAwV8x/Xjcm/dyRvBBSR/2WCPesv1GavX78+7rvvvj7bWOj3ASC/elJdXR1nnXVWXHrppfGTn/wkLr744oLWh1x+vxg1otj1UwA4zcKFC+Ott96KrVu3xk033RSZTKZojQtAYepJVVVVPPPMM3H11VcLAALA8NTU1MSJEyeis7PzlG0XAADGRgDo6Yc7Ozvjn//8Z/zsZz+LHTt2xBe+8IX461//WrT3K/UAULLnAPzud7+Lr371q/HZz342qqurY+7cufGDH/wgWltbT/mwOzs7o7u7OyZMmND74Z8eBE5+ADA6MplMXHDBBfHII49ERMS+ffv6FNDT++n29vZYu3Zt1NfXR1VVVcydOzceeOCBmDRp0oB9+rvvvhu33nprTJ06NWbMmBF33XVXdHR09Fuox3ONKMkZgO985zuxZcuWfl+bP39+/OUvf4kpU6b0u60nH/8fiQQGQG79/ZtvvhmLFi2K+vr6+Ne//jXg8t3d3bF06dJ4+eWXs+rTe37/zDPPPGWwGBGxbt26ePDBB4esc/nUCDMAefrNb34TW7ZsiVmzZsWOHTviwIED0dbWFs3NzXHFFVfEvn374uc//3mfD/P//2vkAZ8/+XUARt7hw4fjpZdeiptvvjkiIm655ZZBl3/88cfj5ZdfjunTp8fTTz8dhw8fjoMHD8bOnTsH/b0LL7wwdu3aFYcOHYo1a9ZERMS2bdv6LcTjuUaU3AzAZZddFq+88ko0NzfHRRdddMpr7733XsyePTsWLVoUe/fuHXR9zgEAGBszAP257rrrYtu2bb0nbvfXb3/xi1+M5ubm2L59e9x4441D9vE9zx0/fjwmTPi/8fGBAwfi7LPPjkwm0+9hACcBjqEAMGnSpDh69Oig66ipqYn29nYBAGAcBoD169f3jswH67d76sHBgwfjrLPOyjoAnPzcsWPHoqqqKqtlx1sAmDCcDRzscfp0yEhPj5w4cWLIZU5OcQCMbT3149FHH42IiM2bN8f+/fuH/L2urq6IiKitrR32e1dWVo743znQY6j6W/QAMNYtXLgwIiLeeeedggSRzs5O3z6AMWDVqlVxzz33xAcffBBXXXVVfPTRR4MuP3PmzIiI2L17d9G2aTzXiJILAHfccUdERFxxxRWxdevWePfdd6OjoyPa29tj79698dhjj/W5e9RgO85DDz0UbW1tvnkAY8CGDRvi2muvjTfffDOuueaaQQvwlVdeGRERd999d+zZsyeOHj0azc3Ncdttt+W9HaVQI3I+B2Ckj1Hk+v7Hjx+P22+/PX79619ntZ0DHcf57ne/G7/61a9G/O8DIAbtn9va2uLyyy+P5ubmuOGGG2LHjh2nTIP3LP/2229HY2NjHDly5JTfr66u7j08kM1x/f6eH40aUej6W3IzABMmTIitW7fGH/7wh/ja174Ws2bNiurq6shkMrFw4cL43ve+N+g1oSenzHvvvTfOO++8yGQyMWXKlLjkkkt8IwFG2cSJE+PZZ5+NOXPmxFNPPRU//OEP+11u3rx58eKLL8aSJUuipqYmJk+eHCtWrIhXXnklIv7vhPB8ZiLGe40YdzMAAJCPPXv2xIUXXhjz5s3rczfB8TAjUqj6W2lXAKAcdHd3x969e2PVqlUREbF8+fKy/jzMAABQukVugJo1Y8aMeOONN3pP5ivHGYCczwHI9zpF/1AHgJGyYsWKmD17dtTW1vb+Y7g777wzXn/99TFV/LOpnYW+z86I3wnQLAEAjH7tnOBjB4DyIwAAgAAAAAgAAIAAAAAIAACAAAAAjBc53QrYNf4AUHjZ1M5C12AzAABQhgQAABAAAAABAAAQAAAAAQAAEAAAAAEAABizcroRUKFuVJDtugCg1I1W3awc7x+KIAGAGlViAWAkGkiAAFDAy7E+VNoFhrdzCA4A+moBgCF3RDshgH5UAGDAndwODujzEADo84XxZQH0VwgAvmy+aIC+h2FxI6AS/GJme00pgH5FAKDEUzqAPoSTVRZ6R8h2OqhQN1DI9zrO4V4+kutZqtme/DLUMbSBpt56nu95rqKiIlJKvT8Bci3+p/chp/czg/VJ2fRnufSNw+l38+njC1FfClnrilGHzQCUqJ4dQPEH9CHkNQPA+PiyAuhnEAB8AQH0SQgAvkwA+jMEAF8EAH2jAICdFkC/KwDYoQDQxwsAGhcA4UEA8MECwLiudRVJJQaAsuNOgAAgAAAAAgAAIAAAAAIAACAAAAACAAAgAAAAAgAAMIr+HyP6AtxN3EzKAAAAAElFTkSuQmCC" + } + ], + "materials" : [ + { + "name" : "BackPlaneMat", + "doubleSided": true, + "pbrMetallicRoughness" : { + "baseColorFactor" : [ + 0.16000001668930075, + 0.16000001668930075, + 0.16000001668930075, + 1.0 + ], + "metallicFactor" : 0.0 + } + }, + { + "name" : "BottomLeftMat", + "doubleSided": true, + "pbrMetallicRoughness" : { + "baseColorFactor" : [ + 0.0, + 0.16000000476837162, + 0.800000011920929, + 1.0 + ], + "baseColorTexture" : { + "index" : 0 + }, + "metallicFactor" : 0.0 + } + }, + { + "name" : "BottomRightMat", + "doubleSided": true, + "pbrMetallicRoughness" : { + "baseColorFactor" : [ + 0.0, + 0.800000011920929, + 0.0, + 1.0 + ], + "baseColorTexture" : { + "index" : 0 + }, + "metallicFactor" : 0.0 + } + }, + { + "name" : "TopLeftMat", + "doubleSided": true, + "pbrMetallicRoughness" : { + "baseColorFactor" : [ + 0.800000011920929, + 0.800000011920929, + 0.0, + 1.0 + ], + "baseColorTexture" : { + "index" : 0 + }, + "metallicFactor" : 0.0 + } + }, + { + "name" : "TopRightMat", + "doubleSided": true, + "pbrMetallicRoughness" : { + "baseColorFactor" : [ + 0.800000011920929, + 0.08000000238418581, + 0.0, + 1.0 + ], + "baseColorTexture" : { + "index" : 0 + }, + "metallicFactor" : 0.0 + } + } + ], + "meshes" : [ + { + "name" : "TopRightMesh", + "primitives" : [ + { + "attributes" : { + "NORMAL" : 2, + "POSITION" : 1, + "TEXCOORD_1" : 3 + }, + "indices" : 0, + "material" : 4 + } + ] + }, + { + "name" : "TopLeftMesh", + "primitives" : [ + { + "attributes" : { + "NORMAL" : 6, + "POSITION" : 5, + "TEXCOORD_0" : 7 + }, + "indices" : 4, + "material" : 3 + } + ] + }, + { + "name" : "BottomRightMesh", + "primitives" : [ + { + "attributes" : { + "NORMAL" : 10, + "POSITION" : 9, + "TEXCOORD_0" : 11 + }, + "indices" : 8, + "material" : 2 + } + ] + }, + { + "name" : "BackPlaneMesh", + "primitives" : [ + { + "attributes" : { + "NORMAL" : 14, + "POSITION" : 13 + }, + "indices" : 12, + "material" : 0 + } + ] + }, + { + "name" : "BottomLeftMesh", + "primitives" : [ + { + "attributes" : { + "NORMAL" : 17, + "POSITION" : 16, + "TEXCOORD_0" : 18 + }, + "indices" : 15, + "material" : 1 + } + ] + } + ], + "nodes" : [ + { + "mesh" : 3, + "name" : "BackPlane" + }, + { + "mesh" : 4, + "name" : "BottomLeftObj" + }, + { + "mesh" : 2, + "name" : "BottomRightObj" + }, + { + "mesh" : 1, + "name" : "TopLeftObj" + }, + { + "mesh" : 0, + "name" : "TopRightObj" + } + ], + "samplers" : [ + {} + ], + "scene" : 0, + "scenes" : [ + { + "name" : "Scene", + "nodes" : [ + 0, + 2, + 1, + 4, + 3 + ] + } + ], + "textures" : [ + { + "sampler" : 0, + "source" : 0 + } + ] +} diff --git a/test/unit/Common/utAssertHandler.cpp b/test/unit/Common/utAssertHandler.cpp new file mode 100644 index 000000000..4a567c0c3 --- /dev/null +++ b/test/unit/Common/utAssertHandler.cpp @@ -0,0 +1,110 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2020, 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 "UnitTestPCH.h" + +/// Ensure this test has asserts on, even if the build type doesn't have asserts by default. +#if !defined(ASSIMP_BUILD_DEBUG) +#define ASSIMP_BUILD_DEBUG +#endif + +#include +#include + +namespace +{ + /// An exception which is thrown by the testAssertHandler + struct TestAssertException + { + TestAssertException(const char* failedExpression, const char* file, int line) + : m_failedExpression(failedExpression) + , m_file(file) + , m_line(line) + { + } + + std::string m_failedExpression; + std::string m_file; + int m_line; + }; + + /// Swap the default handler, which aborts, by one which throws. + void testAssertHandler(const char* failedExpression, const char* file, int line) + { + throw TestAssertException(failedExpression, file, line); + } + + /// Ensure that the default assert handler is restored after the test is finished. + struct ReplaceHandlerScope + { + ReplaceHandlerScope() + { + Assimp::setAiAssertHandler(testAssertHandler); + } + + ~ReplaceHandlerScope() + { + Assimp::setAiAssertHandler(Assimp::defaultAiAssertHandler); + } + }; +} + +TEST(utAssertHandler, replaceWithThrow) +{ + ReplaceHandlerScope scope; + + try + { + ai_assert((2 + 2 == 5) && "Sometimes people put messages here"); + EXPECT_TRUE(false); + } + catch(const TestAssertException& e) + { + EXPECT_STREQ(e.m_failedExpression.c_str(), "(2 + 2 == 5) && \"Sometimes people put messages here\""); + EXPECT_STREQ(e.m_file.c_str(), __FILE__); + EXPECT_GT(e.m_line, 0); + EXPECT_LT(e.m_line, __LINE__); + } + catch(...) + { + EXPECT_TRUE(false); + } +} diff --git a/test/unit/utFindInvalidData.cpp b/test/unit/utFindInvalidData.cpp index e7dc123bb..17a9c0379 100644 --- a/test/unit/utFindInvalidData.cpp +++ b/test/unit/utFindInvalidData.cpp @@ -106,8 +106,10 @@ void utFindInvalidDataProcess::TearDown() { // ------------------------------------------------------------------------------------------------ TEST_F(utFindInvalidDataProcess, testStepNegativeResult) { - ::memset(mMesh->mNormals, 0, mMesh->mNumVertices * sizeof(aiVector3D)); - ::memset(mMesh->mBitangents, 0, mMesh->mNumVertices * sizeof(aiVector3D)); + for ( size_t i=0; imNumVertices; ++i ) { + mMesh->mNormals[i].x = mMesh->mNormals[i].y = mMesh->mNormals[i].z =0; + mMesh->mBitangents[i].x = mMesh->mBitangents[i].y = mMesh->mBitangents[i].z = 0; + } mMesh->mTextureCoords[2][455] = aiVector3D(std::numeric_limits::quiet_NaN()); diff --git a/test/unit/utMatrix3x3.cpp b/test/unit/utMatrix3x3.cpp index 50fa66c50..3905b1d35 100644 --- a/test/unit/utMatrix3x3.cpp +++ b/test/unit/utMatrix3x3.cpp @@ -73,9 +73,21 @@ TEST_F(utMatrix3x3Test, FromToMatrixTest) { aiVector3D from, to; + auto random_ratio = []() -> float { + return static_cast(rand()) / static_cast(RAND_MAX); + }; + for (int i = 0; i < NUM_SAMPLES; ++i) { - from = aiVector3D(1.f * rand() / RAND_MAX, 1.f * rand() / RAND_MAX, 1.f * rand() / RAND_MAX).Normalize(); - to = aiVector3D(1.f * rand() / RAND_MAX, 1.f * rand() / RAND_MAX, 1.f * rand() / RAND_MAX).Normalize(); + from = aiVector3D( + 1.f * random_ratio(), + 1.f * random_ratio(), + 1.f * random_ratio()) + .Normalize(); + to = aiVector3D( + 1.f * random_ratio(), + 1.f * random_ratio(), + 1.f * random_ratio()) + .Normalize(); aiMatrix3x3::FromToMatrix(from, to, trafo); res = trafo * from; diff --git a/test/unit/utMetadata.cpp b/test/unit/utMetadata.cpp index a605107db..81ab61435 100644 --- a/test/unit/utMetadata.cpp +++ b/test/unit/utMetadata.cpp @@ -197,9 +197,11 @@ TEST_F( utMetadata, copy_test ) { m_data->Set( 5, "aiString", strVal ); aiVector3D vecVal( 1, 2, 3 ); m_data->Set( 6, "aiVector3D", vecVal ); + aiMetadata metaVal; + m_data->Set( 7, "aiMetadata", metaVal ); aiMetadata copy( *m_data ); - EXPECT_EQ( 7u, copy.mNumProperties ); + EXPECT_EQ( 8u, copy.mNumProperties ); // bool test { @@ -251,4 +253,11 @@ TEST_F( utMetadata, copy_test ) { EXPECT_TRUE( copy.Get( "aiVector3D", v ) ); EXPECT_EQ( vecVal, v ); } + + // metadata test + { + aiMetadata v; + EXPECT_TRUE( copy.Get( "aiMetadata", v ) ); + EXPECT_EQ( metaVal, v ); + } } diff --git a/test/unit/utRemoveComponent.cpp b/test/unit/utRemoveComponent.cpp index d3c102cfb..622a582d6 100644 --- a/test/unit/utRemoveComponent.cpp +++ b/test/unit/utRemoveComponent.cpp @@ -98,13 +98,6 @@ void RemoveVCProcessTest::SetUp() { pScene->mCameras = new aiCamera *[pScene->mNumCameras = 2]; pScene->mCameras[0] = new aiCamera(); pScene->mCameras[1] = new aiCamera(); - - // COMPILE TEST: aiMaterial may no add any extra members, - // so we don't need a virtual destructor - char check[sizeof(aiMaterial) == sizeof(aiMaterial) ? 10 : -1]; - check[0] = 0; - // to remove compiler warning - EXPECT_EQ(0, check[0]); } // ------------------------------------------------------------------------------------------------ diff --git a/test/unit/utglTF2ImportExport.cpp b/test/unit/utglTF2ImportExport.cpp index f0f18d503..6791d5f89 100644 --- a/test/unit/utglTF2ImportExport.cpp +++ b/test/unit/utglTF2ImportExport.cpp @@ -534,3 +534,10 @@ TEST_F(utglTF2ImportExport, norootnode_scenewithoutnodes) { ASSERT_NE(scene, nullptr); ASSERT_NE(scene->mRootNode, nullptr); } + +// Shall not crash! +TEST_F(utglTF2ImportExport, norootnode_issue_3269) { + Assimp::Importer importer; + const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/glTF2/issue_3269/texcoord_crash.gltf", aiProcess_ValidateDataStructure); + ASSERT_EQ(scene, nullptr); +} diff --git a/tools/assimp_view/Display.cpp b/tools/assimp_view/Display.cpp index 9fa157c41..1f6bb89eb 100644 --- a/tools/assimp_view/Display.cpp +++ b/tools/assimp_view/Display.cpp @@ -462,7 +462,7 @@ int CDisplay::AddTextureToDisplayList(unsigned int iType, TVINSERTSTRUCT sNew; tvi.pszText = chTemp; tvi.cchTextMax = (int)strlen(chTemp); - tvi.mask = TVIF_TEXT | TVIF_SELECTEDIMAGE | TVIF_IMAGE | TVIF_HANDLE | TVIF_HANDLE; + tvi.mask = TVIF_TEXT | TVIF_SELECTEDIMAGE | TVIF_IMAGE | TVIF_HANDLE; tvi.lParam = (LPARAM)20; // find out whether this is the default texture or not