- fbx: add helper functions to read FBX data arrays.
parent
c0af603f0c
commit
a996ecba75
|
@ -64,7 +64,8 @@ namespace {
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
// extract a required element from a scope, abort if the element cannot be found
|
// 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];
|
const Element* el = sc[index];
|
||||||
if(!el) {
|
if(!el) {
|
||||||
DOMError("did not find required element \"" + index + "\"",element);
|
DOMError("did not find required element \"" + index + "\"",element);
|
||||||
|
@ -72,6 +73,88 @@ namespace {
|
||||||
return *el;
|
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 {
|
namespace Assimp {
|
||||||
|
@ -180,6 +263,11 @@ MeshGeometry::MeshGeometry(const Element& element, const std::string& name)
|
||||||
const ElementCollection& LayerElementMaterial = sc->GetCollection("LayerElementMaterial");
|
const ElementCollection& LayerElementMaterial = sc->GetCollection("LayerElementMaterial");
|
||||||
const ElementCollection& LayerElementUV = sc->GetCollection("LayerElementUV");
|
const ElementCollection& LayerElementUV = sc->GetCollection("LayerElementUV");
|
||||||
const ElementCollection& LayerElementNormal = sc->GetCollection("LayerElementNormal");
|
const ElementCollection& LayerElementNormal = sc->GetCollection("LayerElementNormal");
|
||||||
|
|
||||||
|
ReadVectorDataArray(vertices,Vertices);
|
||||||
|
|
||||||
|
std::vector<int> tempFaces;
|
||||||
|
ReadIntDataArray(tempFaces,PolygonVertexIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
|
|
@ -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
|
// same as ID parsing, except there is a trailing asterisk
|
||||||
err_out = NULL;
|
err_out = NULL;
|
||||||
|
|
||||||
if (t.Type() != TokenType_DATA) {
|
if (t.Type() != TokenType_DATA) {
|
||||||
err_out = "expected TOK_DATA token";
|
err_out = "expected TOK_DATA token";
|
||||||
return 0L;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(*t.begin() != '*') {
|
if(*t.begin() != '*') {
|
||||||
err_out = "expected asterisk before array dimension";
|
err_out = "expected asterisk before array dimension";
|
||||||
return 0L;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// XXX: should use size_t here
|
// XXX: should use size_t here
|
||||||
unsigned int length = static_cast<unsigned int>(t.end() - t.begin());
|
unsigned int length = static_cast<unsigned int>(t.end() - t.begin());
|
||||||
if(length == 0) {
|
if(length == 0) {
|
||||||
err_out = "expected valid integer number after asterisk";
|
err_out = "expected valid integer number after asterisk";
|
||||||
return 0L;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* out;
|
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()) {
|
if (out != t.end()) {
|
||||||
err_out = "failed to parse ID";
|
err_out = "failed to parse ID";
|
||||||
return 0L;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return id;
|
return id;
|
||||||
|
|
|
@ -193,7 +193,7 @@ private:
|
||||||
|
|
||||||
/* token parsing - this happens when building the DOM out of the parse-tree*/
|
/* 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 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);
|
float ParseTokenAsFloat(const Token& t, const char*& err_out);
|
||||||
int ParseTokenAsInt(const Token& t, const char*& err_out);
|
int ParseTokenAsInt(const Token& t, const char*& err_out);
|
||||||
|
|
Loading…
Reference in New Issue