- 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)
|
void MeshGeometry::ReadLayer(const Scope& layer)
|
||||||
{
|
{
|
||||||
|
@ -434,6 +442,7 @@ void MeshGeometry::ReadLayer(const Scope& layer)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
void MeshGeometry::ReadLayerElement(const Scope& layerElement)
|
void MeshGeometry::ReadLayerElement(const Scope& layerElement)
|
||||||
{
|
{
|
||||||
|
@ -458,6 +467,7 @@ void MeshGeometry::ReadLayerElement(const Scope& layerElement)
|
||||||
<< type << ", index: " << typedIndex);
|
<< type << ", index: " << typedIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
void MeshGeometry::ReadVertexData(const std::string& type, int index, const Scope& source)
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<aiVector2D>& uv_out = uvs[index];
|
ReadVertexDataUV(uvs[index],source,MappingInformationType,ReferenceInformationType);
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if (type == "LayerElementMaterial") {
|
else if (type == "LayerElementMaterial") {
|
||||||
|
|
||||||
|
@ -562,46 +506,121 @@ void MeshGeometry::ReadVertexData(const std::string& type, int index, const Scop
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (type == "LayerElementNormal") {
|
else if (type == "LayerElementNormal") {
|
||||||
|
ReadVertexDataNormals(normals,source,MappingInformationType,ReferenceInformationType);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
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)
|
Document::Document(const Parser& parser)
|
||||||
|
|
|
@ -172,6 +172,14 @@ private:
|
||||||
void ReadLayerElement(const Scope& layerElement);
|
void ReadLayerElement(const Scope& layerElement);
|
||||||
void ReadVertexData(const std::string& type, int index, const Scope& source);
|
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:
|
private:
|
||||||
|
|
||||||
// cached data arrays
|
// cached data arrays
|
||||||
|
|
Loading…
Reference in New Issue