- fbx: refactor code to handle FBX vertex data access. Support the same access & indexing types for UVs and normals.
parent
026cec7d7b
commit
ffe0ed7926
|
@ -423,6 +423,14 @@ MeshGeometry::MeshGeometry(const Element& element, const std::string& name)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
MeshGeometry::~MeshGeometry()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void MeshGeometry::ReadLayer(const Scope& layer)
|
||||
{
|
||||
|
@ -434,6 +442,7 @@ void MeshGeometry::ReadLayer(const Scope& layer)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void MeshGeometry::ReadLayerElement(const Scope& layerElement)
|
||||
{
|
||||
|
@ -458,6 +467,7 @@ void MeshGeometry::ReadLayerElement(const Scope& layerElement)
|
|||
<< type << ", index: " << typedIndex);
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void MeshGeometry::ReadVertexData(const std::string& type, int index, const Scope& source)
|
||||
{
|
||||
|
@ -477,73 +487,7 @@ void MeshGeometry::ReadVertexData(const std::string& type, int index, const Scop
|
|||
return;
|
||||
}
|
||||
|
||||
std::vector<aiVector2D>& uv_out = uvs[index];
|
||||
|
||||
std::vector<aiVector2D> tempUV;
|
||||
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") {
|
||||
uv_out.resize(vertices.size());
|
||||
for (size_t i = 0, e = tempUV.size(); i < e; ++i) {
|
||||
|
||||
const unsigned int istart = mapping_offsets[i], iend = istart + mapping_counts[i];
|
||||
for (unsigned int j = istart; j < iend; ++j) {
|
||||
uv_out[mappings[j]] = tempUV[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (MappingInformationType == "ByVertice" && ReferenceInformationType == "IndexToDirect") {
|
||||
uv_out.resize(vertices.size());
|
||||
|
||||
std::vector<int> uvIndices;
|
||||
ReadIntDataArray(uvIndices,GetRequiredElement(source,"UVIndex"));
|
||||
|
||||
for (size_t i = 0, e = uvIndices.size(); i < e; ++i) {
|
||||
|
||||
const unsigned int istart = mapping_offsets[i], iend = istart + mapping_counts[i];
|
||||
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]];
|
||||
}
|
||||
}
|
||||
}
|
||||
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 {
|
||||
FBXImporter::LogError(Formatter::format("ignoring normals, unrecognized access type: ")
|
||||
<< MappingInformationType << "," << ReferenceInformationType);
|
||||
}
|
||||
ReadVertexDataUV(uvs[index],source,MappingInformationType,ReferenceInformationType);
|
||||
}
|
||||
else if (type == "LayerElementMaterial") {
|
||||
|
||||
|
@ -562,47 +506,122 @@ void MeshGeometry::ReadVertexData(const std::string& type, int index, const Scop
|
|||
}
|
||||
}
|
||||
else if (type == "LayerElementNormal") {
|
||||
|
||||
std::vector<aiVector3D> tempNormals;
|
||||
ReadVectorDataArray(normals,GetRequiredElement(source,"Normals"));
|
||||
|
||||
normals.resize(vertices.size());
|
||||
|
||||
if (MappingInformationType == "ByVertice" && ReferenceInformationType == "Direct") {
|
||||
|
||||
for (size_t i = 0, e = tempNormals.size(); i < e; ++i) {
|
||||
|
||||
const unsigned int istart = mapping_offsets[i], iend = istart + mapping_counts[i];
|
||||
for (unsigned int j = istart; j < iend; ++j) {
|
||||
normals[mappings[j]] = tempNormals[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (MappingInformationType == "ByVertice" && ReferenceInformationType == "IndexToDirect") {
|
||||
|
||||
std::vector<int> normalIndices;
|
||||
ReadIntDataArray(normalIndices,GetRequiredElement(source,"NormalsIndex"));
|
||||
for (size_t i = 0, e = normalIndices.size(); i < e; ++i) {
|
||||
|
||||
const unsigned int istart = mapping_offsets[i], iend = istart + mapping_counts[i];
|
||||
for (unsigned int j = istart; j < iend; ++j) {
|
||||
normals[mappings[j]] = tempNormals[normalIndices[i]];
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
FBXImporter::LogError(Formatter::format("ignoring normals, unrecognized access type: ")
|
||||
<< MappingInformationType << "," << ReferenceInformationType);
|
||||
}
|
||||
ReadVertexDataNormals(normals,source,MappingInformationType,ReferenceInformationType);
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
MeshGeometry::~MeshGeometry()
|
||||
// Lengthy utility function to read and resolve a FBX vertex data array - that is, the
|
||||
// output is in polygon vertex order. This logic is used for reading normals, UVs, colors,
|
||||
// tangents ..
|
||||
template <typename T>
|
||||
void ResolveVertexDataArray(std::vector<T>& data_out, const Scope& source,
|
||||
const std::string& MappingInformationType,
|
||||
const std::string& ReferenceInformationType,
|
||||
const char* dataElementName,
|
||||
const char* indexDataElementName,
|
||||
size_t vertex_count,
|
||||
const std::vector<unsigned int>& mapping_counts,
|
||||
const std::vector<unsigned int>& mapping_offsets,
|
||||
const std::vector<unsigned int>& mappings)
|
||||
{
|
||||
std::vector<T> tempUV;
|
||||
ReadVectorDataArray(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
|
||||
// now it seems unavoidable.
|
||||
if (MappingInformationType == "ByVertice" && ReferenceInformationType == "Direct") {
|
||||
data_out.resize(vertex_count);
|
||||
for (size_t i = 0, e = tempUV.size(); i < e; ++i) {
|
||||
|
||||
const unsigned int istart = mapping_offsets[i], iend = istart + mapping_counts[i];
|
||||
for (unsigned int j = istart; j < iend; ++j) {
|
||||
data_out[mappings[j]] = tempUV[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (MappingInformationType == "ByVertice" && ReferenceInformationType == "IndexToDirect") {
|
||||
data_out.resize(vertex_count);
|
||||
|
||||
std::vector<int> uvIndices;
|
||||
ReadIntDataArray(uvIndices,GetRequiredElement(source,indexDataElementName));
|
||||
|
||||
for (size_t i = 0, e = uvIndices.size(); i < e; ++i) {
|
||||
|
||||
const unsigned int istart = mapping_offsets[i], iend = istart + mapping_counts[i];
|
||||
for (unsigned int j = istart; j < iend; ++j) {
|
||||
if(static_cast<size_t>(uvIndices[i]) >= tempUV.size()) {
|
||||
DOMError("index out of range",&GetRequiredElement(source,indexDataElementName));
|
||||
}
|
||||
data_out[mappings[j]] = tempUV[uvIndices[i]];
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (MappingInformationType == "ByPolygonVertex" && ReferenceInformationType == "Direct") {
|
||||
if (tempUV.size() != vertex_count) {
|
||||
FBXImporter::LogError("length of input data unexpected for ByPolygonVertex mapping");
|
||||
return;
|
||||
}
|
||||
|
||||
data_out.swap(tempUV);
|
||||
}
|
||||
else if (MappingInformationType == "ByPolygonVertex" && ReferenceInformationType == "IndexToDirect") {
|
||||
data_out.resize(vertex_count);
|
||||
|
||||
std::vector<int> uvIndices;
|
||||
ReadIntDataArray(uvIndices,GetRequiredElement(source,indexDataElementName));
|
||||
|
||||
if (uvIndices.size() != vertex_count) {
|
||||
FBXImporter::LogError("length of input data unexpected for ByPolygonVertex mapping");
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned int next = 0;
|
||||
BOOST_FOREACH(int i, uvIndices) {
|
||||
if(static_cast<size_t>(i) >= tempUV.size()) {
|
||||
DOMError("index out of range",&GetRequiredElement(source,indexDataElementName));
|
||||
}
|
||||
|
||||
data_out[next++] = tempUV[i];
|
||||
}
|
||||
}
|
||||
else {
|
||||
FBXImporter::LogError(Formatter::format("ignoring vertex data channel, unrecognized access type: ")
|
||||
<< MappingInformationType << "," << ReferenceInformationType);
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void MeshGeometry::ReadVertexDataNormals(std::vector<aiVector3D>& normals_out, const Scope& source,
|
||||
const std::string& MappingInformationType,
|
||||
const std::string& ReferenceInformationType)
|
||||
{
|
||||
ResolveVertexDataArray(normals_out,source,MappingInformationType,ReferenceInformationType,
|
||||
"Normals",
|
||||
"NormalsIndex",
|
||||
vertices.size(),
|
||||
mapping_counts,
|
||||
mapping_offsets,
|
||||
mappings);
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void MeshGeometry::ReadVertexDataUV(std::vector<aiVector2D>& uv_out, const Scope& source,
|
||||
const std::string& MappingInformationType,
|
||||
const std::string& ReferenceInformationType)
|
||||
{
|
||||
ResolveVertexDataArray(uv_out,source,MappingInformationType,ReferenceInformationType,
|
||||
"UV",
|
||||
"UVIndex",
|
||||
vertices.size(),
|
||||
mapping_counts,
|
||||
mapping_offsets,
|
||||
mappings);
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
Document::Document(const Parser& parser)
|
||||
: parser(parser)
|
||||
|
|
|
@ -172,6 +172,14 @@ private:
|
|||
void ReadLayerElement(const Scope& layerElement);
|
||||
void ReadVertexData(const std::string& type, int index, const Scope& source);
|
||||
|
||||
void ReadVertexDataUV(std::vector<aiVector2D>& uv_out, const Scope& source,
|
||||
const std::string& MappingInformationType,
|
||||
const std::string& ReferenceInformationType);
|
||||
|
||||
void ReadVertexDataNormals(std::vector<aiVector3D>& normals_out, const Scope& source,
|
||||
const std::string& MappingInformationType,
|
||||
const std::string& ReferenceInformationType);
|
||||
|
||||
private:
|
||||
|
||||
// cached data arrays
|
||||
|
|
Loading…
Reference in New Issue