diff --git a/code/FBXAnimation.cpp b/code/FBXAnimation.cpp index 75319684c..3054373d8 100644 --- a/code/FBXAnimation.cpp +++ b/code/FBXAnimation.cpp @@ -66,8 +66,8 @@ AnimationCurve::AnimationCurve(uint64_t id, const Element& element, const std::s const Element& KeyTime = GetRequiredElement(sc,"KeyTime"); const Element& KeyValueFloat = GetRequiredElement(sc,"KeyValueFloat"); - ReadVectorDataArray(keys, KeyTime); - ReadVectorDataArray(values, KeyValueFloat); + ParseVectorDataArray(keys, KeyTime); + ParseVectorDataArray(values, KeyValueFloat); if(keys.size() != values.size()) { DOMError("the number of key times does not match the number of keyframe values",&KeyTime); @@ -80,12 +80,12 @@ AnimationCurve::AnimationCurve(uint64_t id, const Element& element, const std::s const Element* KeyAttrDataFloat = sc["KeyAttrDataFloat"]; if(KeyAttrDataFloat) { - ReadVectorDataArray(attributes, *KeyAttrDataFloat); + ParseVectorDataArray(attributes, *KeyAttrDataFloat); } const Element* KeyAttrFlags = sc["KeyAttrFlags"]; if(KeyAttrFlags) { - ReadVectorDataArray(flags, *KeyAttrFlags); + ParseVectorDataArray(flags, *KeyAttrFlags); } } diff --git a/code/FBXDeformer.cpp b/code/FBXDeformer.cpp index 72a222b13..6fd2ed0fa 100644 --- a/code/FBXDeformer.cpp +++ b/code/FBXDeformer.cpp @@ -97,8 +97,8 @@ Cluster::Cluster(uint64_t id, const Element& element, const Document& doc, const } if(Indexes) { - ReadVectorDataArray(indices,*Indexes); - ReadVectorDataArray(weights,*Weights); + ParseVectorDataArray(indices,*Indexes); + ParseVectorDataArray(weights,*Weights); } if(indices.size() != weights.size()) { diff --git a/code/FBXDocumentUtil.cpp b/code/FBXDocumentUtil.cpp index 7a2718a9a..6c388f62c 100644 --- a/code/FBXDocumentUtil.cpp +++ b/code/FBXDocumentUtil.cpp @@ -45,8 +45,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef ASSIMP_BUILD_NO_FBX_IMPORTER -#include - #include "FBXParser.h" #include "FBXDocument.h" #include "FBXUtil.h" @@ -96,322 +94,6 @@ void DOMWarning(const std::string& message, const Element* element /*= NULL*/) } -// ------------------------------------------------------------------------------------------------ -// extract required compound scope -const Scope& GetRequiredScope(const Element& el) -{ - const Scope* const s = el.Compound(); - if(!s) { - DOMError("expected compound scope",&el); - } - - return *s; -} - - -// ------------------------------------------------------------------------------------------------ -// get token at a particular index -const Token& GetRequiredToken(const Element& el, unsigned int index) -{ - const TokenList& t = el.Tokens(); - if(index >= t.size()) { - DOMError(Formatter::format( "missing token at index " ) << index,&el); - } - - return *t[index]; -} - - -// ------------------------------------------------------------------------------------------------ -// wrapper around ParseTokenAsID() with DOMError handling -uint64_t ParseTokenAsID(const Token& t) -{ - const char* err; - const uint64_t i = ParseTokenAsID(t,err); - if(err) { - DOMError(err,t); - } - return i; -} - - -// ------------------------------------------------------------------------------------------------ -// wrapper around ParseTokenAsDim() with DOMError handling -size_t ParseTokenAsDim(const Token& t) -{ - const char* err; - const size_t i = ParseTokenAsDim(t,err); - if(err) { - DOMError(err,t); - } - return i; -} - - -// ------------------------------------------------------------------------------------------------ -// wrapper around ParseTokenAsFloat() with DOMError handling -float ParseTokenAsFloat(const Token& t) -{ - const char* err; - const float i = ParseTokenAsFloat(t,err); - if(err) { - DOMError(err,t); - } - return i; -} - - -// ------------------------------------------------------------------------------------------------ -// wrapper around ParseTokenAsInt() with DOMError handling -int ParseTokenAsInt(const Token& t) -{ - const char* err; - const int i = ParseTokenAsInt(t,err); - if(err) { - DOMError(err,t); - } - return i; -} - - -// ------------------------------------------------------------------------------------------------ -// wrapper around ParseTokenAsString() with DOMError handling -std::string ParseTokenAsString(const Token& t) -{ - const char* err; - const std::string& i = ParseTokenAsString(t,err); - if(err) { - DOMError(err,t); - } - return i; -} - -// ------------------------------------------------------------------------------------------------ -// extract a required element from a scope, abort if the element cannot be found -const Element& GetRequiredElement(const Scope& sc, const std::string& index, const Element* element /*= NULL*/) -{ - const Element* el = sc[index]; - if(!el) { - DOMError("did not find required element \"" + index + "\"",element); - } - return *el; -} - -// XXX: tacke code duplication in the various ReadVectorDataArray() overloads below. -// could use a type traits based solution. - -// ------------------------------------------------------------------------------------------------ -// read an array of float3 tuples -void ReadVectorDataArray(std::vector& out, const Element& el) -{ - out.clear(); - const TokenList& tok = el.Tokens(); - const size_t dim = ParseTokenAsDim(*tok[0]); - - // may throw bad_alloc if the input is rubbish, but this need - // not to be prevented - importing would fail but we wouldn't - // crash since assimp handles this case properly. - out.reserve(dim); - - const Scope& scope = GetRequiredScope(el); - const Element& a = GetRequiredElement(scope,"a",&el); - - if (a.Tokens().size() % 3 != 0) { - DOMError("number of floats is not a multiple of three (3)",&el); - } - for (TokenList::const_iterator it = a.Tokens().begin(), end = a.Tokens().end(); it != end; ) { - aiVector3D v; - v.x = ParseTokenAsFloat(**it++); - v.y = ParseTokenAsFloat(**it++); - v.z = ParseTokenAsFloat(**it++); - - out.push_back(v); - } -} - - -// ------------------------------------------------------------------------------------------------ -// read an array of color4 tuples -void ReadVectorDataArray(std::vector& out, const Element& el) -{ - out.clear(); - const TokenList& tok = el.Tokens(); - const size_t dim = ParseTokenAsDim(*tok[0]); - - // see notes in ReadVectorDataArray() above - out.reserve(dim); - - const Scope& scope = GetRequiredScope(el); - const Element& a = GetRequiredElement(scope,"a",&el); - - if (a.Tokens().size() % 4 != 0) { - DOMError("number of floats is not a multiple of four (4)",&el); - } - for (TokenList::const_iterator it = a.Tokens().begin(), end = a.Tokens().end(); it != end; ) { - aiColor4D v; - v.r = ParseTokenAsFloat(**it++); - v.g = ParseTokenAsFloat(**it++); - v.b = ParseTokenAsFloat(**it++); - v.a = ParseTokenAsFloat(**it++); - - out.push_back(v); - } -} - - -// ------------------------------------------------------------------------------------------------ -// read an array of float2 tuples -void ReadVectorDataArray(std::vector& out, const Element& el) -{ - out.clear(); - const TokenList& tok = el.Tokens(); - const size_t dim = ParseTokenAsDim(*tok[0]); - - // see notes in ReadVectorDataArray() above - out.reserve(dim); - - const Scope& scope = GetRequiredScope(el); - const Element& a = GetRequiredElement(scope,"a",&el); - - if (a.Tokens().size() % 2 != 0) { - DOMError("number of floats is not a multiple of two (2)",&el); - } - for (TokenList::const_iterator it = a.Tokens().begin(), end = a.Tokens().end(); it != end; ) { - aiVector2D v; - v.x = ParseTokenAsFloat(**it++); - v.y = ParseTokenAsFloat(**it++); - - out.push_back(v); - } -} - - -// ------------------------------------------------------------------------------------------------ -// read an array of ints -void ReadVectorDataArray(std::vector& out, const Element& el) -{ - out.clear(); - const TokenList& tok = el.Tokens(); - const size_t dim = ParseTokenAsDim(*tok[0]); - - // see notes in ReadVectorDataArray() - out.reserve(dim); - - const Scope& scope = GetRequiredScope(el); - const Element& a = GetRequiredElement(scope,"a",&el); - - for (TokenList::const_iterator it = a.Tokens().begin(), end = a.Tokens().end(); it != end; ) { - const int ival = ParseTokenAsInt(**it++); - out.push_back(ival); - } -} - - -// ------------------------------------------------------------------------------------------------ -// read an array of floats -void ReadVectorDataArray(std::vector& out, const Element& el) -{ - out.clear(); - const TokenList& tok = el.Tokens(); - const size_t dim = ParseTokenAsDim(*tok[0]); - - // see notes in ReadVectorDataArray() - out.reserve(dim); - - const Scope& scope = GetRequiredScope(el); - const Element& a = GetRequiredElement(scope,"a",&el); - - for (TokenList::const_iterator it = a.Tokens().begin(), end = a.Tokens().end(); it != end; ) { - const float ival = ParseTokenAsFloat(**it++); - out.push_back(ival); - } -} - - -// ------------------------------------------------------------------------------------------------ -// read an array of uints -void ReadVectorDataArray(std::vector& out, const Element& el) -{ - out.clear(); - const TokenList& tok = el.Tokens(); - const size_t dim = ParseTokenAsDim(*tok[0]); - - // see notes in ReadVectorDataArray() - out.reserve(dim); - - const Scope& scope = GetRequiredScope(el); - const Element& a = GetRequiredElement(scope,"a",&el); - - for (TokenList::const_iterator it = a.Tokens().begin(), end = a.Tokens().end(); it != end; ) { - const int ival = ParseTokenAsInt(**it++); - if(ival < 0) { - DOMError("encountered negative integer index"); - } - out.push_back(static_cast(ival)); - } -} - - -// ------------------------------------------------------------------------------------------------ -// read an array of uint64_ts -void ReadVectorDataArray(std::vector& out, const Element& el) -{ - out.clear(); - const TokenList& tok = el.Tokens(); - const size_t dim = ParseTokenAsDim(*tok[0]); - - // see notes in ReadVectorDataArray() - out.reserve(dim); - - const Scope& scope = GetRequiredScope(el); - const Element& a = GetRequiredElement(scope,"a",&el); - - for (TokenList::const_iterator it = a.Tokens().begin(), end = a.Tokens().end(); it != end; ) { - const uint64_t ival = ParseTokenAsID(**it++); - - out.push_back(ival); - } -} - - -// ------------------------------------------------------------------------------------------------ -aiMatrix4x4 ReadMatrix(const Element& element) -{ - std::vector values; - ReadVectorDataArray(values,element); - - if(values.size() != 16) { - DOMError("expected 16 matrix elements"); - } - - aiMatrix4x4 result; - - - result.a1 = values[0]; - result.a2 = values[1]; - result.a3 = values[2]; - result.a4 = values[3]; - - result.b1 = values[4]; - result.b2 = values[5]; - result.b3 = values[6]; - result.b4 = values[7]; - - result.c1 = values[8]; - result.c2 = values[9]; - result.c3 = values[10]; - result.c4 = values[11]; - - result.d1 = values[12]; - result.d2 = values[13]; - result.d3 = values[14]; - result.d4 = values[15]; - - result.Transpose(); - return result; -} - - // ------------------------------------------------------------------------------------------------ // fetch a property table and the corresponding property template boost::shared_ptr GetPropertyTable(const Document& doc, diff --git a/code/FBXDocumentUtil.h b/code/FBXDocumentUtil.h index f563d9876..530bd9b2f 100644 --- a/code/FBXDocumentUtil.h +++ b/code/FBXDocumentUtil.h @@ -48,7 +48,8 @@ namespace Assimp { namespace FBX { namespace Util { -// does not return + +/* DOM/Parse error reporting - does not return */ void DOMError(const std::string& message, const Token& token); void DOMError(const std::string& message, const Element* element = NULL); @@ -56,51 +57,6 @@ void DOMError(const std::string& message, const Element* element = NULL); void DOMWarning(const std::string& message, const Token& token); void DOMWarning(const std::string& message, const Element* element = NULL); -// extract required compound scope -const Scope& GetRequiredScope(const Element& el); -// get token at a particular index -const Token& GetRequiredToken(const Element& el, unsigned int index); - -// wrapper around ParseTokenAsID() with DOMError handling -uint64_t ParseTokenAsID(const Token& t); -// wrapper around ParseTokenAsDim() with DOMError handling -size_t ParseTokenAsDim(const Token& t); -// wrapper around ParseTokenAsFloat() with DOMError handling -float ParseTokenAsFloat(const Token& t); -// wrapper around ParseTokenAsInt() with DOMError handling -int ParseTokenAsInt(const Token& t); -// wrapper around ParseTokenAsString() with DOMError handling -std::string ParseTokenAsString(const Token& t); - - -// extract a required element from a scope, abort if the element cannot be found -const Element& GetRequiredElement(const Scope& sc, const std::string& index, const Element* element = NULL); - -// read an array of float3 tuples -void ReadVectorDataArray(std::vector& out, const Element& el); - -// read an array of color4 tuples -void ReadVectorDataArray(std::vector& out, const Element& el); - -// read an array of float2 tuples -void ReadVectorDataArray(std::vector& out, const Element& el); - -// read an array of ints -void ReadVectorDataArray(std::vector& out, const Element& el); - -// read an array of floats -void ReadVectorDataArray(std::vector& out, const Element& el); - -// read an array of uints -void ReadVectorDataArray(std::vector& out, const Element& el); - -// read an array of uint64_t's -void ReadVectorDataArray(std::vector& out, const Element& el); - - -// read a 4x4 matrix from an array of 16 floats -aiMatrix4x4 ReadMatrix(const Element& element); - // fetch a property table and the corresponding property template boost::shared_ptr GetPropertyTable(const Document& doc, @@ -109,8 +65,6 @@ boost::shared_ptr GetPropertyTable(const Document& doc, const Scope& sc); - - // ------------------------------------------------------------------------------------------------ template inline const T* ProcessSimpleConnection(const Connection& con, diff --git a/code/FBXMeshGeometry.cpp b/code/FBXMeshGeometry.cpp index 1be98216e..84fcc2ed3 100644 --- a/code/FBXMeshGeometry.cpp +++ b/code/FBXMeshGeometry.cpp @@ -99,7 +99,7 @@ MeshGeometry::MeshGeometry(uint64_t id, const Element& element, const std::strin const ElementCollection& Layer = sc->GetCollection("Layer"); std::vector tempVerts; - ReadVectorDataArray(tempVerts,Vertices); + ParseVectorDataArray(tempVerts,Vertices); if(tempVerts.empty()) { FBXImporter::LogWarn("encountered mesh with no vertices"); @@ -107,7 +107,7 @@ MeshGeometry::MeshGeometry(uint64_t id, const Element& element, const std::strin } std::vector tempFaces; - ReadVectorDataArray(tempFaces,PolygonVertexIndex); + ParseVectorDataArray(tempFaces,PolygonVertexIndex); if(tempFaces.empty()) { FBXImporter::LogWarn("encountered mesh with no faces"); @@ -346,7 +346,7 @@ void ResolveVertexDataArray(std::vector& data_out, const Scope& source, const std::vector& mappings) { std::vector tempUV; - ReadVectorDataArray(tempUV,GetRequiredElement(source,dataElementName)); + ParseVectorDataArray(tempUV,GetRequiredElement(source,dataElementName)); // handle permutations of Mapping and Reference type - it would be nice to // deal with this more elegantly and with less redundancy, but right @@ -365,7 +365,7 @@ void ResolveVertexDataArray(std::vector& data_out, const Scope& source, data_out.resize(vertex_count); std::vector uvIndices; - ReadVectorDataArray(uvIndices,GetRequiredElement(source,indexDataElementName)); + ParseVectorDataArray(uvIndices,GetRequiredElement(source,indexDataElementName)); for (size_t i = 0, e = uvIndices.size(); i < e; ++i) { @@ -392,7 +392,7 @@ void ResolveVertexDataArray(std::vector& data_out, const Scope& source, data_out.resize(vertex_count); std::vector uvIndices; - ReadVectorDataArray(uvIndices,GetRequiredElement(source,indexDataElementName)); + ParseVectorDataArray(uvIndices,GetRequiredElement(source,indexDataElementName)); if (uvIndices.size() != vertex_count) { FBXImporter::LogError("length of input data unexpected for ByPolygonVertex mapping"); @@ -500,7 +500,7 @@ void MeshGeometry::ReadVertexDataMaterials(std::vector& materials_out, cons // materials are handled separately. First of all, they are assigned per-face // and not per polyvert. Secondly, ReferenceInformationType=IndexToDirect // has a slightly different meaning for materials. - ReadVectorDataArray(materials_out,GetRequiredElement(source,"Materials")); + ParseVectorDataArray(materials_out,GetRequiredElement(source,"Materials")); if (MappingInformationType == "AllSame") { // easy - same material for all faces diff --git a/code/FBXParser.cpp b/code/FBXParser.cpp index c6324c733..b79f5eb1a 100644 --- a/code/FBXParser.cpp +++ b/code/FBXParser.cpp @@ -57,12 +57,53 @@ using namespace Assimp::FBX; namespace { -// ------------------------------------------------------------------------------------------------ -// signal parsing error, this is always unrecoverable. Throws DeadlyImportError. -void ParseError(const std::string& message, TokenPtr token) -{ - throw DeadlyImportError(token ? Util::AddTokenText("FBX-Parse",message,token) : ("FBX-Parse " + message)); -} + + // ------------------------------------------------------------------------------------------------ + // signal parse error, this is always unrecoverable. Throws DeadlyImportError. + void ParseError(const std::string& message, const Token& token) + { + throw DeadlyImportError(Util::AddTokenText("FBX-Parser",message,&token)); + } + + // ------------------------------------------------------------------------------------------------ + void ParseError(const std::string& message, const Element* element = NULL) + { + if(element) { + ParseError(message,element->KeyToken()); + } + throw DeadlyImportError("FBX-Parser " + message); + } + + + // ------------------------------------------------------------------------------------------------ + // print warning, do return + void ParseWarning(const std::string& message, const Token& token) + { + if(DefaultLogger::get()) { + DefaultLogger::get()->warn(Util::AddTokenText("FBX-Parser",message,&token)); + } + } + + // ------------------------------------------------------------------------------------------------ + void ParseWarning(const std::string& message, const Element* element = NULL) + { + if(element) { + ParseWarning(message,element->KeyToken()); + return; + } + if(DefaultLogger::get()) { + DefaultLogger::get()->warn("FBX-Parser: " + message); + } + } + + // ------------------------------------------------------------------------------------------------ + void ParseError(const std::string& message, TokenPtr token) + { + if(token) { + ParseError(message, *token); + } + ParseError(message); + } } @@ -130,7 +171,7 @@ Scope::Scope(Parser& parser,bool topLevel) TokenPtr n = parser.AdvanceToNextToken(); if(n == NULL) { - ParseError("unexpected end of file",NULL); + ParseError("unexpected end of file"); } // note: empty scopes are allowed @@ -419,6 +460,323 @@ std::string ParseTokenAsString(const Token& t, const char*& err_out) return std::string(s+1,length-2); } + +// ------------------------------------------------------------------------------------------------ +// read an array of float3 tuples +void ParseVectorDataArray(std::vector& out, const Element& el) +{ + out.clear(); + const TokenList& tok = el.Tokens(); + const size_t dim = ParseTokenAsDim(*tok[0]); + + // may throw bad_alloc if the input is rubbish, but this need + // not to be prevented - importing would fail but we wouldn't + // crash since assimp handles this case properly. + out.reserve(dim); + + const Scope& scope = GetRequiredScope(el); + const Element& a = GetRequiredElement(scope,"a",&el); + + if (a.Tokens().size() % 3 != 0) { + ParseError("number of floats is not a multiple of three (3)",&el); + } + for (TokenList::const_iterator it = a.Tokens().begin(), end = a.Tokens().end(); it != end; ) { + aiVector3D v; + v.x = ParseTokenAsFloat(**it++); + v.y = ParseTokenAsFloat(**it++); + v.z = ParseTokenAsFloat(**it++); + + out.push_back(v); + } +} + + +// ------------------------------------------------------------------------------------------------ +// read an array of color4 tuples +void ParseVectorDataArray(std::vector& out, const Element& el) +{ + out.clear(); + const TokenList& tok = el.Tokens(); + const size_t dim = ParseTokenAsDim(*tok[0]); + + // see notes in ParseVectorDataArray() above + out.reserve(dim); + + const Scope& scope = GetRequiredScope(el); + const Element& a = GetRequiredElement(scope,"a",&el); + + if (a.Tokens().size() % 4 != 0) { + ParseError("number of floats is not a multiple of four (4)",&el); + } + for (TokenList::const_iterator it = a.Tokens().begin(), end = a.Tokens().end(); it != end; ) { + aiColor4D v; + v.r = ParseTokenAsFloat(**it++); + v.g = ParseTokenAsFloat(**it++); + v.b = ParseTokenAsFloat(**it++); + v.a = ParseTokenAsFloat(**it++); + + out.push_back(v); + } +} + + +// ------------------------------------------------------------------------------------------------ +// read an array of float2 tuples +void ParseVectorDataArray(std::vector& out, const Element& el) +{ + out.clear(); + const TokenList& tok = el.Tokens(); + const size_t dim = ParseTokenAsDim(*tok[0]); + + // see notes in ParseVectorDataArray() above + out.reserve(dim); + + const Scope& scope = GetRequiredScope(el); + const Element& a = GetRequiredElement(scope,"a",&el); + + if (a.Tokens().size() % 2 != 0) { + ParseError("number of floats is not a multiple of two (2)",&el); + } + for (TokenList::const_iterator it = a.Tokens().begin(), end = a.Tokens().end(); it != end; ) { + aiVector2D v; + v.x = ParseTokenAsFloat(**it++); + v.y = ParseTokenAsFloat(**it++); + + out.push_back(v); + } +} + + +// ------------------------------------------------------------------------------------------------ +// read an array of ints +void ParseVectorDataArray(std::vector& out, const Element& el) +{ + out.clear(); + const TokenList& tok = el.Tokens(); + const size_t dim = ParseTokenAsDim(*tok[0]); + + // see notes in ParseVectorDataArray() + out.reserve(dim); + + const Scope& scope = GetRequiredScope(el); + const Element& a = GetRequiredElement(scope,"a",&el); + + for (TokenList::const_iterator it = a.Tokens().begin(), end = a.Tokens().end(); it != end; ) { + const int ival = ParseTokenAsInt(**it++); + out.push_back(ival); + } +} + + +// ------------------------------------------------------------------------------------------------ +// read an array of floats +void ParseVectorDataArray(std::vector& out, const Element& el) +{ + out.clear(); + const TokenList& tok = el.Tokens(); + const size_t dim = ParseTokenAsDim(*tok[0]); + + // see notes in ParseVectorDataArray() + out.reserve(dim); + + const Scope& scope = GetRequiredScope(el); + const Element& a = GetRequiredElement(scope,"a",&el); + + for (TokenList::const_iterator it = a.Tokens().begin(), end = a.Tokens().end(); it != end; ) { + const float ival = ParseTokenAsFloat(**it++); + out.push_back(ival); + } +} + + +// ------------------------------------------------------------------------------------------------ +// read an array of uints +void ParseVectorDataArray(std::vector& out, const Element& el) +{ + out.clear(); + const TokenList& tok = el.Tokens(); + const size_t dim = ParseTokenAsDim(*tok[0]); + + // see notes in ParseVectorDataArray() + out.reserve(dim); + + const Scope& scope = GetRequiredScope(el); + const Element& a = GetRequiredElement(scope,"a",&el); + + for (TokenList::const_iterator it = a.Tokens().begin(), end = a.Tokens().end(); it != end; ) { + const int ival = ParseTokenAsInt(**it++); + if(ival < 0) { + ParseError("encountered negative integer index"); + } + out.push_back(static_cast(ival)); + } +} + + +// ------------------------------------------------------------------------------------------------ +// read an array of uint64_ts +void ParseVectorDataArray(std::vector& out, const Element& el) +{ + out.clear(); + const TokenList& tok = el.Tokens(); + const size_t dim = ParseTokenAsDim(*tok[0]); + + // see notes in ParseVectorDataArray() + out.reserve(dim); + + const Scope& scope = GetRequiredScope(el); + const Element& a = GetRequiredElement(scope,"a",&el); + + for (TokenList::const_iterator it = a.Tokens().begin(), end = a.Tokens().end(); it != end; ) { + const uint64_t ival = ParseTokenAsID(**it++); + + out.push_back(ival); + } +} + + +// ------------------------------------------------------------------------------------------------ +aiMatrix4x4 ReadMatrix(const Element& element) +{ + std::vector values; + ParseVectorDataArray(values,element); + + if(values.size() != 16) { + ParseError("expected 16 matrix elements"); + } + + aiMatrix4x4 result; + + + result.a1 = values[0]; + result.a2 = values[1]; + result.a3 = values[2]; + result.a4 = values[3]; + + result.b1 = values[4]; + result.b2 = values[5]; + result.b3 = values[6]; + result.b4 = values[7]; + + result.c1 = values[8]; + result.c2 = values[9]; + result.c3 = values[10]; + result.c4 = values[11]; + + result.d1 = values[12]; + result.d2 = values[13]; + result.d3 = values[14]; + result.d4 = values[15]; + + result.Transpose(); + return result; +} + + +// ------------------------------------------------------------------------------------------------ +// wrapper around ParseTokenAsString() with ParseError handling +std::string ParseTokenAsString(const Token& t) +{ + const char* err; + const std::string& i = ParseTokenAsString(t,err); + if(err) { + ParseError(err,t); + } + return i; +} + + +// ------------------------------------------------------------------------------------------------ +// extract a required element from a scope, abort if the element cannot be found +const Element& GetRequiredElement(const Scope& sc, const std::string& index, const Element* element /*= NULL*/) +{ + const Element* el = sc[index]; + if(!el) { + ParseError("did not find required element \"" + index + "\"",element); + } + return *el; +} + + +// ------------------------------------------------------------------------------------------------ +// extract required compound scope +const Scope& GetRequiredScope(const Element& el) +{ + const Scope* const s = el.Compound(); + if(!s) { + ParseError("expected compound scope",&el); + } + + return *s; +} + + +// ------------------------------------------------------------------------------------------------ +// get token at a particular index +const Token& GetRequiredToken(const Element& el, unsigned int index) +{ + const TokenList& t = el.Tokens(); + if(index >= t.size()) { + ParseError(Formatter::format( "missing token at index " ) << index,&el); + } + + return *t[index]; +} + + +// ------------------------------------------------------------------------------------------------ +// wrapper around ParseTokenAsID() with ParseError handling +uint64_t ParseTokenAsID(const Token& t) +{ + const char* err; + const uint64_t i = ParseTokenAsID(t,err); + if(err) { + ParseError(err,t); + } + return i; +} + + +// ------------------------------------------------------------------------------------------------ +// wrapper around ParseTokenAsDim() with ParseError handling +size_t ParseTokenAsDim(const Token& t) +{ + const char* err; + const size_t i = ParseTokenAsDim(t,err); + if(err) { + ParseError(err,t); + } + return i; +} + + +// ------------------------------------------------------------------------------------------------ +// wrapper around ParseTokenAsFloat() with ParseError handling +float ParseTokenAsFloat(const Token& t) +{ + const char* err; + const float i = ParseTokenAsFloat(t,err); + if(err) { + ParseError(err,t); + } + return i; +} + + +// ------------------------------------------------------------------------------------------------ +// wrapper around ParseTokenAsInt() with ParseError handling +int ParseTokenAsInt(const Token& t) +{ + const char* err; + const int i = ParseTokenAsInt(t,err); + if(err) { + ParseError(err,t); + } + return i; +} + + + } // !FBX } // !Assimp diff --git a/code/FBXParser.h b/code/FBXParser.h index 5801eb98a..e6fa25d22 100644 --- a/code/FBXParser.h +++ b/code/FBXParser.h @@ -208,6 +208,38 @@ float ParseTokenAsFloat(const Token& t, const char*& err_out); int ParseTokenAsInt(const Token& t, const char*& err_out); std::string ParseTokenAsString(const Token& t, const char*& err_out); + +/* wrapper around ParseTokenAsXXX() with DOMError handling */ +uint64_t ParseTokenAsID(const Token& t); +size_t ParseTokenAsDim(const Token& t); +float ParseTokenAsFloat(const Token& t); +int ParseTokenAsInt(const Token& t); +std::string ParseTokenAsString(const Token& t); + +/* read data arrays */ +void ParseVectorDataArray(std::vector& out, const Element& el); +void ParseVectorDataArray(std::vector& out, const Element& el); +void ParseVectorDataArray(std::vector& out, const Element& el); +void ParseVectorDataArray(std::vector& out, const Element& el); +void ParseVectorDataArray(std::vector& out, const Element& el); +void ParseVectorDataArray(std::vector& out, const Element& el); +void ParseVectorDataArray(std::vector& out, const Element& e); + + + +// extract a required element from a scope, abort if the element cannot be found +const Element& GetRequiredElement(const Scope& sc, const std::string& index, const Element* element = NULL); + +// extract required compound scope +const Scope& GetRequiredScope(const Element& el); +// get token at a particular index +const Token& GetRequiredToken(const Element& el, unsigned int index); + + + +// read a 4x4 matrix from an array of 16 floats +aiMatrix4x4 ReadMatrix(const Element& element); + } // ! FBX } // ! Assimp