- fbx: UVs, normals and materials arw now read properly. Fix bug related to reading vertices.

pull/14/head
Alexander Gessler 2012-06-28 01:49:52 +02:00
parent fcdb2fc6b8
commit 026cec7d7b
2 changed files with 62 additions and 20 deletions

View File

@ -90,7 +90,7 @@ const Scope& GetRequiredScope(const Element& el)
const Token& GetRequiredToken(const Element& el, unsigned int index) const Token& GetRequiredToken(const Element& el, unsigned int index)
{ {
const TokenList& t = el.Tokens(); const TokenList& t = el.Tokens();
if(t.size() > index) { if(index >= t.size()) {
DOMError(Formatter::format( "missing token at index " ) << index,&el); DOMError(Formatter::format( "missing token at index " ) << index,&el);
} }
@ -292,12 +292,9 @@ const Object* LazyObject::Get()
} }
// this needs to be relatively fast since we do it a lot, // this needs to be relatively fast since we do it a lot,
// so avoid constructing strings all the time. strcmp() // so avoid constructing strings all the time.
// 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(); const char* obtype = key.begin();
if (!strcmp(obtype,"Geometry")) { if (!strncmp(obtype,"Geometry",static_cast<size_t>(key.end()-key.begin()))) {
if (!strcmp(classtag.c_str(),"Mesh")) { if (!strcmp(classtag.c_str(),"Mesh")) {
object = new MeshGeometry(element,name); object = new MeshGeometry(element,name);
@ -305,7 +302,7 @@ const Object* LazyObject::Get()
} }
if (!object.get()) { if (!object.get()) {
DOMError("failed to convert element to DOM object, class: " + classtag + ", name: " + name,&element); //DOMError("failed to convert element to DOM object, class: " + classtag + ", name: " + name,&element);
} }
return object.get(); return object.get();
@ -370,11 +367,17 @@ MeshGeometry::MeshGeometry(const Element& element, const std::string& name)
mapping_counts.resize(tempVerts.size(),0); mapping_counts.resize(tempVerts.size(),0);
mappings.resize(tempFaces.size()); mappings.resize(tempFaces.size());
const size_t vertex_count = tempVerts.size();
// generate output vertices, computing an adjacency table to // generate output vertices, computing an adjacency table to
// preserve the mapping from fbx indices to *this* indexing. // preserve the mapping from fbx indices to *this* indexing.
unsigned int count = 0; unsigned int count = 0;
BOOST_FOREACH(int index, tempFaces) { BOOST_FOREACH(int index, tempFaces) {
const int absi = index < 0 ? -index : index; const int absi = index < 0 ? (-index - 1) : index;
if(static_cast<size_t>(absi) >= vertex_count) {
DOMError("polygon vertex index out of range",&PolygonVertexIndex);
}
vertices.push_back(tempVerts[absi]); vertices.push_back(tempVerts[absi]);
++count; ++count;
@ -396,7 +399,7 @@ MeshGeometry::MeshGeometry(const Element& element, const std::string& name)
cursor = 0; cursor = 0;
BOOST_FOREACH(int index, tempFaces) { BOOST_FOREACH(int index, tempFaces) {
const int absi = index < 0 ? -index : index; const int absi = index < 0 ? (-index - 1) : index;
mappings[mapping_offsets[absi] + mapping_counts[absi]++] = cursor; mappings[mapping_offsets[absi] + mapping_counts[absi]++] = cursor;
} }
@ -475,12 +478,15 @@ void MeshGeometry::ReadVertexData(const std::string& type, int index, const Scop
} }
std::vector<aiVector2D>& uv_out = uvs[index]; std::vector<aiVector2D>& uv_out = uvs[index];
uv_out.resize(vertices.size());
std::vector<aiVector2D> tempUV; std::vector<aiVector2D> tempUV;
ReadVectorDataArray(tempUV,GetRequiredElement(source,"UV")); ReadVectorDataArray(tempUV,GetRequiredElement(source,"UV"));
// handle permutations of Mapping and Reference type - it would be nice to
// deal with this more elegantly and with less redundancy, but right
// now it seems unavoidable.
if (MappingInformationType == "ByVertice" && ReferenceInformationType == "Direct") { if (MappingInformationType == "ByVertice" && ReferenceInformationType == "Direct") {
uv_out.resize(vertices.size());
for (size_t i = 0, e = tempUV.size(); i < e; ++i) { for (size_t i = 0, e = tempUV.size(); i < e; ++i) {
const unsigned int istart = mapping_offsets[i], iend = istart + mapping_counts[i]; const unsigned int istart = mapping_offsets[i], iend = istart + mapping_counts[i];
@ -490,6 +496,7 @@ void MeshGeometry::ReadVertexData(const std::string& type, int index, const Scop
} }
} }
else if (MappingInformationType == "ByVertice" && ReferenceInformationType == "IndexToDirect") { else if (MappingInformationType == "ByVertice" && ReferenceInformationType == "IndexToDirect") {
uv_out.resize(vertices.size());
std::vector<int> uvIndices; std::vector<int> uvIndices;
ReadIntDataArray(uvIndices,GetRequiredElement(source,"UVIndex")); ReadIntDataArray(uvIndices,GetRequiredElement(source,"UVIndex"));
@ -498,10 +505,41 @@ void MeshGeometry::ReadVertexData(const std::string& type, int index, const Scop
const unsigned int istart = mapping_offsets[i], iend = istart + mapping_counts[i]; const unsigned int istart = mapping_offsets[i], iend = istart + mapping_counts[i];
for (unsigned int j = istart; j < iend; ++j) { for (unsigned int j = istart; j < iend; ++j) {
if(static_cast<size_t>(uvIndices[i]) >= tempUV.size()) {
DOMError("UV index out of range",&GetRequiredElement(source,"UVIndex"));
}
uv_out[mappings[j]] = tempUV[uvIndices[i]]; uv_out[mappings[j]] = tempUV[uvIndices[i]];
} }
} }
} }
else if (MappingInformationType == "ByPolygonVertex" && ReferenceInformationType == "Direct") {
if (tempUV.size() != vertices.size()) {
FBXImporter::LogError("size of input UV array unexpected for ByPolygonVertex mapping");
return;
}
uv_out.swap(tempUV);
}
else if (MappingInformationType == "ByPolygonVertex" && ReferenceInformationType == "IndexToDirect") {
uv_out.resize(vertices.size());
std::vector<int> uvIndices;
ReadIntDataArray(uvIndices,GetRequiredElement(source,"UVIndex"));
if (uvIndices.size() != vertices.size()) {
FBXImporter::LogError("size of input UV array unexpected for ByPolygonVertex mapping");
return;
}
unsigned int next = 0;
BOOST_FOREACH(int i, uvIndices) {
if(static_cast<size_t>(i) >= tempUV.size()) {
DOMError("UV index out of range",&GetRequiredElement(source,"UVIndex"));
}
uv_out[next++] = tempUV[i];
}
}
else { else {
FBXImporter::LogError(Formatter::format("ignoring normals, unrecognized access type: ") FBXImporter::LogError(Formatter::format("ignoring normals, unrecognized access type: ")
<< MappingInformationType << "," << ReferenceInformationType); << MappingInformationType << "," << ReferenceInformationType);
@ -594,6 +632,8 @@ Document::Document(const Parser& parser)
} }
objects[id] = new LazyObject(*el.second); objects[id] = new LazyObject(*el.second);
// DEBUG - evaluate all objects
const Object* o = objects[id]->Get();
} }
} }

View File

@ -223,7 +223,7 @@ uint64_t ParseTokenAsID(const Token& t, const char*& err_out)
const char* out; const char* out;
const uint64_t id = strtoul10_64(t.begin(),&out,&length); const uint64_t id = strtoul10_64(t.begin(),&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 0L;
} }
@ -257,7 +257,7 @@ size_t ParseTokenAsDim(const Token& t, const char*& err_out)
const char* out; const char* out;
const size_t id = static_cast<size_t>(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 0; return 0;
} }
@ -278,14 +278,16 @@ float ParseTokenAsFloat(const Token& t, const char*& err_out)
const char* inout = t.begin(); const char* inout = t.begin();
float f; // need to copy the input string to a temporary buffer
fast_atof(&inout); // first - next in the fbx token stream comes ',',
if (inout != t.end()) { // which fast_atof could interpret as decimal point.
err_out = "failed to parse floating point number"; #define MAX_FLOAT_LENGTH 31
return 0.0f; char temp[MAX_FLOAT_LENGTH + 1];
} const size_t length = static_cast<size_t>(t.end()-t.begin());
std::copy(t.begin(),t.end(),temp);
temp[std::min(static_cast<size_t>(MAX_FLOAT_LENGTH),length)] = '\0';
return f; return fast_atof(temp);
} }
@ -329,7 +331,7 @@ std::string ParseTokenAsString(const Token& t, const char*& err_out)
} }
const char* s = t.begin(), *e = t.end() - 1; const char* s = t.begin(), *e = t.end() - 1;
if (*s != '\"' || *e != '\*') { if (*s != '\"' || *e != '\"') {
err_out = "expected double quoted string"; err_out = "expected double quoted string";
return ""; return "";
} }