From 7adfe1f2d85b358831d4fe75947f0a71b4595884 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Fri, 21 Aug 2020 06:45:30 +0200 Subject: [PATCH] Xml: introduce helper for attribute parsing. --- code/AssetLib/Collada/ColladaParser.cpp | 57 +++++++++++-- code/AssetLib/Collada/ColladaParser.h | 1 - include/assimp/XmlParser.h | 102 ++++++++++++++---------- 3 files changed, 111 insertions(+), 49 deletions(-) diff --git a/code/AssetLib/Collada/ColladaParser.cpp b/code/AssetLib/Collada/ColladaParser.cpp index 9b3f46613..21d56365c 100644 --- a/code/AssetLib/Collada/ColladaParser.cpp +++ b/code/AssetLib/Collada/ColladaParser.cpp @@ -246,19 +246,18 @@ ai_real ColladaParser::ReadFloatFromTextContent() { // Reads the contents of the file void ColladaParser::ReadContents(XmlNode &node) { for (pugi::xml_node &curNode : node.children()) { - pugi::xml_attribute attr = curNode.attribute("version"); - if (attr) { - const char *version = attr.as_string(); + std::string version; + if (XmlParser::getStdStrAttribute(curNode, "version", version)) { aiString v; - v.Set(version); + v.Set(version.c_str()); mAssetMetaData.emplace(AI_METADATA_SOURCE_FORMAT_VERSION, v); - if (!::strncmp(version, "1.5", 3)) { + if (!::strncmp(version.c_str(), "1.5", 3)) { mFormat = FV_1_5_n; ASSIMP_LOG_DEBUG("Collada schema version is 1.5.n"); - } else if (!::strncmp(version, "1.4", 3)) { + } else if (!::strncmp(version.c_str(), "1.4", 3)) { mFormat = FV_1_4_n; ASSIMP_LOG_DEBUG("Collada schema version is 1.4.n"); - } else if (!::strncmp(version, "1.3", 3)) { + } else if (!::strncmp(version.c_str(), "1.3", 3)) { mFormat = FV_1_3_n; ASSIMP_LOG_DEBUG("Collada schema version is 1.3.n"); } @@ -1244,6 +1243,50 @@ void ColladaParser::ReadEffectColor(XmlNode &node, aiColor4D &pColor, Sampler &p return; } + for (XmlNode ¤tNode : node.children()) { + const std::string ¤tName = currentNode.name(); + if (currentName == "color") { + // text content contains 4 floats + const char *content = currentNode.value(); + + content = fast_atoreal_move(content, (ai_real &)pColor.r); + SkipSpacesAndLineEnd(&content); + + content = fast_atoreal_move(content, (ai_real &)pColor.g); + SkipSpacesAndLineEnd(&content); + + content = fast_atoreal_move(content, (ai_real &)pColor.b); + SkipSpacesAndLineEnd(&content); + + content = fast_atoreal_move(content, (ai_real &)pColor.a); + SkipSpacesAndLineEnd(&content); + } else if (currentName == "texture") { + // get name of source texture/sampler + int attrTex = GetAttribute("texture"); + pSampler.mName = mReader->getAttributeValue(attrTex); + + // get name of UV source channel. Specification demands it to be there, but some exporters + // don't write it. It will be the default UV channel in case it's missing. + attrTex = TestAttribute("texcoord"); + if (attrTex >= 0) + pSampler.mUVChannel = mReader->getAttributeValue(attrTex); + //SkipElement(); + + // as we've read texture, the color needs to be 1,1,1,1 + pColor = aiColor4D(1.f, 1.f, 1.f, 1.f); + } else if (currentName == "technique" ) { + const int _profile = GetAttribute("profile"); + const char *profile = mReader->getAttributeValue(_profile); + + // Some extensions are quite useful ... ReadSamplerProperties processes + // several extensions in MAYA, OKINO and MAX3D profiles. + if (!::strcmp(profile, "MAYA") || !::strcmp(profile, "MAX3D") || !::strcmp(profile, "OKINO")) { + // get more information on this sampler + ReadSamplerProperties(pSampler); + } + } + } + // Save current element name const std::string curElem = mReader->getNodeName(); diff --git a/code/AssetLib/Collada/ColladaParser.h b/code/AssetLib/Collada/ColladaParser.h index 58044e479..e5b1e5971 100644 --- a/code/AssetLib/Collada/ColladaParser.h +++ b/code/AssetLib/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, diff --git a/include/assimp/XmlParser.h b/include/assimp/XmlParser.h index 0738df871..a5c9729c1 100644 --- a/include/assimp/XmlParser.h +++ b/include/assimp/XmlParser.h @@ -52,22 +52,22 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. namespace Assimp { struct find_node_by_name_predicate { - std::string mName; - find_node_by_name_predicate(const std::string &name) : - mName(name) { + std::string mName; + find_node_by_name_predicate(const std::string &name) : + mName(name) { // empty - } + } - bool operator()(pugi::xml_node node) const { - return node.name() == mName; - } + bool operator()(pugi::xml_node node) const { + return node.name() == mName; + } }; -template +template struct NodeConverter { public: - static int to_int(TNodeType &node, const char *attribName ) { - ai_assert(nullptr != attribName); + static int to_int(TNodeType &node, const char *attribName) { + ai_assert(nullptr != attribName); return node.attribute(attribName).to_int(); } }; @@ -75,72 +75,73 @@ public: using XmlNode = pugi::xml_node; using XmlAttribute = pugi::xml_attribute; -template +template class TXmlParser { public: - TXmlParser() : - mDoc(nullptr), mRoot(nullptr), mData() { + TXmlParser() : + mDoc(nullptr), + mRoot(nullptr), + mData() { // empty - } + } ~TXmlParser() { - clear(); + clear(); } void clear() { - mData.resize(0); - mRoot = nullptr; - delete mDoc; - mDoc = nullptr; + mData.resize(0); + mRoot = nullptr; + delete mDoc; + mDoc = nullptr; } TNodeType *findNode(const std::string &name) { - if (name.empty()) { - return nullptr; - } + if (name.empty()) { + return nullptr; + } - if (nullptr == mDoc) { - return nullptr; + if (nullptr == mDoc) { + return nullptr; } find_node_by_name_predicate predicate(name); mCurrent = mDoc->find_node(predicate); if (mCurrent.empty()) { - return nullptr; + return nullptr; } return &mCurrent; } - bool hasNode( const std::string &name ) { + bool hasNode(const std::string &name) { return nullptr != findNode(name); } TNodeType *parse(IOStream *stream) { - if (nullptr == stream) { - return nullptr; - } + if (nullptr == stream) { + return nullptr; + } mData.resize(stream->FileSize()); - stream->Read(&mData[0], mData.size(), 1); - mDoc = new pugi::xml_document(); - pugi::xml_parse_result result = mDoc->load_string(&mData[0]); + stream->Read(&mData[0], mData.size(), 1); + mDoc = new pugi::xml_document(); + pugi::xml_parse_result result = mDoc->load_string(&mData[0]); if (result.status == pugi::status_ok) { pugi::xml_node root = *(mDoc->children().begin()); - + mRoot = &root; - //mRoot = &mDoc->root(); } return mRoot; } pugi::xml_document *getDocument() const { - return mDoc; + return mDoc; } const TNodeType *getRootNode() const { - return mRoot; + return mRoot; } TNodeType *getRootNode() { @@ -157,16 +158,35 @@ public: return !attr.empty(); } - private: - pugi::xml_document *mDoc; - TNodeType *mRoot; + static inline bool getIntAttribute(XmlNode &xmlNode, const char *name, int &val ) { + pugi::xml_attribute attr = xmlNode.attribute(name); + if (attr.empty()) { + return false; + } + + val = attr.as_int(); + return true; + } + + static inline bool getStdStrAttribute(XmlNode &xmlNode, const char *name, std::string &val) { + pugi::xml_attribute attr = xmlNode.attribute(name); + if (attr.empty()) { + return false; + } + + val = attr.as_string(); + return true; + } + +private: + pugi::xml_document *mDoc; + TNodeType *mRoot; TNodeType mCurrent; - std::vector mData; + std::vector mData; }; using XmlParser = TXmlParser; - } // namespace Assimp #endif // !! INCLUDED_AI_IRRXML_WRAPPER