diff --git a/code/AMF/AMFImporter.cpp b/code/AMF/AMFImporter.cpp index 5bda49dd8..6ffbdf6f5 100644 --- a/code/AMF/AMFImporter.cpp +++ b/code/AMF/AMFImporter.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, @@ -90,9 +88,9 @@ void AMFImporter::Clear() { } AMFImporter::~AMFImporter() { - if (mReader != nullptr) { - delete mReader; - mReader = nullptr; + if (mXmlParser != nullptr) { + delete mXmlParser; + mXmlParser = nullptr; } // Clear() is accounting if data already is deleted. So, just check again if all data is deleted. @@ -106,7 +104,9 @@ AMFImporter::~AMFImporter() { 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; + if (pNodeElement != nullptr) { + *pNodeElement = ne; + } return true; } @@ -173,10 +173,9 @@ void AMFImporter::Throw_ID_NotFound(const std::string &pID) const { /************************************************************* Functions: XML set ************************************************************/ /*********************************************************************************************************************************************/ -void AMFImporter::XML_CheckNode_MustHaveChildren( XmlNode *node ) { - //if (mReader->isEmptyElement()) throw DeadlyImportError(std::string("Node <") + mReader->getNodeName() + "> must have children."); - if (node->getNode()->children().begin() == node->getNode()->children().end()) { - throw DeadlyImportError(std::string("Node <") + std::string(node->getNode()->name()) + "> must have children."); +void AMFImporter::XML_CheckNode_MustHaveChildren( XmlNode &node ) { + if (node.children().begin() == node.children().end()) { + throw DeadlyImportError(std::string("Node <") + std::string(node.name()) + "> must have children."); } } @@ -221,20 +220,23 @@ casu_cres: } } */ -bool AMFImporter::XML_SearchNode(const std::string &pNodeName) { - - mReader->while (mReader->read()) { - //if((mReader->getNodeType() == irr::io::EXN_ELEMENT) && XML_CheckNode_NameEqual(pNodeName)) return true; - if ((mReader->getNodeType() == pugi::node_element) && XML_CheckNode_NameEqual(pNodeName)) { - return true; - } - } +bool AMFImporter::XML_SearchNode(const std::string &nodeName) { + XmlNode *root = mXmlParser->getRootNode(); + if (nullptr == root) { + return false; + } - return false; + find_node_by_name_predicate predicate(nodeName); + XmlNode node = root->find_node(predicate); + if (node.empty()) { + return false; + } + + return true; } -bool AMFImporter::XML_ReadNode_GetAttrVal_AsBool(const int pAttrIdx) { - std::string val(mReader->getAttributeValue(pAttrIdx)); +bool AMFImporter::XML_ReadNode_GetAttrVal_AsBool (const int pAttrIdx) { + std::string val(mXmlParser->getAttributeValue(pAttrIdx)); if ((val == "false") || (val == "0")) return false; @@ -248,42 +250,42 @@ float AMFImporter::XML_ReadNode_GetAttrVal_AsFloat(const int pAttrIdx) { std::string val; float tvalf; - ParseHelper_FixTruncatedFloatString(mReader->getAttributeValue(pAttrIdx), val); + ParseHelper_FixTruncatedFloatString(mXmlParser->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)); + return strtoul10(mXmlParser->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."); + if (!mXmlParser->read()) throw DeadlyImportError("XML_ReadNode_GetVal_AsFloat. No data, seems file is corrupt."); + if (mXmlParser->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); + ParseHelper_FixTruncatedFloatString(mXmlParser->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."); + if (!mXmlParser->read()) throw DeadlyImportError("XML_ReadNode_GetVal_AsU32. No data, seems file is corrupt."); + if (mXmlParser->getNodeType() != irr::io::EXN_TEXT) throw DeadlyImportError("XML_ReadNode_GetVal_AsU32. Invalid type of XML element, seems file is corrupt."); - return strtoul10(mReader->getNodeData()); + return strtoul10(mXmlParser->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) + if (!mXmlParser->read()) throw DeadlyImportError("XML_ReadNode_GetVal_AsString. No data, seems file is corrupt."); + if (mXmlParser->getNodeType() != irr::io::EXN_TEXT) throw DeadlyImportError("XML_ReadNode_GetVal_AsString. Invalid type of XML element, seems file is corrupt."); - pValue = mReader->getNodeData(); + pValue = mXmlParser->getNodeData(); } /*********************************************************************************************************************************************/ @@ -383,8 +385,8 @@ void AMFImporter::ParseFile(const std::string &pFile, IOSystem *pIOHandler) { throw DeadlyImportError("Failed to open AMF file " + pFile + "."); } - mReader = new XmlParser; - XmlNode *root = mReader->parse(file.get()); + mXmlParser = new XmlParser; + XmlNode *root = mXmlParser->parse(file.get()); if (nullptr == root) { throw DeadlyImportError("Failed to create XML reader for file" + pFile + "."); } @@ -398,8 +400,8 @@ void AMFImporter::ParseFile(const std::string &pFile, IOSystem *pIOHandler) { ParseNode_Root(root); - delete mReader; - mReader = nullptr; + delete mXmlParser; + mXmlParser = nullptr; } // . MACRO_ATTRREAD_LOOPBEG; - MACRO_ATTRREAD_CHECK_RET("id", id, mReader->getAttributeValue); + MACRO_ATTRREAD_CHECK_RET("id", id, mXmlParser->getAttributeValue); MACRO_ATTRREAD_LOOPEND; // create and if needed - define new grouping object. @@ -512,7 +514,7 @@ void AMFImporter::ParseNode_Constellation() { if (!id.empty()) als.ID = id; // Check for child nodes - if (!mReader->isEmptyElement()) { + if (!mXmlParser->isEmptyElement()) { ParseHelper_Node_Enter(ne); MACRO_NODECHECK_LOOPBEGIN("constellation"); if (XML_CheckNode_NameEqual("instance")) { @@ -546,7 +548,7 @@ void AMFImporter::ParseNode_Instance() { // Read attributes for node . MACRO_ATTRREAD_LOOPBEG; - MACRO_ATTRREAD_CHECK_RET("objectid", objectid, mReader->getAttributeValue); + MACRO_ATTRREAD_CHECK_RET("objectid", objectid, mXmlParser->getAttributeValue); MACRO_ATTRREAD_LOOPEND; // used object id must be defined, check that. @@ -558,7 +560,7 @@ void AMFImporter::ParseNode_Instance() { als.ObjectID = objectid; // Check for child nodes - if (!mReader->isEmptyElement()) { + if (!mXmlParser->isEmptyElement()) { bool read_flag[6] = { false, false, false, false, false, false }; als.Delta.Set(0, 0, 0); @@ -625,7 +627,7 @@ void AMFImporter::ParseNode_Object(XmlNode *nodeInst) { ParseNode_Metadata(*it); } } - if (!mReader->isEmptyElement()) { + if (!mXmlParser->isEmptyElement()) { bool col_read = false; ParseHelper_Node_Enter(ne); @@ -682,10 +684,10 @@ void AMFImporter::ParseNode_Metadata() { // read attribute MACRO_ATTRREAD_LOOPBEG; - MACRO_ATTRREAD_CHECK_RET("type", type, mReader->getAttributeValue); + MACRO_ATTRREAD_CHECK_RET("type", type, mXmlParser->getAttributeValue); MACRO_ATTRREAD_LOOPEND; // and value of node. - value = mReader->getNodeData(); + value = mXmlParser->getNodeData(); // Create node element and assign read data. ne = new CAMFImporter_NodeElement_Metadata(mNodeElement_Cur); ((CAMFImporter_NodeElement_Metadata *)ne)->Type = type; diff --git a/code/AMF/AMFImporter.hpp b/code/AMF/AMFImporter.hpp index a2ab420f5..e6094c69e 100644 --- a/code/AMF/AMFImporter.hpp +++ b/code/AMF/AMFImporter.hpp @@ -63,8 +63,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. namespace Assimp { -class XmlNode; - /// \class AMFImporter /// Class that holding scene graph which include: geometry, metadata, materials etc. /// @@ -280,7 +278,7 @@ private: void Throw_ID_NotFound(const std::string& pID) const; /// Check if current node have children: .... If not then exception will thrown. - void XML_CheckNode_MustHaveChildren(XmlNode *node); + void XML_CheckNode_MustHaveChildren( XmlNode &node); /// Check if current node name is equal to pNodeName. /// \param [in] pNodeName - name for checking. @@ -345,49 +343,49 @@ private: void ParseHelper_Decode_Base64(const std::string& pInputBase64, std::vector& pOutputData) const; /// Parse node of the file. - void ParseNode_Root(XmlNode *root); + void ParseNode_Root(XmlNode &root); /// Parse node of the file. - void ParseNode_Constellation(XmlNode *node); + void ParseNode_Constellation(XmlNode &node); /// Parse node of the file. - void ParseNode_Instance(XmlNode *node); + void ParseNode_Instance(XmlNode &node); /// Parse node of the file. - void ParseNode_Material(XmlNode *node); + void ParseNode_Material(XmlNode &node); /// Parse node. - void ParseNode_Metadata(XmlNode *node); + void ParseNode_Metadata(XmlNode &node); /// Parse node of the file. - void ParseNode_Object(XmlNode *node); + void ParseNode_Object(XmlNode &node); /// Parse node of the file. - void ParseNode_Texture(XmlNode *node); + void ParseNode_Texture(XmlNode &node); /// Parse node of the file. - void ParseNode_Coordinates(XmlNode *node); + void ParseNode_Coordinates(XmlNode &node); /// Parse node of the file. - void ParseNode_Edge(XmlNode *node); + void ParseNode_Edge(XmlNode &node); /// Parse node of the file. - void ParseNode_Mesh(XmlNode *node); + void ParseNode_Mesh(XmlNode &node); /// Parse node of the file. - void ParseNode_Triangle(XmlNode *node); + void ParseNode_Triangle(XmlNode &node); /// Parse node of the file. - void ParseNode_Vertex(XmlNode *node); + void ParseNode_Vertex(XmlNode &node); /// Parse node of the file. - void ParseNode_Vertices(XmlNode *node); + void ParseNode_Vertices(XmlNode &node); /// Parse node of the file. - void ParseNode_Volume(XmlNode *node); + void ParseNode_Volume(XmlNode &node); /// Parse node of the file. - void ParseNode_Color(XmlNode *node); + void ParseNode_Color(XmlNode &node); /// Parse of node of the file. /// \param [in] pUseOldName - if true then use old name of node(and children) - , instead of new name - . @@ -397,7 +395,7 @@ public: /// Default constructor. AMFImporter() AI_NO_EXCEPT : mNodeElement_Cur(nullptr) - , mReader(nullptr) { + , mXmlParser(nullptr) { // empty } @@ -423,7 +421,7 @@ private: CAMFImporter_NodeElement* mNodeElement_Cur;///< Current element. std::list mNodeElement_List;///< All elements of scene graph. - XmlParser *mReader; + XmlParser *mXmlParser; //irr::io::IrrXMLReader* mReader;///< Pointer to XML-reader object std::string mUnit; std::list mMaterial_Converted;///< List of converted materials for postprocessing step. diff --git a/code/AMF/AMFImporter_Geometry.cpp b/code/AMF/AMFImporter_Geometry.cpp index 1cff1d761..d74eb71c4 100644 --- a/code/AMF/AMFImporter_Geometry.cpp +++ b/code/AMF/AMFImporter_Geometry.cpp @@ -66,7 +66,7 @@ void AMFImporter::ParseNode_Mesh() // create new mesh object. ne = new CAMFImporter_NodeElement_Mesh(mNodeElement_Cur); // Check for child nodes - if(!mReader->isEmptyElement()) + if(!mXmlParser->isEmptyElement()) { bool vert_read = false; @@ -107,7 +107,7 @@ CAMFImporter_NodeElement* ne; // create new mesh object. ne = new CAMFImporter_NodeElement_Vertices(mNodeElement_Cur); // Check for child nodes - if(!mReader->isEmptyElement()) + if(!mXmlParser->isEmptyElement()) { ParseHelper_Node_Enter(ne); MACRO_NODECHECK_LOOPBEGIN("vertices"); @@ -135,7 +135,7 @@ CAMFImporter_NodeElement* ne; // create new mesh object. ne = new CAMFImporter_NodeElement_Vertex(mNodeElement_Cur); // Check for child nodes - if(!mReader->isEmptyElement()) + if(!mXmlParser->isEmptyElement()) { bool col_read = false; bool coord_read = false; @@ -196,7 +196,7 @@ CAMFImporter_NodeElement* ne; CAMFImporter_NodeElement_Coordinates& als = *((CAMFImporter_NodeElement_Coordinates*)ne);// alias for convenience // Check for child nodes - if(!mReader->isEmptyElement()) + if(!mXmlParser->isEmptyElement()) { bool read_flag[3] = { false, false, false }; @@ -236,8 +236,8 @@ CAMFImporter_NodeElement* ne; // Read attributes for node . MACRO_ATTRREAD_LOOPBEG; - MACRO_ATTRREAD_CHECK_RET("materialid", materialid, mReader->getAttributeValue); - MACRO_ATTRREAD_CHECK_RET("type", type, mReader->getAttributeValue); + MACRO_ATTRREAD_CHECK_RET("materialid", materialid, mXmlParser->getAttributeValue); + MACRO_ATTRREAD_CHECK_RET("type", type, mXmlParser->getAttributeValue); MACRO_ATTRREAD_LOOPEND; // create new object. @@ -246,7 +246,7 @@ CAMFImporter_NodeElement* ne; ((CAMFImporter_NodeElement_Volume*)ne)->MaterialID = materialid; ((CAMFImporter_NodeElement_Volume*)ne)->Type = type; // Check for child nodes - if(!mReader->isEmptyElement()) + if(!mXmlParser->isEmptyElement()) { bool col_read = false; @@ -296,7 +296,7 @@ CAMFImporter_NodeElement* ne; CAMFImporter_NodeElement_Triangle& als = *((CAMFImporter_NodeElement_Triangle*)ne);// alias for convenience // Check for child nodes - if(!mReader->isEmptyElement()) + if(!mXmlParser->isEmptyElement()) { bool col_read = false, tex_read = false; bool read_flag[3] = { false, false, false }; diff --git a/code/AMF/AMFImporter_Material.cpp b/code/AMF/AMFImporter_Material.cpp index 64da12dda..78a0962f1 100644 --- a/code/AMF/AMFImporter_Material.cpp +++ b/code/AMF/AMFImporter_Material.cpp @@ -74,7 +74,7 @@ void AMFImporter::ParseNode_Color() { // Read attributes for node . MACRO_ATTRREAD_LOOPBEG; - MACRO_ATTRREAD_CHECK_RET("profile", profile, mReader->getAttributeValue); + MACRO_ATTRREAD_CHECK_RET("profile", profile, mXmlParser->getAttributeValue); MACRO_ATTRREAD_LOOPEND; // create new color object. @@ -84,7 +84,7 @@ void AMFImporter::ParseNode_Color() { als.Profile = profile; // Check for child nodes - if(!mReader->isEmptyElement()) + if(!mXmlParser->isEmptyElement()) { bool read_flag[4] = { false, false, false, false }; @@ -128,7 +128,7 @@ void AMFImporter::ParseNode_Material() { // Read attributes for node . MACRO_ATTRREAD_LOOPBEG; - MACRO_ATTRREAD_CHECK_RET("id", id, mReader->getAttributeValue); + MACRO_ATTRREAD_CHECK_RET("id", id, mXmlParser->getAttributeValue); MACRO_ATTRREAD_LOOPEND; // create new object. @@ -138,7 +138,7 @@ void AMFImporter::ParseNode_Material() { ((CAMFImporter_NodeElement_Material*)ne)->ID = id; // Check for child nodes - if(!mReader->isEmptyElement()) + if(!mXmlParser->isEmptyElement()) { bool col_read = false; @@ -183,25 +183,13 @@ void AMFImporter::ParseNode_Material() { // then layer by layer. // Multi elements - Yes. // Parent element - . -void AMFImporter::ParseNode_Texture() -{ - std::string id; - uint32_t width = 0; - uint32_t height = 0; - uint32_t depth = 1; - std::string type; - bool tiled = false; - std::string enc64_data; - - // Read attributes for node . - MACRO_ATTRREAD_LOOPBEG; - MACRO_ATTRREAD_CHECK_RET("id", id, mReader->getAttributeValue); - MACRO_ATTRREAD_CHECK_RET("width", width, XML_ReadNode_GetAttrVal_AsU32); - MACRO_ATTRREAD_CHECK_RET("height", height, XML_ReadNode_GetAttrVal_AsU32); - MACRO_ATTRREAD_CHECK_RET("depth", depth, XML_ReadNode_GetAttrVal_AsU32); - MACRO_ATTRREAD_CHECK_RET("type", type, mReader->getAttributeValue); - MACRO_ATTRREAD_CHECK_RET("tiled", tiled, XML_ReadNode_GetAttrVal_AsBool); - MACRO_ATTRREAD_LOOPEND; +void AMFImporter::ParseNode_Texture(XmlNode &node) { + std::string id = node.attribute("id").as_string(); + uint32_t width = node.attribute("width").as_uint(); + uint32_t height = node.attribute("height").as_uint(); + uint32_t depth = node.attribute("depth").as_uint(); + std::string type = node.attribute("type").as_string(); + bool tiled = node.attribute("tiled").as_bool(); // create new texture object. CAMFImporter_NodeElement *ne = new CAMFImporter_NodeElement_Texture(mNodeElement_Cur); @@ -209,7 +197,7 @@ void AMFImporter::ParseNode_Texture() CAMFImporter_NodeElement_Texture& als = *((CAMFImporter_NodeElement_Texture*)ne);// alias for convenience // Check for child nodes - if (!mReader->isEmptyElement()) { + if (!mXmlParser->isEmptyElement()) { XML_ReadNode_GetVal_AsString(enc64_data); } @@ -268,10 +256,10 @@ void AMFImporter::ParseNode_TexMap(const bool pUseOldName) { // Read attributes for node . MACRO_ATTRREAD_LOOPBEG; - MACRO_ATTRREAD_CHECK_RET("rtexid", rtexid, mReader->getAttributeValue); - MACRO_ATTRREAD_CHECK_RET("gtexid", gtexid, mReader->getAttributeValue); - MACRO_ATTRREAD_CHECK_RET("btexid", btexid, mReader->getAttributeValue); - MACRO_ATTRREAD_CHECK_RET("atexid", atexid, mReader->getAttributeValue); + MACRO_ATTRREAD_CHECK_RET("rtexid", rtexid, mXmlParser->getAttributeValue); + MACRO_ATTRREAD_CHECK_RET("gtexid", gtexid, mXmlParser->getAttributeValue); + MACRO_ATTRREAD_CHECK_RET("btexid", btexid, mXmlParser->getAttributeValue); + MACRO_ATTRREAD_CHECK_RET("atexid", atexid, mXmlParser->getAttributeValue); MACRO_ATTRREAD_LOOPEND; // create new texture coordinates object. diff --git a/code/Collada/ColladaParser.cpp b/code/Collada/ColladaParser.cpp index d0f71d95a..93f85521c 100644 --- a/code/Collada/ColladaParser.cpp +++ b/code/Collada/ColladaParser.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, @@ -68,11 +66,8 @@ using namespace Assimp::Formatter; // ------------------------------------------------------------------------------------------------ // Constructor to be privately used by Importer -ColladaParser::ColladaParser(IOSystem* pIOHandler, const std::string& pFile) - : mFileName(pFile) - , mReader(nullptr) - , mDataLibrary() - , mAccessorLibrary() +ColladaParser::ColladaParser(IOSystem* pIOHandler, const std::string& pFile) : + mFileName(pFile), mXmlParser(nullptr), mDataLibrary(), mAccessorLibrary() , mMeshLibrary() , mNodeLibrary() , mImageLibrary() @@ -1532,7 +1527,7 @@ void ColladaParser::ReadLight(Collada::Light& pLight) // ------------------------------------------------------------------------------------------------ // Reads a camera entry into the given light -void ColladaParser::ReadCamera(Collada::Camera& pCamera) +void ColladaParser::ReadCamera(Collada::Camera& camera) { while (mReader->read()) { @@ -1541,26 +1536,26 @@ void ColladaParser::ReadCamera(Collada::Camera& pCamera) SkipElement(); } else if (IsElement("orthographic")) { - pCamera.mOrtho = true; + camera.mOrtho = true; } else if (IsElement("xfov") || IsElement("xmag")) { - pCamera.mHorFov = ReadFloatFromTextContent(); - TestClosing((pCamera.mOrtho ? "xmag" : "xfov")); + camera.mHorFov = ReadFloatFromTextContent(); + TestClosing((camera.mOrtho ? "xmag" : "xfov")); } else if (IsElement("yfov") || IsElement("ymag")) { - pCamera.mVerFov = ReadFloatFromTextContent(); - TestClosing((pCamera.mOrtho ? "ymag" : "yfov")); + camera.mVerFov = ReadFloatFromTextContent(); + TestClosing((camera.mOrtho ? "ymag" : "yfov")); } else if (IsElement("aspect_ratio")) { - pCamera.mAspect = ReadFloatFromTextContent(); + camera.mAspect = ReadFloatFromTextContent(); TestClosing("aspect_ratio"); } else if (IsElement("znear")) { - pCamera.mZNear = ReadFloatFromTextContent(); + camera.mZNear = ReadFloatFromTextContent(); TestClosing("znear"); } else if (IsElement("zfar")) { - pCamera.mZFar = ReadFloatFromTextContent(); + camera.mZFar = ReadFloatFromTextContent(); TestClosing("zfar"); } } diff --git a/code/Collada/ColladaParser.h b/code/Collada/ColladaParser.h index 963f79dc1..614e6ca12 100644 --- a/code/Collada/ColladaParser.h +++ b/code/Collada/ColladaParser.h @@ -4,7 +4,6 @@ Copyright (c) 2006-2020, assimp team - All rights reserved. Redistribution and use of this software in source and binary forms, @@ -55,6 +54,7 @@ namespace Assimp { class ZipArchiveIOSystem; + class XmlParser; // ------------------------------------------------------------------------------------------ /** Parser helper class for the Collada loader. @@ -112,7 +112,7 @@ namespace Assimp /** Reads an animation into the given parent structure */ void ReadAnimation( Collada::Animation* pParent); - /** Reads an animation sampler into the given anim channel */ + /** Reads an animation sampler into the given animation channel */ void ReadAnimationSampler( Collada::AnimationChannel& pChannel); /** Reads the skeleton controller library */ @@ -157,16 +157,16 @@ namespace Assimp /** Reads an effect entry into the given effect*/ void ReadEffect( Collada::Effect& pEffect); - /** Reads an COMMON effect profile */ + /// Reads an COMMON effect profile void ReadEffectProfileCommon( Collada::Effect& pEffect); - /** Read sampler properties */ + /// Read sampler properties void ReadSamplerProperties( Collada::Sampler& pSampler); - /** Reads an effect entry containing a color or a texture defining that color */ + /// Reads an effect entry containing a color or a texture defining that color void ReadEffectColor( aiColor4D& pColor, Collada::Sampler& pSampler); - /** Reads an effect entry containing a float */ + /// Reads an effect entry containing a float void ReadEffectFloat( ai_real& pFloat); /** Reads an effect parameter specification of any kind */ @@ -182,7 +182,7 @@ namespace Assimp void ReadMesh( Collada::Mesh* pMesh); /** Reads a source element - a combination of raw data and an accessor defining - * things that should not be redefinable. Yes, that's another rant. + * things that should not be re-definable. Yes, that's another rant. */ void ReadSource(); @@ -214,7 +214,7 @@ namespace Assimp Collada::Mesh* pMesh, std::vector& pPerIndexChannels, size_t currentPrimitive, const std::vector& indices); - /** Reads one triangle of a tristrip into the mesh */ + /** Reads one triangle of a triangle-strip into the mesh */ void ReadPrimTriStrips(size_t numOffsets, size_t perVertexOffset, Collada::Mesh* pMesh, std::vector& pPerIndexChannels, size_t currentPrimitive, const std::vector& indices); @@ -298,7 +298,8 @@ namespace Assimp std::string mFileName; /** XML reader, member for everyday use */ - irr::io::IrrXMLReader* mReader; + //irr::io::IrrXMLReader* mReader; + XmlParser *mXmlParser; /** All data arrays found in the file by ID. Might be referred to by actually everyone. Collada, you are a steaming pile of indirection. */ @@ -359,19 +360,24 @@ namespace Assimp /** Size unit: how large compared to a meter */ ai_real mUnitSize; - /** Which is the up vector */ - enum { UP_X, UP_Y, UP_Z } mUpDirection; + /// Which is the up vector. + enum { + UP_X, + UP_Y, + UP_Z + } mUpDirection; - /** Asset metadata (global for scene) */ + /// Asset metadata (global for scene) StringMetaData mAssetMetaData; - /** Collada file format version */ + /// Collada file format version Collada::FormatVersion mFormat; }; // ------------------------------------------------------------------------------------------------ // Check for element match - inline bool ColladaParser::IsElement( const char* pName) const + inline + bool ColladaParser::IsElement( const char* pName) const { ai_assert( mReader->getNodeType() == irr::io::EXN_ELEMENT); return ::strcmp( mReader->getNodeName(), pName) == 0; @@ -380,11 +386,11 @@ namespace Assimp // ------------------------------------------------------------------------------------------------ // Finds the item in the given library by its reference, throws if not found template - const Type& ColladaParser::ResolveLibraryReference( const std::map& pLibrary, const std::string& pURL) const + const Type& ColladaParser::ResolveLibraryReference( const std::map& library, const std::string& url) const { - typename std::map::const_iterator it = pLibrary.find( pURL); - if( it == pLibrary.end()) - ThrowException( Formatter::format() << "Unable to resolve library reference \"" << pURL << "\"." ); + typename std::map::const_iterator it = library.find( url); + if( it == library.end()) + ThrowException( Formatter::format() << "Unable to resolve library reference \"" << url << "\"." ); return it->second; } diff --git a/code/Irr/IRRLoader.h b/code/Irr/IRRLoader.h index fc6f77031..b70782963 100644 --- a/code/Irr/IRRLoader.h +++ b/code/Irr/IRRLoader.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, @@ -40,7 +39,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ---------------------------------------------------------------------- */ - /** @file IRRLoader.h * @brief Declaration of the .irrMesh (Irrlight Engine Mesh Format) * importer class. @@ -83,7 +81,7 @@ protected: private: - /** Data structure for a scenegraph node animator + /** Data structure for a scene-graph node animator */ struct Animator { // Type of the animator @@ -129,7 +127,7 @@ private: int timeForWay; }; - /** Data structure for a scenegraph node in an IRR file + /** Data structure for a scene-graph node in an IRR file */ struct Node { @@ -227,8 +225,7 @@ private: // ------------------------------------------------------------------- - /** Fill the scenegraph recursively - */ + /// Fill the scene-graph recursively void GenerateGraph(Node* root,aiNode* rootOut ,aiScene* scene, BatchLoader& batch, std::vector& meshes, @@ -237,27 +234,22 @@ private: std::vector& materials, unsigned int& defaultMatIdx); - // ------------------------------------------------------------------- - /** Generate a mesh that consists of just a single quad - */ + /// Generate a mesh that consists of just a single quad aiMesh* BuildSingleQuadMesh(const SkyboxVertex& v1, const SkyboxVertex& v2, const SkyboxVertex& v3, const SkyboxVertex& v4); - // ------------------------------------------------------------------- - /** Build a skybox - * - * @param meshes Receives 6 output meshes - * @param materials The last 6 materials are assigned to the newly - * created meshes. The names of the materials are adjusted. - */ + /// Build a sky-box + /// + /// @param meshes Receives 6 output meshes + /// @param materials The last 6 materials are assigned to the newly + /// created meshes. The names of the materials are adjusted. void BuildSkybox(std::vector& meshes, std::vector materials); - // ------------------------------------------------------------------- /** Copy a material for a mesh to the output material list * @@ -271,7 +263,6 @@ private: unsigned int& defMatIdx, aiMesh* mesh); - // ------------------------------------------------------------------- /** Compute animations for a specific node * @@ -281,13 +272,11 @@ private: void ComputeAnimations(Node* root, aiNode* real, std::vector& anims); - private: - - /** Configuration option: desired output FPS */ + /// Configuration option: desired output FPS double fps; - /** Configuration option: speed flag was set? */ + /// Configuration option: speed flag was set? bool configSpeedFlag; }; diff --git a/code/X3D/X3DExporter.cpp b/code/X3D/X3DExporter.cpp index e5eeb0886..aa73ede74 100644 --- a/code/X3D/X3DExporter.cpp +++ b/code/X3D/X3DExporter.cpp @@ -14,23 +14,14 @@ #include #include -using namespace std; +namespace Assimp { -namespace Assimp -{ - -void ExportSceneX3D(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* pProperties) -{ +void ExportSceneX3D(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* pProperties) { X3DExporter exporter(pFile, pIOSystem, pScene, pProperties); } -}// namespace Assimp -namespace Assimp -{ - -void X3DExporter::IndentationStringSet(const size_t pNewLevel) -{ +void X3DExporter::IndentationStringSet(const size_t pNewLevel) { if(pNewLevel > mIndentationString.size()) { if(pNewLevel > mIndentationString.capacity()) mIndentationString.reserve(pNewLevel + 1); @@ -43,31 +34,33 @@ void X3DExporter::IndentationStringSet(const size_t pNewLevel) } } -void X3DExporter::XML_Write(const string& pData) -{ - if(pData.size() == 0) return; - if(mOutFile->Write((void*)pData.data(), pData.length(), 1) != 1) throw DeadlyExportError("Failed to write scene data!"); +void X3DExporter::XML_Write(const std::string& pData) { + if (pData.empty() ) { + return; + } + + if (mOutFile->Write((void *)pData.data(), pData.length(), 1) != 1) { + throw DeadlyExportError("Failed to write scene data!"); + } } -aiMatrix4x4 X3DExporter::Matrix_GlobalToCurrent(const aiNode& pNode) const -{ -aiNode* cur_node; -std::list matr; -aiMatrix4x4 out_matr; +aiMatrix4x4 X3DExporter::Matrix_GlobalToCurrent(const aiNode& pNode) const { + aiNode *cur_node; + std::list matr; + aiMatrix4x4 out_matr; // starting walk from current element to root matr.push_back(pNode.mTransformation); cur_node = pNode.mParent; if(cur_node != nullptr) { - do - { + do { matr.push_back(cur_node->mTransformation); cur_node = cur_node->mParent; } while(cur_node != nullptr); } - // multiplicate all matrices in reverse order + // Multiplication of all matrices in reverse order for(std::list::reverse_iterator rit = matr.rbegin(); rit != matr.rend(); ++rit) out_matr = out_matr * (*rit); return out_matr; @@ -142,7 +135,7 @@ void X3DExporter::AttrHelper_Col3DArrToString(const aiColor3D* pArray, const siz void X3DExporter::AttrHelper_Color3ToAttrList(std::list& pList, const std::string& pName, const aiColor3D& pValue, const aiColor3D& pDefaultValue) { -string tstr; + string tstr; if(pValue == pDefaultValue) return; @@ -152,7 +145,7 @@ string tstr; void X3DExporter::AttrHelper_FloatToAttrList(std::list& pList, const string& pName, const float pValue, const float pDefaultValue) { -string tstr; + string tstr; if(pValue == pDefaultValue) return; @@ -183,7 +176,7 @@ void X3DExporter::NodeHelper_OpenNode(const string& pNodeName, const size_t pTab void X3DExporter::NodeHelper_OpenNode(const string& pNodeName, const size_t pTabLevel, const bool pEmptyElement) { -const list attr_list; + const list attr_list; NodeHelper_OpenNode(pNodeName, pTabLevel, pEmptyElement, attr_list); } @@ -199,8 +192,8 @@ void X3DExporter::NodeHelper_CloseNode(const string& pNodeName, const size_t pTa void X3DExporter::Export_Node(const aiNode *pNode, const size_t pTabLevel) { -bool transform = false; -list attr_list; + bool transform = false; + list attr_list; // In Assimp lights is stored in next way: light source store in mScene->mLights and in node tree must present aiNode with name same as // light source has. Considering it we must compare every aiNode name with light sources names. Why not to look where ligths is present @@ -303,11 +296,11 @@ list attr_list; void X3DExporter::Export_Mesh(const size_t pIdxMesh, const size_t pTabLevel) { -const char* NodeName_IFS = "IndexedFaceSet"; -const char* NodeName_Shape = "Shape"; + const char* NodeName_IFS = "IndexedFaceSet"; + const char* NodeName_Shape = "Shape"; -list attr_list; -aiMesh& mesh = *mScene->mMeshes[pIdxMesh];// create alias for conveniance. + list attr_list; + aiMesh& mesh = *mScene->mMeshes[pIdxMesh];// create alias for conveniance. // Check if mesh already defined early. if(mDEF_Map_Mesh.find(pIdxMesh) != mDEF_Map_Mesh.end()) @@ -407,10 +400,10 @@ aiMesh& mesh = *mScene->mMeshes[pIdxMesh];// create alias for conveniance. void X3DExporter::Export_Material(const size_t pIdxMaterial, const size_t pTabLevel) { -const char* NodeName_A = "Appearance"; + const char* NodeName_A = "Appearance"; -list attr_list; -aiMaterial& material = *mScene->mMaterials[pIdxMaterial];// create alias for conveniance. + list attr_list; + aiMaterial& material = *mScene->mMaterials[pIdxMaterial];// create alias for conveniance. // Check if material already defined early. if(mDEF_Map_Material.find(pIdxMaterial) != mDEF_Map_Material.end()) @@ -564,7 +557,7 @@ aiMaterial& material = *mScene->mMaterials[pIdxMaterial];// create alias for con void X3DExporter::Export_MetadataBoolean(const aiString& pKey, const bool pValue, const size_t pTabLevel) { -list attr_list; + list attr_list; attr_list.push_back({"name", pKey.C_Str()}); attr_list.push_back({"value", pValue ? "true" : "false"}); @@ -573,7 +566,7 @@ list attr_list; void X3DExporter::Export_MetadataDouble(const aiString& pKey, const double pValue, const size_t pTabLevel) { -list attr_list; + list attr_list; attr_list.push_back({"name", pKey.C_Str()}); attr_list.push_back({"value", to_string(pValue)}); @@ -582,7 +575,7 @@ list attr_list; void X3DExporter::Export_MetadataFloat(const aiString& pKey, const float pValue, const size_t pTabLevel) { -list attr_list; + list attr_list; attr_list.push_back({"name", pKey.C_Str()}); attr_list.push_back({"value", to_string(pValue)}); @@ -591,7 +584,7 @@ list attr_list; void X3DExporter::Export_MetadataInteger(const aiString& pKey, const int32_t pValue, const size_t pTabLevel) { -list attr_list; + list attr_list; attr_list.push_back({"name", pKey.C_Str()}); attr_list.push_back({"value", to_string(pValue)}); @@ -600,7 +593,7 @@ list attr_list; void X3DExporter::Export_MetadataString(const aiString& pKey, const aiString& pValue, const size_t pTabLevel) { -list attr_list; + list attr_list; attr_list.push_back({"name", pKey.C_Str()}); attr_list.push_back({"value", pValue.C_Str()}); @@ -609,7 +602,7 @@ list attr_list; bool X3DExporter::CheckAndExport_Light(const aiNode& pNode, const size_t pTabLevel) { -list attr_list; + list attr_list; auto Vec3ToAttrList = [&](const string& pAttrName, const aiVector3D& pAttrValue, const aiVector3D& pAttrDefaultValue) { @@ -622,8 +615,8 @@ auto Vec3ToAttrList = [&](const string& pAttrName, const aiVector3D& pAttrValue, } }; -size_t idx_light; -bool found = false; + size_t idx_light; + bool found = false; // Name of the light source can not be empty. if(pNode.mName.length == 0) return false; @@ -699,7 +692,7 @@ bool found = false; X3DExporter::X3DExporter(const char* pFileName, IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* /*pProperties*/) : mScene(pScene) { -list attr_list; + list attr_list; mOutFile = pIOSystem->Open(pFileName, "wt"); if(mOutFile == nullptr) throw DeadlyExportError("Could not open output .x3d file: " + string(pFileName)); diff --git a/code/X3D/X3DExporter.hpp b/code/X3D/X3DExporter.hpp index dc1650b5a..64953ca1d 100644 --- a/code/X3D/X3DExporter.hpp +++ b/code/X3D/X3DExporter.hpp @@ -47,6 +47,8 @@ namespace Assimp /// class X3DExporter { + using AttrubuteList = std::list; + /***********************************************/ /******************** Types ********************/ /***********************************************/ diff --git a/code/XGL/XGLLoader.cpp b/code/XGL/XGLLoader.cpp index 24ed5d57c..93c3b559c 100644 --- a/code/XGL/XGLLoader.cpp +++ b/code/XGL/XGLLoader.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,453 +41,387 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. /** @file Implementation of the XGL/ZGL importer class */ - #ifndef ASSIMP_BUILD_NO_XGL_IMPORTER #include "XGLLoader.h" #include #include -#include #include +#include +#include #include #include -#include #include #include using namespace Assimp; -using namespace irr; -using namespace irr::io; +//using namespace irr; +//using namespace irr::io; // zlib is needed for compressed XGL files #ifndef ASSIMP_BUILD_NO_COMPRESSED_XGL -# ifdef ASSIMP_BUILD_NO_OWN_ZLIB -# include -# else -# include -# endif +#ifdef ASSIMP_BUILD_NO_OWN_ZLIB +#include +#else +#include +#endif #endif - namespace Assimp { // this has to be in here because LogFunctions is in ::Assimp - template<> const char* LogFunctions::Prefix() - { - static auto prefix = "XGL: "; - return prefix; - } +template <> +const char *LogFunctions::Prefix() { + static auto prefix = "XGL: "; + return prefix; } +} // namespace Assimp static const aiImporterDesc desc = { - "XGL Importer", - "", - "", - "", - aiImporterFlags_SupportTextFlavour | aiImporterFlags_SupportCompressedFlavour, - 0, - 0, - 0, - 0, - "xgl zgl" + "XGL Importer", + "", + "", + "", + aiImporterFlags_SupportTextFlavour | aiImporterFlags_SupportCompressedFlavour, + 0, + 0, + 0, + 0, + "xgl zgl" }; - // ------------------------------------------------------------------------------------------------ // Constructor to be privately used by Importer -XGLImporter::XGLImporter() -: m_reader( nullptr ) -, m_scene( nullptr ) { - // empty +XGLImporter::XGLImporter() : + m_xmlParser(nullptr), m_scene(nullptr) { + // empty } // ------------------------------------------------------------------------------------------------ // Destructor, private as well XGLImporter::~XGLImporter() { - // empty + // empty } // ------------------------------------------------------------------------------------------------ // Returns whether the class can handle the format of the given file. -bool XGLImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const -{ - /* NOTE: A simple check for the file extension is not enough +bool XGLImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const { + /* NOTE: A simple check for the file extension is not enough * 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); + const std::string extension = GetExtension(pFile); - if (extension == "xgl" || extension == "zgl") { - return true; - } - else if (extension == "xml" || checkSig) { - ai_assert(pIOHandler != NULL); + if (extension == "xgl" || extension == "zgl") { + return true; + } else if (extension == "xml" || checkSig) { + ai_assert(pIOHandler != NULL); - const char* tokens[] = {"","",""}; - return SearchFileHeaderForToken(pIOHandler,pFile,tokens,3); - } - return false; + const char *tokens[] = { "", "", "" }; + return SearchFileHeaderForToken(pIOHandler, pFile, tokens, 3); + } + return false; } // ------------------------------------------------------------------------------------------------ // Get a list of all file extensions which are handled by this class -const aiImporterDesc* XGLImporter::GetInfo () const -{ - return &desc; +const aiImporterDesc *XGLImporter::GetInfo() const { + return &desc; } // ------------------------------------------------------------------------------------------------ // Imports the given file into the given scene structure. -void XGLImporter::InternReadFile( const std::string& pFile, - aiScene* pScene, IOSystem* pIOHandler) -{ +void XGLImporter::InternReadFile(const std::string &pFile, + aiScene *pScene, IOSystem *pIOHandler) { #ifndef ASSIMP_BUILD_NO_COMPRESSED_XGL - std::vector uncompressed; + std::vector uncompressed; #endif - m_scene = pScene; - std::shared_ptr stream( pIOHandler->Open( pFile, "rb")); + m_scene = pScene; + std::shared_ptr stream(pIOHandler->Open(pFile, "rb")); - // check whether we can read from the file - if( stream.get() == NULL) { - throw DeadlyImportError( "Failed to open XGL/ZGL file " + pFile + ""); - } + // check whether we can read from the file + if (stream.get() == NULL) { + throw DeadlyImportError("Failed to open XGL/ZGL file " + pFile + ""); + } - // see if its compressed, if so uncompress it - if (GetExtension(pFile) == "zgl") { + // 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"); + ThrowException("Cannot read ZGL file since Assimp was built without compression support"); #else - std::unique_ptr raw_reader(new StreamReaderLE(stream)); + 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; + // 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); + // 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); + // 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 = raw_reader->GetRemainingSize(); + zstream.next_in = reinterpret_cast(raw_reader->GetPtr()); + zstream.avail_in = raw_reader->GetRemainingSize(); - size_t total = 0l; + 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); + // 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); + 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); + // terminate zlib + inflateEnd(&zstream); - // replace the input stream with a memory stream - stream.reset(new MemoryIOStream(reinterpret_cast(uncompressed.data()),total)); + // 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 ) ); + // construct the irrXML parser + /*CIrrXML_IOStreamReader st(stream.get()); + m_reader.reset( createIrrXMLReader( ( IFileReadCallBack* ) &st ) );*/ + m_xmlParser = new XmlParser; + XmlNode *root = m_xmlParser->parse(stream.get()); + if (nullptr == root) { + return; + } - // parse the XML file - TempScope scope; + // parse the XML file + TempScope scope; + if (!ASSIMP_stricmp(root->name(), "world")) { + ReadWorld(scope); + } - while (ReadElement()) { + /* while (ReadElement()) { if (!ASSIMP_stricmp(m_reader->getNodeName(),"world")) { ReadWorld(scope); } - } + }*/ + 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"); + } - 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 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); - // 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; - if (scope.light) { - m_scene->mNumLights = 1; - m_scene->mLights = new aiLight*[1]; - m_scene->mLights[0] = scope.light; + scope.light->mName = m_scene->mRootNode->mName; + } - scope.light->mName = m_scene->mRootNode->mName; - } - - scope.dismiss(); + scope.dismiss(); } // ------------------------------------------------------------------------------------------------ -bool XGLImporter::ReadElement() -{ - while(m_reader->read()) { - if (m_reader->getNodeType() == EXN_ELEMENT) { - return true; - } - } - return false; +void XGLImporter::ReadWorld(TempScope &scope) { + XmlNode *root = m_xmlParser->getRootNode(); + for (XmlNode &node : root->children()) { + const std::string &s = node.name(); + // XXX right now we'd skip if it comes after + // or + if (s == "lighting") { + ReadLighting(node, scope); + } else if (s == "object" || s == "mesh" || s == "mat") { + break; + } + } + + aiNode *const nd = ReadObject(*root, scope, true, "world"); + if (!nd) { + ThrowException("failure reading "); + } + if (!nd->mName.length) { + nd->mName.Set("WORLD"); + } + + m_scene->mRootNode = nd; } // ------------------------------------------------------------------------------------------------ -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; +void XGLImporter::ReadLighting(XmlNode &node, TempScope &scope) { + const std::string &s = node.name(); + if (s == "directionallight") { + scope.light = ReadDirectionalLight(node); + } else if (s == "ambient") { + LogWarn("ignoring tag"); + } else if (s == "spheremap") { + LogWarn("ignoring tag"); + } } // ------------------------------------------------------------------------------------------------ -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; +aiLight *XGLImporter::ReadDirectionalLight(XmlNode &node) { + std::unique_ptr l(new aiLight()); + l->mType = aiLightSource_DIRECTIONAL; + find_node_by_name_predicate predicate("directionallight"); + XmlNode child = node.find_child(predicate); + if (child.empty()) { + return nullptr; + } + + const std::string &s = child.name(); + if (s == "direction") { + l->mDirection = ReadVec3(child); + } else if (s == "diffuse") { + l->mColorDiffuse = ReadCol3(child); + } else if (s == "specular") { + l->mColorSpecular = ReadCol3(child); + } + + return l.release(); } // ------------------------------------------------------------------------------------------------ -std::string XGLImporter::GetElementName() -{ - const char* s = m_reader->getNodeName(); - size_t len = strlen(s); +aiNode *XGLImporter::ReadObject(XmlNode &node, TempScope &scope, bool skipFirst, const char *closetag) { + aiNode *nd = new aiNode; + std::vector children; + std::vector meshes; - std::string ret; - ret.resize(len); + try { + for (XmlNode &child : node.children()) { - std::transform(s,s+len,ret.begin(),::tolower); - return ret; + skipFirst = false; + + const std::string &s = child.name(); + if (s == "mesh") { + const size_t prev = scope.meshes_linear.size(); + if (ReadMesh(child, scope)) { + const size_t newc = scope.meshes_linear.size(); + for (size_t i = 0; i < newc - prev; ++i) { + meshes.push_back(static_cast(i + prev)); + } + } + } else if (s == "mat") { + ReadMaterial(child, scope); + } else if (s == "object") { + children.push_back(ReadObject(child, scope)); + } else if (s == "objectref") { + // XXX + } else if (s == "meshref") { + const unsigned int id = static_cast(ReadIndexFromText(child)); + + 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(child); + } + } + } 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 (0 != 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; } // ------------------------------------------------------------------------------------------------ -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; - } - } +aiMatrix4x4 XGLImporter::ReadTrafo(XmlNode &node) { + aiVector3D forward, up, right, position; + float scale = 1.0f; + aiMatrix4x4 m; + XmlNode child = node.child("transform"); + if (child.empty()) { + return m; + } - aiNode* const nd = ReadObject(scope,true,"world"); - if(!nd) { - ThrowException("failure reading "); - } - if(!nd->mName.length) { - nd->mName.Set("WORLD"); - } + for (XmlNode &sub_child : child.children()) { + const std::string &s = sub_child.name(); + if (s == "forward") { + forward = ReadVec3(sub_child); + } else if (s == "up") { + up = ReadVec3(sub_child); + } else if (s == "position") { + position = ReadVec3(sub_child); + } + if (s == "scale") { + scale = ReadFloat(sub_child); + 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"); + } + } + } - 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; + if (forward.SquareLength() < 1e-4 || up.SquareLength() < 1e-4) { + LogError("A direction vector in is zero, ignoring trafo"); + return m; } forward.Normalize(); @@ -497,10 +429,10 @@ aiMatrix4x4 XGLImporter::ReadTrafo() right = forward ^ up; if (std::fabs(up * forward) > 1e-4) { - // this is definitely wrong - a degenerate coordinate space ruins everything - // so substitute identity transform. - LogError(" and vectors in are skewing, ignoring trafo"); - return m; + // this is definitely wrong - a degenerate coordinate space ruins everything + // so substitute identity transform. + LogError(" and vectors in are skewing, ignoring trafo"); + return m; } right *= scale; @@ -523,434 +455,385 @@ aiMatrix4x4 XGLImporter::ReadTrafo() m.b4 = position.y; m.c4 = position.z; - return m; + return m; } // ------------------------------------------------------------------------------------------------ -aiMesh* XGLImporter::ToOutputMesh(const TempMaterialMesh& m) -{ - std::unique_ptr mesh(new aiMesh()); +aiMesh *XGLImporter::ToOutputMesh(const TempMaterialMesh &m) { + 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); + 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.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]; + 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); - } - } + 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()]; + 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++; - } - } + 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++; + } + } - ai_assert(idx == mesh->mNumVertices); + ai_assert(idx == mesh->mNumVertices); + + mesh->mPrimitiveTypes = m.pflags; + mesh->mMaterialIndex = m.matid; - mesh->mPrimitiveTypes = m.pflags; - mesh->mMaterialIndex = m.matid; return mesh.release(); } // ------------------------------------------------------------------------------------------------ -bool XGLImporter::ReadMesh(TempScope& scope) -{ - TempMesh t; +bool XGLImporter::ReadMesh(XmlNode &node, TempScope &scope) { + TempMesh t; - std::map bymat; - const unsigned int mesh_id = ReadIDAttr(); + std::map bymat; + const unsigned int mesh_id = ReadIDAttr(node); - while (ReadElementUpToClosing("mesh")) { - const std::string& s = GetElementName(); + for (XmlNode &child : node.children()) { + const std::string &s = child.name(); - 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); + if (s == "mat") { + ReadMaterial(child, scope); + } else if (s == "p") { + pugi::xml_attribute attr = child.attribute("ID"); + if (attr.empty()) { + LogWarn("no ID attribute on

, ignoring"); + } else { + int id = attr.as_int(); + t.points[id] = ReadVec3(child); + } + } else if (s == "n") { + pugi::xml_attribute attr = child.attribute("ID"); + if (attr.empty()) { + LogWarn("no ID attribute on , ignoring"); + } else { + int id = attr.as_int(); + t.normals[id] = ReadVec3(child); + } + } else if (s == "tc") { + pugi::xml_attribute attr = child.attribute("ID"); + if (attr.empty()) { + LogWarn("no ID attribute on , ignoring"); + } else { + int id = attr.as_int(); + t.uvs[id] = ReadVec2(child); + } + } 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}; + unsigned int mid = ~0u; + TempFace tf[3]; + bool has[3] = { false }; + for (XmlNode &sub_child : child.children()) { + const std::string &s = sub_child.name(); + if (s == "fv1" || s == "lv1" || s == "pv1") { + ReadFaceVertex(sub_child, t, tf[0]); + has[0] = true; + } else if (s == "fv2" || s == "lv2") { + ReadFaceVertex(sub_child, t, tf[1]); + has[1] = true; + } else if (s == "fv3") { + ReadFaceVertex(sub_child, t, tf[2]); + has[2] = true; + } else if (s == "mat") { + if (mid != ~0u) { + LogWarn("only one material tag allowed per "); + } + mid = ResolveMaterialRef(sub_child, scope); + } else if (s == "matref") { + if (mid != ~0u) { + LogWarn("only one material tag allowed per "); + } + mid = ResolveMaterialRef(sub_child, scope); + } + } - while (ReadElementUpToClosing(s.c_str())) { - const std::string& s = GetElementName(); - if (s == "fv1" || s == "lv1" || s == "pv1") { - ReadFaceVertex(t,tf[0]); - has[0] = true; - } - else if (s == "fv2" || s == "lv2") { - ReadFaceVertex(t,tf[1]); - has[1] = true; - } - else if (s == "fv3") { - ReadFaceVertex(t,tf[2]); - has[2] = true; - } - else if (s == "mat") { - if (mid != ~0u) { - LogWarn("only one material tag allowed per "); - } - mid = ResolveMaterialRef(scope); - } - else if (s == "matref") { - if (mid != ~0u) { - LogWarn("only one material tag allowed per "); - } - mid = ResolveMaterialRef(scope); - } - } + if (mid == ~0u) { + ThrowException("missing material index"); + } - 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"); + } - 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; + } - 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); - 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; - 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); + } - 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.pflags |= 1 << (vcount-1); - } + mesh.vcounts.push_back(vcount); + } + } - 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); - // 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)); + } + } - // 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; + // 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); - } +unsigned int XGLImporter::ResolveMaterialRef(XmlNode &node, TempScope &scope) { + const std::string &s = node.name(); + if (s == "mat") { + ReadMaterial(node, scope); + return static_cast(scope.materials_linear.size() - 1); + } - const int id = ReadIndexFromText(); + const int id = ReadIndexFromText(node); - std::map::iterator it = scope.materials.find(id), end = scope.materials.end(); - if (it == end) { - ThrowException(" index out of range"); - } + 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; + // 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; - } - } + unsigned int i = 0, mcount = static_cast(scope.materials_linear.size()); + for (; i < mcount; ++i) { + if (scope.materials_linear[i] == m) { + return i; + } + } - ai_assert(false); - return 0; + ai_assert(false); + + return 0; } // ------------------------------------------------------------------------------------------------ -void XGLImporter::ReadMaterial(TempScope& scope) { - const unsigned int mat_id = ReadIDAttr(); +void XGLImporter::ReadMaterial(XmlNode &node, TempScope &scope) { + const unsigned int mat_id = ReadIDAttr(node); - 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); - } - } + aiMaterial *mat(new aiMaterial); + for (XmlNode &child : node.children()) { + const std::string &s = child.name(); + if (s == "amb") { + const aiColor3D c = ReadCol3(child); + mat->AddProperty(&c, 1, AI_MATKEY_COLOR_AMBIENT); + } else if (s == "diff") { + const aiColor3D c = ReadCol3(child); + mat->AddProperty(&c, 1, AI_MATKEY_COLOR_DIFFUSE); + } else if (s == "spec") { + const aiColor3D c = ReadCol3(child); + mat->AddProperty(&c, 1, AI_MATKEY_COLOR_SPECULAR); + } else if (s == "emiss") { + const aiColor3D c = ReadCol3(child); + mat->AddProperty(&c, 1, AI_MATKEY_COLOR_EMISSIVE); + } else if (s == "alpha") { + const float f = ReadFloat(child); + mat->AddProperty(&f, 1, AI_MATKEY_OPACITY); + } else if (s == "shine") { + const float f = ReadFloat(child); + mat->AddProperty(&f, 1, AI_MATKEY_SHININESS); + } + } - scope.materials[mat_id] = mat; - scope.materials_linear.push_back(mat); + scope.materials[mat_id] = mat; + scope.materials_linear.push_back(mat); } // ---------------------------------------------------------------------------------------------- -void XGLImporter::ReadFaceVertex(const TempMesh& t, TempFace& out) -{ - const std::string& end = GetElementName(); +void XGLImporter::ReadFaceVertex(XmlNode &node, const TempMesh &t, TempFace &out) { + const std::string &end = node.name(); - 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"); - } + bool havep = false; + //while (ReadElementUpToClosing(end.c_str())) { + for (XmlNode &child : node.children()) { + const std::string &s = child.name(); + if (s == "pref") { + const unsigned int id = ReadIndexFromText(child); + 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.pos = (*it).second; + havep = true; + } else if (s == "nref") { + const unsigned int id = ReadIndexFromText(child); + 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.normal = (*it).second; + out.has_normal = true; + } else if (s == "tcref") { + const unsigned int id = ReadIndexFromText(child); + 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(); - } - } + out.uv = (*it).second; + out.has_uv = true; + } else if (s == "p") { + out.pos = ReadVec3(child); + } else if (s == "n") { + out.normal = ReadVec3(child); + } else if (s == "tc") { + out.uv = ReadVec2(child); + } + } - if (!havep) { - ThrowException("missing in element"); - } + if (!havep) { + ThrowException("missing in element"); + } } // ------------------------------------------------------------------------------------------------ -unsigned int XGLImporter::ReadIDAttr() -{ - for(int i = 0, e = m_reader->getAttributeCount(); i < e; ++i) { +unsigned int XGLImporter::ReadIDAttr(XmlNode &node) { + for (pugi::xml_attribute attr : node.attributes()) { + if (!ASSIMP_stricmp(attr.name(), "id")) { + return attr.as_int(); + } + } - if(!ASSIMP_stricmp(m_reader->getAttributeName(i),"id")) { - return m_reader->getAttributeValueAsInt(i); - } - } - return ~0u; + return ~0u; } // ------------------------------------------------------------------------------------------------ -float XGLImporter::ReadFloat() -{ - if(!SkipToText()) { - LogError("unexpected EOF reading float element contents"); - return 0.f; - } - const char* s = m_reader->getNodeData(), *se; +float XGLImporter::ReadFloat(XmlNode &node) { + const char *s = node.value(), *se; + if (!SkipSpaces(&s)) { + LogError("unexpected EOL, failed to parse index element"); + return 0.f; + } + float t; + se = fast_atoreal_move(s, t); + if (se == s) { + LogError("failed to read float text"); + return 0.f; + } - 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; + 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; - } +unsigned int XGLImporter::ReadIndexFromText(XmlNode &node) { + const char *s = node.value(); + if (!SkipSpaces(&s)) { + LogError("unexpected EOL, failed to parse index element"); + return ~0u; + } + const char *se; + const unsigned int t = strtoul10(s, &se); - const unsigned int t = strtoul10(s,&se); + if (se == s) { + LogError("failed to read index"); + return ~0u; + } - if (se == s) { - LogError("failed to read index"); - return ~0u; - } - - return t; + return t; } // ------------------------------------------------------------------------------------------------ -aiVector2D XGLImporter::ReadVec2() -{ - aiVector2D vec; +aiVector2D XGLImporter::ReadVec2(XmlNode &node) { + aiVector2D vec; + const char *s = node.value(); + ai_real v[2]; + for (int i = 0; i < 2; ++i) { + if (!SkipSpaces(&s)) { + LogError("unexpected EOL, failed to parse vec2"); + return vec; + } - if(!SkipToText()) { - LogError("unexpected EOF reading vec2 contents"); - return vec; - } - const char* s = m_reader->getNodeData(); + v[i] = fast_atof(&s); - 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; - } + SkipSpaces(&s); + if (i != 1 && *s != ',') { + LogError("expected comma, failed to parse vec2"); + return vec; + } + ++s; + } vec.x = v[0]; vec.y = v[1]; - return vec; + return vec; } // ------------------------------------------------------------------------------------------------ -aiVector3D XGLImporter::ReadVec3() -{ - aiVector3D vec; +aiVector3D XGLImporter::ReadVec3(XmlNode &node) { + aiVector3D vec; + const char *s = node.value(); + for (int i = 0; i < 3; ++i) { + if (!SkipSpaces(&s)) { + LogError("unexpected EOL, failed to parse vec3"); + return vec; + } + vec[i] = fast_atof(&s); - if(!SkipToText()) { - LogError("unexpected EOF reading vec3 contents"); - return vec; - } - const char* s = m_reader->getNodeData(); + SkipSpaces(&s); + if (i != 2 && *s != ',') { + LogError("expected comma, failed to parse vec3"); + return vec; + } + ++s; + } - 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; + 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); +aiColor3D XGLImporter::ReadCol3(XmlNode &node) { + const aiVector3D &v = ReadVec3(node); + 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); } #endif diff --git a/code/XGL/XGLLoader.h b/code/XGL/XGLLoader.h index bfa529833..e3861fe9b 100644 --- a/code/XGL/XGLLoader.h +++ b/code/XGL/XGLLoader.h @@ -53,6 +53,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include + #include #include @@ -65,16 +66,11 @@ namespace Assimp { * * Spec: http://vizstream.aveva.com/release/vsplatform/XGLSpec.htm */ -class XGLImporter : public BaseImporter, public LogFunctions -{ +class XGLImporter : public BaseImporter, public LogFunctions { public: - XGLImporter(); ~XGLImporter(); - -public: - // ------------------------------------------------------------------- /** Returns whether the class can handle the format of the given file. * See BaseImporter::CanRead() for details. */ @@ -95,8 +91,6 @@ protected: IOSystem* pIOHandler); private: - - struct TempScope { TempScope() @@ -180,34 +174,30 @@ private: }; private: - void Cleanup(); - std::string GetElementName(); - bool ReadElement(); - bool ReadElementUpToClosing(const char* closetag); - bool SkipToText(); - unsigned int ReadIDAttr(); + unsigned int ReadIDAttr(XmlNode &node); 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(); + void ReadLighting(XmlNode &node, TempScope &scope); + aiLight *ReadDirectionalLight(XmlNode &node); + aiNode *ReadObject(XmlNode &node, TempScope &scope, bool skipFirst = false, const char *closetag = "object"); + bool ReadMesh(XmlNode &node, TempScope &scope); + void ReadMaterial(XmlNode &node, TempScope &scope); + aiVector2D ReadVec2(XmlNode &node ); + aiVector3D ReadVec3(XmlNode &node ); + aiColor3D ReadCol3(XmlNode &node ); + aiMatrix4x4 ReadTrafo(XmlNode &node ); + unsigned int ReadIndexFromText(XmlNode &node); + float ReadFloat(XmlNode &node ); aiMesh* ToOutputMesh(const TempMaterialMesh& m); - void ReadFaceVertex(const TempMesh& t, TempFace& out); - unsigned int ResolveMaterialRef(TempScope& scope); + void ReadFaceVertex(XmlNode &node, const TempMesh &t, TempFace &out); + unsigned int ResolveMaterialRef(XmlNode &node, TempScope &scope); private: - std::shared_ptr m_reader; + //std::shared_ptr m_reader; + XmlParser *m_xmlParser; aiScene* m_scene; }; diff --git a/include/assimp/XmlParser.h b/include/assimp/XmlParser.h index c10cbcb34..0bfcae88f 100644 --- a/include/assimp/XmlParser.h +++ b/include/assimp/XmlParser.h @@ -51,96 +51,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 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() == NULL) { - * 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 -*/ - struct find_node_by_name_predicate { std::string mName; find_node_by_name_predicate(const std::string &name) : @@ -153,6 +63,14 @@ struct find_node_by_name_predicate { } }; +template +struct NodeConverter { +public: + static int to_int(TNodeType &node, const char *attribName ) { + ai_assert(nullptr != attribName); + return node.attribute(attribName).to_int(); + } +}; template class TXmlParser { @@ -177,6 +95,7 @@ public: if (name.empty()) { return nullptr; } + if (nullptr == mDoc) { return nullptr; } @@ -187,6 +106,7 @@ public: return nullptr; } + return &node; } TNodeType *parse(IOStream *stream) { @@ -220,6 +140,7 @@ private: }; using XmlParser = TXmlParser; +using XmlNode = pugi::xml_node; } // namespace Assimp