From c0af603f0c42bff699c7e7d01e0fa60e9a70a80b Mon Sep 17 00:00:00 2001 From: Alexander Gessler Date: Tue, 26 Jun 2012 19:19:13 +0200 Subject: [PATCH] - fbx: further work on DOM, start work on geometry extraction. --- code/FBXDocument.cpp | 78 +++++++++++++++++++++++++++++++++++++++----- code/FBXDocument.h | 7 ++-- code/FBXParser.cpp | 4 +-- code/FBXParser.h | 13 ++++++-- 4 files changed, 85 insertions(+), 17 deletions(-) diff --git a/code/FBXDocument.cpp b/code/FBXDocument.cpp index 062c30170..4a895d4a8 100644 --- a/code/FBXDocument.cpp +++ b/code/FBXDocument.cpp @@ -56,10 +56,22 @@ namespace { // ------------------------------------------------------------------------------------------------ // signal DOM construction error, this is always unrecoverable. Throws DeadlyImportError. - void DOMError(const std::string& message, Element* element = NULL) + void DOMError(const std::string& message, const Element* element = NULL) { - throw DeadlyImportError(element ? Util::AddTokenText("FBX-DOM",message,element->KeyToken()) : ("FBX-DOM " + message)); + throw DeadlyImportError(element ? Util::AddTokenText("FBX-DOM",message,&element->KeyToken()) : ("FBX-DOM " + message)); } + + + // ------------------------------------------------------------------------------------------------ + // extract a required element from a scope, abort if the element cannot be found + const Element& GetFixedElementFromScope(const Scope& sc, const std::string& index, const Element* element = NULL) { + const Element* el = sc[index]; + if(!el) { + DOMError("did not find required element \"" + index + "\"",element); + } + return *el; + } + } namespace Assimp { @@ -85,13 +97,48 @@ const Object* LazyObject::Get() return object.get(); } - // XXX - return NULL; + const Token& key = element.KeyToken(); + const TokenList& tokens = element.Tokens(); + + if(tokens.size() < 3) { + DOMError("expected at least 3 tokens: id, name and class tag",&element); + } + + const char* err; + const std::string name = ParseTokenAsString(*tokens[1],err); + if (err) { + DOMError(err,&element); + } + + const std::string classtag = ParseTokenAsString(*tokens[2],err); + if (err) { + DOMError(err,&element); + } + + // this needs to be relatively fast since we do it a lot, + // so avoid constructing strings all the time. strcmp() + // may scan beyond the bounds of the token, but the + // next character is always a colon so false positives + // are not possible. + const char* obtype = key.begin(); + if (!strcmp(obtype,"Geometry")) { + + if (!strcmp(classtag.c_str(),"Mesh")) { + object = new MeshGeometry(element,name); + } + } + + if (!object.get()) { + DOMError("failed to convert element to DOM object, class: " + classtag + ", name: " + name,&element); + } + + return object.get(); } // ------------------------------------------------------------------------------------------------ -Object::Object(const Element& element) +Object::Object(const Element& element, const std::string& name) : element(element) +, name(name) { } @@ -103,8 +150,8 @@ Object::~Object() } // ------------------------------------------------------------------------------------------------ -Geometry::Geometry(const Element& element) -: Object(element) +Geometry::Geometry(const Element& element, const std::string& name) +: Object(element,name) { } @@ -116,10 +163,23 @@ Geometry::~Geometry() } // ------------------------------------------------------------------------------------------------ -MeshGeometry::MeshGeometry(const Element& element) -: Geometry(element) +MeshGeometry::MeshGeometry(const Element& element, const std::string& name) +: Geometry(element,name) { + const Scope* sc = element.Compound(); + if (!sc) { + DOMError("failed to read Geometry object (class: Mesh), no data scope found"); + } + // must have Mesh elements: + const Element& Vertices = GetFixedElementFromScope(*sc,"Vertices",&element); + const Element& PolygonVertexIndex = GetFixedElementFromScope(*sc,"PolygonVertexIndex",&element); + + // optional Mesh elements: + const ElementCollection& Layer = sc->GetCollection("Layer"); + const ElementCollection& LayerElementMaterial = sc->GetCollection("LayerElementMaterial"); + const ElementCollection& LayerElementUV = sc->GetCollection("LayerElementUV"); + const ElementCollection& LayerElementNormal = sc->GetCollection("LayerElementNormal"); } // ------------------------------------------------------------------------------------------------ diff --git a/code/FBXDocument.h b/code/FBXDocument.h index cb5d0fdfd..558863704 100644 --- a/code/FBXDocument.h +++ b/code/FBXDocument.h @@ -88,13 +88,14 @@ class Object { public: - Object(const Element& element); + Object(const Element& element, const std::string& name); ~Object(); public: protected: const Element& element; + const std::string name; }; @@ -103,7 +104,7 @@ class Geometry : public Object { public: - Geometry(const Element& element); + Geometry(const Element& element, const std::string& name); ~Geometry(); }; @@ -114,7 +115,7 @@ class MeshGeometry : public Geometry public: - MeshGeometry(const Element& element); + MeshGeometry(const Element& element, const std::string& name); ~MeshGeometry(); public: diff --git a/code/FBXParser.cpp b/code/FBXParser.cpp index a10d70adc..5918177b1 100644 --- a/code/FBXParser.cpp +++ b/code/FBXParser.cpp @@ -70,7 +70,7 @@ namespace Assimp { namespace FBX { // ------------------------------------------------------------------------------------------------ -Element::Element(TokenPtr key_token, Parser& parser) +Element::Element(const Token& key_token, Parser& parser) : key_token(key_token) { TokenPtr n = NULL; @@ -140,7 +140,7 @@ Scope::Scope(Parser& parser,bool topLevel) } const std::string& str = n->StringContents(); - elements.insert(ElementMap::value_type(str,new_Element(n,parser))); + elements.insert(ElementMap::value_type(str,new_Element(*n,parser))); // Element() should stop at the next Key token (or right after a Close token) n = parser.CurrentToken(); diff --git a/code/FBXParser.h b/code/FBXParser.h index 94a0560bd..385028954 100644 --- a/code/FBXParser.h +++ b/code/FBXParser.h @@ -47,6 +47,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include +#include #include @@ -66,6 +67,8 @@ namespace FBX { typedef std::vector< Scope* > ScopeList; typedef std::fbx_unordered_multimap< std::string, Element* > ElementMap; + typedef std::pair ElementCollection; + # define new_Scope new Scope # define new_Element new Element @@ -85,7 +88,7 @@ class Element { public: - Element(TokenPtr key_token, Parser& parser); + Element(const Token& key_token, Parser& parser); ~Element(); public: @@ -94,7 +97,7 @@ public: return compound.get(); } - TokenPtr KeyToken() const { + const Token& KeyToken() const { return key_token; } @@ -104,7 +107,7 @@ public: private: - TokenPtr key_token; + const Token& key_token; TokenList tokens; boost::scoped_ptr compound; }; @@ -137,6 +140,10 @@ public: return it == elements.end() ? NULL : (*it).second; } + ElementCollection GetCollection(const std::string& index) const { + return elements.equal_range(index); + } + const ElementMap& Elements() const { return elements; }