- fbx: further work on DOM, start work on geometry extraction.

pull/14/head
Alexander Gessler 2012-06-26 19:19:13 +02:00
parent 25dfbdf58d
commit c0af603f0c
4 changed files with 85 additions and 17 deletions

View File

@ -56,10 +56,22 @@ namespace {
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// signal DOM construction error, this is always unrecoverable. Throws DeadlyImportError. // 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 { namespace Assimp {
@ -85,13 +97,48 @@ const Object* LazyObject::Get()
return object.get(); return object.get();
} }
// XXX const Token& key = element.KeyToken();
return NULL; 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) : element(element)
, name(name)
{ {
} }
@ -103,8 +150,8 @@ Object::~Object()
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
Geometry::Geometry(const Element& element) Geometry::Geometry(const Element& element, const std::string& name)
: Object(element) : Object(element,name)
{ {
} }
@ -116,10 +163,23 @@ Geometry::~Geometry()
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
MeshGeometry::MeshGeometry(const Element& element) MeshGeometry::MeshGeometry(const Element& element, const std::string& name)
: Geometry(element) : 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");
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------

View File

@ -88,13 +88,14 @@ class Object
{ {
public: public:
Object(const Element& element); Object(const Element& element, const std::string& name);
~Object(); ~Object();
public: public:
protected: protected:
const Element& element; const Element& element;
const std::string name;
}; };
@ -103,7 +104,7 @@ class Geometry : public Object
{ {
public: public:
Geometry(const Element& element); Geometry(const Element& element, const std::string& name);
~Geometry(); ~Geometry();
}; };
@ -114,7 +115,7 @@ class MeshGeometry : public Geometry
public: public:
MeshGeometry(const Element& element); MeshGeometry(const Element& element, const std::string& name);
~MeshGeometry(); ~MeshGeometry();
public: public:

View File

@ -70,7 +70,7 @@ namespace Assimp {
namespace FBX { namespace FBX {
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
Element::Element(TokenPtr key_token, Parser& parser) Element::Element(const Token& key_token, Parser& parser)
: key_token(key_token) : key_token(key_token)
{ {
TokenPtr n = NULL; TokenPtr n = NULL;
@ -140,7 +140,7 @@ Scope::Scope(Parser& parser,bool topLevel)
} }
const std::string& str = n->StringContents(); 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) // Element() should stop at the next Key token (or right after a Close token)
n = parser.CurrentToken(); n = parser.CurrentToken();

View File

@ -47,6 +47,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <vector> #include <vector>
#include <map> #include <map>
#include <string> #include <string>
#include <utility>
#include <boost/shared_ptr.hpp> #include <boost/shared_ptr.hpp>
@ -66,6 +67,8 @@ namespace FBX {
typedef std::vector< Scope* > ScopeList; typedef std::vector< Scope* > ScopeList;
typedef std::fbx_unordered_multimap< std::string, Element* > ElementMap; typedef std::fbx_unordered_multimap< std::string, Element* > ElementMap;
typedef std::pair<ElementMap::const_iterator,ElementMap::const_iterator> ElementCollection;
# define new_Scope new Scope # define new_Scope new Scope
# define new_Element new Element # define new_Element new Element
@ -85,7 +88,7 @@ class Element
{ {
public: public:
Element(TokenPtr key_token, Parser& parser); Element(const Token& key_token, Parser& parser);
~Element(); ~Element();
public: public:
@ -94,7 +97,7 @@ public:
return compound.get(); return compound.get();
} }
TokenPtr KeyToken() const { const Token& KeyToken() const {
return key_token; return key_token;
} }
@ -104,7 +107,7 @@ public:
private: private:
TokenPtr key_token; const Token& key_token;
TokenList tokens; TokenList tokens;
boost::scoped_ptr<Scope> compound; boost::scoped_ptr<Scope> compound;
}; };
@ -137,6 +140,10 @@ public:
return it == elements.end() ? NULL : (*it).second; return it == elements.end() ? NULL : (*it).second;
} }
ElementCollection GetCollection(const std::string& index) const {
return elements.equal_range(index);
}
const ElementMap& Elements() const { const ElementMap& Elements() const {
return elements; return elements;
} }