- fbx: work on reading vertex data.
parent
f354d8d7c7
commit
f9e310edfb
|
@ -57,9 +57,18 @@ 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, const Token& token)
|
||||||
|
{
|
||||||
|
throw DeadlyImportError(Util::AddTokenText("FBX-DOM",message,&token));
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
void DOMError(const std::string& message, const 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));
|
if(element) {
|
||||||
|
DOMError(message,element->KeyToken());
|
||||||
|
}
|
||||||
|
throw DeadlyImportError("FBX-DOM " + message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -77,11 +86,11 @@ namespace {
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
// extract required compound scope
|
// extract required compound scope
|
||||||
const Scope& GetRequiredScope(const Element& el, const Element* element = NULL)
|
const Scope& GetRequiredScope(const Element& el)
|
||||||
{
|
{
|
||||||
const Scope* const s = el.Compound();
|
const Scope* const s = el.Compound();
|
||||||
if(!s) {
|
if(!s) {
|
||||||
DOMError("expected compound scope",element);
|
DOMError("expected compound scope",&el);
|
||||||
}
|
}
|
||||||
|
|
||||||
return *s;
|
return *s;
|
||||||
|
@ -90,11 +99,11 @@ namespace {
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
// get token at a particular index
|
// get token at a particular index
|
||||||
const Token& GetRequiredToken(const Element& el, unsigned int index, const Element* element = NULL)
|
const Token& GetRequiredToken(const Element& el, unsigned int index)
|
||||||
{
|
{
|
||||||
const TokenList& t = el.Tokens();
|
const TokenList& t = el.Tokens();
|
||||||
if(t.size() > index) {
|
if(t.size() > index) {
|
||||||
DOMError(Formatter::format( "missing token at index " ) << index,element);
|
DOMError(Formatter::format( "missing token at index " ) << index,&el);
|
||||||
}
|
}
|
||||||
|
|
||||||
return *t[index];
|
return *t[index];
|
||||||
|
@ -189,12 +198,12 @@ namespace FBX {
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
// wrapper around ParseTokenAsID() with DOMError handling
|
// wrapper around ParseTokenAsID() with DOMError handling
|
||||||
uint64_t ParseTokenAsID(const Token& t, const Element* element = NULL)
|
uint64_t ParseTokenAsID(const Token& t)
|
||||||
{
|
{
|
||||||
const char* err;
|
const char* err;
|
||||||
const uint64_t i = ParseTokenAsID(t,err);
|
const uint64_t i = ParseTokenAsID(t,err);
|
||||||
if(err) {
|
if(err) {
|
||||||
DOMError(err,element);
|
DOMError(err,t);
|
||||||
}
|
}
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
@ -202,12 +211,12 @@ uint64_t ParseTokenAsID(const Token& t, const Element* element = NULL)
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
// wrapper around ParseTokenAsDim() with DOMError handling
|
// wrapper around ParseTokenAsDim() with DOMError handling
|
||||||
size_t ParseTokenAsDim(const Token& t, const Element* element = NULL)
|
size_t ParseTokenAsDim(const Token& t)
|
||||||
{
|
{
|
||||||
const char* err;
|
const char* err;
|
||||||
const size_t i = ParseTokenAsDim(t,err);
|
const size_t i = ParseTokenAsDim(t,err);
|
||||||
if(err) {
|
if(err) {
|
||||||
DOMError(err,element);
|
DOMError(err,t);
|
||||||
}
|
}
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
@ -215,12 +224,12 @@ size_t ParseTokenAsDim(const Token& t, const Element* element = NULL)
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
// wrapper around ParseTokenAsFloat() with DOMError handling
|
// wrapper around ParseTokenAsFloat() with DOMError handling
|
||||||
float ParseTokenAsFloat(const Token& t, const Element* element = NULL)
|
float ParseTokenAsFloat(const Token& t)
|
||||||
{
|
{
|
||||||
const char* err;
|
const char* err;
|
||||||
const float i = ParseTokenAsFloat(t,err);
|
const float i = ParseTokenAsFloat(t,err);
|
||||||
if(err) {
|
if(err) {
|
||||||
DOMError(err,element);
|
DOMError(err,t);
|
||||||
}
|
}
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
@ -228,12 +237,12 @@ float ParseTokenAsFloat(const Token& t, const Element* element = NULL)
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
// wrapper around ParseTokenAsInt() with DOMError handling
|
// wrapper around ParseTokenAsInt() with DOMError handling
|
||||||
int ParseTokenAsInt(const Token& t, const Element* element = NULL)
|
int ParseTokenAsInt(const Token& t)
|
||||||
{
|
{
|
||||||
const char* err;
|
const char* err;
|
||||||
const int i = ParseTokenAsInt(t,err);
|
const int i = ParseTokenAsInt(t,err);
|
||||||
if(err) {
|
if(err) {
|
||||||
DOMError(err,element);
|
DOMError(err,t);
|
||||||
}
|
}
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
@ -241,12 +250,12 @@ int ParseTokenAsInt(const Token& t, const Element* element = NULL)
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
// wrapper around ParseTokenAsString() with DOMError handling
|
// wrapper around ParseTokenAsString() with DOMError handling
|
||||||
std::string ParseTokenAsString(const Token& t, const Element* element = NULL)
|
std::string ParseTokenAsString(const Token& t)
|
||||||
{
|
{
|
||||||
const char* err;
|
const char* err;
|
||||||
const std::string& i = ParseTokenAsString(t,err);
|
const std::string& i = ParseTokenAsString(t,err);
|
||||||
if(err) {
|
if(err) {
|
||||||
DOMError(err,element);
|
DOMError(err,t);
|
||||||
}
|
}
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
@ -371,20 +380,8 @@ MeshGeometry::MeshGeometry(const Element& element, const std::string& name)
|
||||||
}
|
}
|
||||||
|
|
||||||
if(index == 0) {
|
if(index == 0) {
|
||||||
const Scope& layer = GetRequiredScope(*(*it).second,&element);
|
const Scope& layer = GetRequiredScope(*(*it).second);
|
||||||
|
ReadLayer(layer);
|
||||||
const ElementCollection& LayerElement = sc->GetCollection("LayerElement");
|
|
||||||
for (ElementMap::const_iterator eit = LayerElement.first; eit != LayerElement.second; ++eit) {
|
|
||||||
const Scope& elayer = GetRequiredScope(*(*eit).second,&element);
|
|
||||||
|
|
||||||
const Element& Type = GetRequiredElement(elayer,"Type",&element);
|
|
||||||
const Element& TypedIndex = GetRequiredElement(elayer,"TypedIndex",&element);
|
|
||||||
|
|
||||||
const std::string& type = ParseTokenAsString(GetRequiredToken(Type,0),&Type);
|
|
||||||
const std::string& typedIndex = ParseTokenAsString(GetRequiredToken(TypedIndex,0),&Type);
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
FBXImporter::LogWarn("ignoring additional geometry layers");
|
FBXImporter::LogWarn("ignoring additional geometry layers");
|
||||||
|
@ -392,6 +389,66 @@ MeshGeometry::MeshGeometry(const Element& element, const std::string& name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
void MeshGeometry::ReadLayer(const Scope& layer)
|
||||||
|
{
|
||||||
|
const ElementCollection& LayerElement = layer.GetCollection("LayerElement");
|
||||||
|
for (ElementMap::const_iterator eit = LayerElement.first; eit != LayerElement.second; ++eit) {
|
||||||
|
const Scope& elayer = GetRequiredScope(*(*eit).second);
|
||||||
|
|
||||||
|
ReadLayerElement(elayer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
void MeshGeometry::ReadLayerElement(const Scope& layerElement)
|
||||||
|
{
|
||||||
|
const Element& Type = GetRequiredElement(layerElement,"Type");
|
||||||
|
const Element& TypedIndex = GetRequiredElement(layerElement,"TypedIndex");
|
||||||
|
|
||||||
|
const std::string& type = ParseTokenAsString(GetRequiredToken(Type,0));
|
||||||
|
const int typedIndex = ParseTokenAsInt(GetRequiredToken(TypedIndex,0));
|
||||||
|
|
||||||
|
const Scope& top = GetRequiredScope(element);
|
||||||
|
const ElementCollection candidates = top.GetCollection(type);
|
||||||
|
|
||||||
|
for (ElementMap::const_iterator it = candidates.first; it != candidates.second; ++it) {
|
||||||
|
const int index = ParseTokenAsInt(GetRequiredToken(*(*it).second,0));
|
||||||
|
if(index == typedIndex) {
|
||||||
|
ReadVertexData(type,typedIndex,GetRequiredScope(*(*it).second));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FBXImporter::LogError(Formatter::format("failed to resolve vertex layer element: ")
|
||||||
|
<< type << ", index: " << typedIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
void MeshGeometry::ReadVertexData(const std::string& type, int index, const Scope& source)
|
||||||
|
{
|
||||||
|
const std::string& MappingInformationType = ParseTokenAsString(GetRequiredToken(GetRequiredElement(source,"MappingInformationType"),0));
|
||||||
|
const std::string& ReferenceInformationType = ParseTokenAsString(GetRequiredToken(GetRequiredElement(source,"ReferenceInformationType"),0));
|
||||||
|
|
||||||
|
if (type == "LayerElementUV") {
|
||||||
|
if(index >= AI_MAX_NUMBER_OF_TEXTURECOORDS) {
|
||||||
|
FBXImporter::LogError(Formatter::format("ignoring UV layer, maximum UV number exceeded: ")
|
||||||
|
<< index << " (limit is " << AI_MAX_NUMBER_OF_TEXTURECOORDS << ")" );
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::vector<aiVector2D>& uv = uvs[index];
|
||||||
|
}
|
||||||
|
else if (type == "LayerElementMaterial") {
|
||||||
|
|
||||||
|
}
|
||||||
|
else if (type == "LayerElementNormal") {
|
||||||
|
|
||||||
|
ReadVectorDataArray(normals,GetRequiredElement(source,"Normals"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
MeshGeometry::~MeshGeometry()
|
MeshGeometry::~MeshGeometry()
|
||||||
{
|
{
|
||||||
|
|
|
@ -146,8 +146,8 @@ public:
|
||||||
|
|
||||||
/** Get a UV coordinate slot, returns an empty array if
|
/** Get a UV coordinate slot, returns an empty array if
|
||||||
* the requested slot does not exist. */
|
* the requested slot does not exist. */
|
||||||
const std::vector<aiVector3D>& GetTextureCoords(unsigned int index) const {
|
const std::vector<aiVector2D>& GetTextureCoords(unsigned int index) const {
|
||||||
static const std::vector<aiVector3D> empty;
|
static const std::vector<aiVector2D> empty;
|
||||||
return index >= AI_MAX_NUMBER_OF_TEXTURECOORDS ? empty : uvs[index];
|
return index >= AI_MAX_NUMBER_OF_TEXTURECOORDS ? empty : uvs[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -166,6 +166,12 @@ public:
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
void ReadLayer(const Scope& layer);
|
||||||
|
void ReadLayerElement(const Scope& layerElement);
|
||||||
|
void ReadVertexData(const std::string& type, int index, const Scope& source);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
// cached data arrays
|
// cached data arrays
|
||||||
|
@ -174,7 +180,7 @@ private:
|
||||||
std::vector<unsigned int> faces;
|
std::vector<unsigned int> faces;
|
||||||
std::vector<aiVector3D> tangents;
|
std::vector<aiVector3D> tangents;
|
||||||
std::vector<aiVector3D> normals;
|
std::vector<aiVector3D> normals;
|
||||||
std::vector<aiVector3D> uvs[AI_MAX_NUMBER_OF_TEXTURECOORDS];
|
std::vector<aiVector2D> uvs[AI_MAX_NUMBER_OF_TEXTURECOORDS];
|
||||||
std::vector<aiColor4D> colors[AI_MAX_NUMBER_OF_COLOR_SETS];
|
std::vector<aiColor4D> colors[AI_MAX_NUMBER_OF_COLOR_SETS];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue