Răsfoiți Sursa

- fbx: add helper functions to read FBX data arrays.

Alexander Gessler 13 ani în urmă
părinte
comite
a996ecba75
3 a modificat fișierele cu 96 adăugiri și 8 ștergeri
  1. 89 1
      code/FBXDocument.cpp
  2. 6 6
      code/FBXParser.cpp
  3. 1 1
      code/FBXParser.h

+ 89 - 1
code/FBXDocument.cpp

@@ -64,7 +64,8 @@ namespace {
 
 	// ------------------------------------------------------------------------------------------------
 	// 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& 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);
@@ -72,6 +73,88 @@ namespace {
 		return *el;
 	}
 
+
+	// ------------------------------------------------------------------------------------------------
+	// read an array of float3 tuples
+	void ReadVectorDataArray(std::vector<aiVector3D>& out, const Element& el)
+	{
+		out.clear();
+		const TokenList& tok = el.Tokens();
+
+		const char* err;
+		const size_t dim = ParseTokenAsDim(*tok[0],err);
+		if(err) {
+			DOMError(err,&el);
+		}
+
+		// 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* const scope = el.Compound();
+		if(!scope) {
+			DOMError("expected vector3 data",&el);
+		}
+
+		const Element& a = GetFixedElementFromScope(*scope,"a",&el);
+		if (a.Tokens().size() % 3 != 0) {
+			DOMError("number of floats is not a multiple of three",&el);
+		}
+		for (TokenList::const_iterator it = a.Tokens().begin(), end = a.Tokens().end(); it != end; ) {
+			aiVector3D v;
+			v.x = ParseTokenAsFloat(**it++,err);
+			if(err) {
+				DOMError(err,&el);
+			}
+
+			v.y = ParseTokenAsFloat(**it++,err);
+			if(err) {
+				DOMError(err,&el);
+			}
+
+			v.z = ParseTokenAsFloat(**it++,err);
+			if(err) {
+				DOMError(err,&el);
+			}
+
+			out.push_back(v);
+		}
+	}
+
+
+	// ------------------------------------------------------------------------------------------------
+	// read an array of ints
+	void ReadIntDataArray(std::vector<int>& out, const Element& el)
+	{
+		out.clear();
+		const TokenList& tok = el.Tokens();
+
+		const char* err;
+		const size_t dim = ParseTokenAsDim(*tok[0],err);
+		if(err) {
+			DOMError(err,&el);
+		}
+
+		// see notes in ReadVectorDataArray()
+		out.reserve(dim);
+
+		const Scope* const scope = el.Compound();
+		if(!scope) {
+			DOMError("expected int data block",&el);
+		}
+
+		const Element& a = GetFixedElementFromScope(*scope,"a",&el);
+		for (TokenList::const_iterator it = a.Tokens().begin(), end = a.Tokens().end(); it != end; ) {
+			const int ival = ParseTokenAsInt(**it++,err);
+			if(err) {
+				DOMError(err,&el);
+			}
+
+			out.push_back(ival);
+		}
+	}
+
 }
 
 namespace Assimp {
@@ -180,6 +263,11 @@ MeshGeometry::MeshGeometry(const Element& element, const std::string& name)
 	const ElementCollection& LayerElementMaterial = sc->GetCollection("LayerElementMaterial");
 	const ElementCollection& LayerElementUV = sc->GetCollection("LayerElementUV");
 	const ElementCollection& LayerElementNormal = sc->GetCollection("LayerElementNormal");
+
+	ReadVectorDataArray(vertices,Vertices);
+
+	std::vector<int> tempFaces;
+	ReadIntDataArray(tempFaces,PolygonVertexIndex);
 }
 
 // ------------------------------------------------------------------------------------------------

+ 6 - 6
code/FBXParser.cpp

@@ -233,33 +233,33 @@ uint64_t ParseTokenAsID(const Token& t, const char*& err_out)
 
 
 // ------------------------------------------------------------------------------------------------
-uint64_t ParseTokenAsDim(const Token& t, const char*& err_out)
+size_t ParseTokenAsDim(const Token& t, const char*& err_out)
 {
 	// same as ID parsing, except there is a trailing asterisk
 	err_out = NULL;
 
 	if (t.Type() != TokenType_DATA) {
 		err_out = "expected TOK_DATA token";
-		return 0L;
+		return 0;
 	}
 
 	if(*t.begin() != '*') {
 		err_out = "expected asterisk before array dimension";
-		return 0L;
+		return 0;
 	}
 
 	// XXX: should use size_t here
 	unsigned int length = static_cast<unsigned int>(t.end() - t.begin());
 	if(length == 0) {
 		err_out = "expected valid integer number after asterisk";
-		return 0L;
+		return 0;
 	}
 
 	const char* out;
-	const uint64_t id = strtoul10_64(t.begin() + 1,&out,&length);
+	const size_t id = static_cast<size_t>(strtoul10_64(t.begin() + 1,&out,&length));
 	if (out != t.end()) {
 		err_out = "failed to parse ID";
-		return 0L;
+		return 0;
 	}
 
 	return id;

+ 1 - 1
code/FBXParser.h

@@ -193,7 +193,7 @@ private:
 
 /* token parsing - this happens when building the DOM out of the parse-tree*/
 uint64_t ParseTokenAsID(const Token& t, const char*& err_out);
-uint64_t ParseTokenAsDim(const Token& t, const char*& err_out);
+size_t ParseTokenAsDim(const Token& t, const char*& err_out);
 
 float ParseTokenAsFloat(const Token& t, const char*& err_out);
 int ParseTokenAsInt(const Token& t, const char*& err_out);