Merge pull request #9371 from jherico/fbx_parse_optimizations

Improve FBX parsing performance
This commit is contained in:
samcake 2017-01-13 13:44:54 -08:00 committed by GitHub
commit 584feef56d
3 changed files with 169 additions and 86 deletions

View file

@ -555,8 +555,9 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QS
} }
} else if (subobject.name == "Properties70") { } else if (subobject.name == "Properties70") {
foreach (const FBXNode& subsubobject, subobject.children) { foreach (const FBXNode& subsubobject, subobject.children) {
static const QVariant APPLICATION_NAME = QVariant(QByteArray("Original|ApplicationName"));
if (subsubobject.name == "P" && subsubobject.properties.size() >= 5 && if (subsubobject.name == "P" && subsubobject.properties.size() >= 5 &&
subsubobject.properties.at(0) == "Original|ApplicationName") { subsubobject.properties.at(0) == APPLICATION_NAME) {
geometry.applicationName = subsubobject.properties.at(4).toString(); geometry.applicationName = subsubobject.properties.at(4).toString();
} }
} }
@ -571,10 +572,12 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QS
int index = 4; int index = 4;
foreach (const FBXNode& subobject, object.children) { foreach (const FBXNode& subobject, object.children) {
if (subobject.name == propertyName) { if (subobject.name == propertyName) {
QString subpropName = subobject.properties.at(0).toString(); static const QVariant UNIT_SCALE_FACTOR = QByteArray("UnitScaleFactor");
if (subpropName == "UnitScaleFactor") { static const QVariant AMBIENT_COLOR = QByteArray("AmbientColor");
const auto& subpropName = subobject.properties.at(0);
if (subpropName == UNIT_SCALE_FACTOR) {
unitScaleFactor = subobject.properties.at(index).toFloat(); unitScaleFactor = subobject.properties.at(index).toFloat();
} else if (subpropName == "AmbientColor") { } else if (subpropName == AMBIENT_COLOR) {
ambientColor = getVec3(subobject.properties, index); ambientColor = getVec3(subobject.properties, index);
} }
} }
@ -672,66 +675,87 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QS
index = 4; index = 4;
} }
if (properties) { if (properties) {
foreach (const FBXNode& property, subobject.children) { static const QVariant GEOMETRIC_TRANSLATION = QByteArray("GeometricTranslation");
static const QVariant GEOMETRIC_ROTATION = QByteArray("GeometricRotation");
static const QVariant GEOMETRIC_SCALING = QByteArray("GeometricScaling");
static const QVariant LCL_TRANSLATION = QByteArray("Lcl Translation");
static const QVariant LCL_ROTATION = QByteArray("Lcl Rotation");
static const QVariant LCL_SCALING = QByteArray("Lcl Scaling");
static const QVariant ROTATION_MAX = QByteArray("RotationMax");
static const QVariant ROTATION_MAX_X = QByteArray("RotationMaxX");
static const QVariant ROTATION_MAX_Y = QByteArray("RotationMaxY");
static const QVariant ROTATION_MAX_Z = QByteArray("RotationMaxZ");
static const QVariant ROTATION_MIN = QByteArray("RotationMin");
static const QVariant ROTATION_MIN_X = QByteArray("RotationMinX");
static const QVariant ROTATION_MIN_Y = QByteArray("RotationMinY");
static const QVariant ROTATION_MIN_Z = QByteArray("RotationMinZ");
static const QVariant ROTATION_OFFSET = QByteArray("RotationOffset");
static const QVariant ROTATION_PIVOT = QByteArray("RotationPivot");
static const QVariant SCALING_OFFSET = QByteArray("ScalingOffset");
static const QVariant SCALING_PIVOT = QByteArray("ScalingPivot");
static const QVariant PRE_ROTATION = QByteArray("PreRotation");
static const QVariant POST_ROTATION = QByteArray("PostRotation");
foreach(const FBXNode& property, subobject.children) {
const auto& childProperty = property.properties.at(0);
if (property.name == propertyName) { if (property.name == propertyName) {
if (property.properties.at(0) == "Lcl Translation") { if (childProperty == LCL_TRANSLATION) {
translation = getVec3(property.properties, index); translation = getVec3(property.properties, index);
} else if (property.properties.at(0) == "RotationOffset") { } else if (childProperty == ROTATION_OFFSET) {
rotationOffset = getVec3(property.properties, index); rotationOffset = getVec3(property.properties, index);
} else if (property.properties.at(0) == "RotationPivot") { } else if (childProperty == ROTATION_PIVOT) {
rotationPivot = getVec3(property.properties, index); rotationPivot = getVec3(property.properties, index);
} else if (property.properties.at(0) == "PreRotation") { } else if (childProperty == PRE_ROTATION) {
preRotation = getVec3(property.properties, index); preRotation = getVec3(property.properties, index);
} else if (property.properties.at(0) == "Lcl Rotation") { } else if (childProperty == LCL_ROTATION) {
rotation = getVec3(property.properties, index); rotation = getVec3(property.properties, index);
} else if (property.properties.at(0) == "PostRotation") { } else if (childProperty == POST_ROTATION) {
postRotation = getVec3(property.properties, index); postRotation = getVec3(property.properties, index);
} else if (property.properties.at(0) == "ScalingPivot") { } else if (childProperty == SCALING_PIVOT) {
scalePivot = getVec3(property.properties, index); scalePivot = getVec3(property.properties, index);
} else if (property.properties.at(0) == "Lcl Scaling") { } else if (childProperty == LCL_SCALING) {
scale = getVec3(property.properties, index); scale = getVec3(property.properties, index);
} else if (property.properties.at(0) == "ScalingOffset") { } else if (childProperty == SCALING_OFFSET) {
scaleOffset = getVec3(property.properties, index); scaleOffset = getVec3(property.properties, index);
// NOTE: these rotation limits are stored in degrees (NOT radians) // NOTE: these rotation limits are stored in degrees (NOT radians)
} else if (property.properties.at(0) == "RotationMin") { } else if (childProperty == ROTATION_MIN) {
rotationMin = getVec3(property.properties, index); rotationMin = getVec3(property.properties, index);
} else if (property.properties.at(0) == "RotationMax") { } else if (childProperty == ROTATION_MAX) {
rotationMax = getVec3(property.properties, index); rotationMax = getVec3(property.properties, index);
} else if (property.properties.at(0) == "RotationMinX") { } else if (childProperty == ROTATION_MIN_X) {
rotationMinX = property.properties.at(index).toBool(); rotationMinX = property.properties.at(index).toBool();
} else if (property.properties.at(0) == "RotationMinY") { } else if (childProperty == ROTATION_MIN_Y) {
rotationMinY = property.properties.at(index).toBool(); rotationMinY = property.properties.at(index).toBool();
} else if (property.properties.at(0) == "RotationMinZ") { } else if (childProperty == ROTATION_MIN_Z) {
rotationMinZ = property.properties.at(index).toBool(); rotationMinZ = property.properties.at(index).toBool();
} else if (property.properties.at(0) == "RotationMaxX") { } else if (childProperty == ROTATION_MAX_X) {
rotationMaxX = property.properties.at(index).toBool(); rotationMaxX = property.properties.at(index).toBool();
} else if (property.properties.at(0) == "RotationMaxY") { } else if (childProperty == ROTATION_MAX_Y) {
rotationMaxY = property.properties.at(index).toBool(); rotationMaxY = property.properties.at(index).toBool();
} else if (property.properties.at(0) == "RotationMaxZ") { } else if (childProperty == ROTATION_MAX_Z) {
rotationMaxZ = property.properties.at(index).toBool(); rotationMaxZ = property.properties.at(index).toBool();
} else if (property.properties.at(0) == "GeometricTranslation") { } else if (childProperty == GEOMETRIC_TRANSLATION) {
geometricTranslation = getVec3(property.properties, index); geometricTranslation = getVec3(property.properties, index);
hasGeometricOffset = true; hasGeometricOffset = true;
} else if (property.properties.at(0) == "GeometricRotation") { } else if (childProperty == GEOMETRIC_ROTATION) {
geometricRotation = getVec3(property.properties, index); geometricRotation = getVec3(property.properties, index);
hasGeometricOffset = true; hasGeometricOffset = true;
} else if (property.properties.at(0) == "GeometricScaling") { } else if (childProperty == GEOMETRIC_SCALING) {
geometricScaling = getVec3(property.properties, index); geometricScaling = getVec3(property.properties, index);
hasGeometricOffset = true; hasGeometricOffset = true;
} }
@ -842,20 +866,26 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QS
propertyName = "P"; propertyName = "P";
index = 4; index = 4;
foreach (const FBXNode& property, subobject.children) { foreach (const FBXNode& property, subobject.children) {
static const QVariant UV_SET = QByteArray("UVSet");
static const QVariant CURRENT_TEXTURE_BLEND_MODE = QByteArray("CurrentTextureBlendMode");
static const QVariant USE_MATERIAL = QByteArray("UseMaterial");
static const QVariant TRANSLATION = QByteArray("Translation");
static const QVariant ROTATION = QByteArray("Rotation");
static const QVariant SCALING = QByteArray("Scaling");
if (property.name == propertyName) { if (property.name == propertyName) {
QString v = property.properties.at(0).toString(); QString v = property.properties.at(0).toString();
if (property.properties.at(0) == "UVSet") { if (property.properties.at(0) == UV_SET) {
std::string uvName = property.properties.at(index).toString().toStdString(); std::string uvName = property.properties.at(index).toString().toStdString();
tex.assign(tex.UVSet, property.properties.at(index).toString()); tex.assign(tex.UVSet, property.properties.at(index).toString());
} else if (property.properties.at(0) == "CurrentTextureBlendMode") { } else if (property.properties.at(0) == CURRENT_TEXTURE_BLEND_MODE) {
tex.assign<uint8_t>(tex.currentTextureBlendMode, property.properties.at(index).value<int>()); tex.assign<uint8_t>(tex.currentTextureBlendMode, property.properties.at(index).value<int>());
} else if (property.properties.at(0) == "UseMaterial") { } else if (property.properties.at(0) == USE_MATERIAL) {
tex.assign<bool>(tex.useMaterial, property.properties.at(index).value<int>()); tex.assign<bool>(tex.useMaterial, property.properties.at(index).value<int>());
} else if (property.properties.at(0) == "Translation") { } else if (property.properties.at(0) == TRANSLATION) {
tex.assign(tex.translation, getVec3(property.properties, index)); tex.assign(tex.translation, getVec3(property.properties, index));
} else if (property.properties.at(0) == "Rotation") { } else if (property.properties.at(0) == ROTATION) {
tex.assign(tex.rotation, getVec3(property.properties, index)); tex.assign(tex.rotation, getVec3(property.properties, index));
} else if (property.properties.at(0) == "Scaling") { } else if (property.properties.at(0) == SCALING) {
tex.assign(tex.scaling, getVec3(property.properties, index)); tex.assign(tex.scaling, getVec3(property.properties, index));
if (tex.scaling.x == 0.0f) { if (tex.scaling.x == 0.0f) {
tex.scaling.x = 1.0f; tex.scaling.x = 1.0f;
@ -931,87 +961,114 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QS
if (properties) { if (properties) {
std::vector<std::string> unknowns; std::vector<std::string> unknowns;
static const QVariant DIFFUSE_COLOR = QByteArray("DiffuseColor");
static const QVariant DIFFUSE_FACTOR = QByteArray("DiffuseFactor");
static const QVariant DIFFUSE = QByteArray("Diffuse");
static const QVariant SPECULAR_COLOR = QByteArray("SpecularColor");
static const QVariant SPECULAR_FACTOR = QByteArray("SpecularFactor");
static const QVariant SPECULAR = QByteArray("Specular");
static const QVariant EMISSIVE_COLOR = QByteArray("EmissiveColor");
static const QVariant EMISSIVE_FACTOR = QByteArray("EmissiveFactor");
static const QVariant EMISSIVE = QByteArray("Emissive");
static const QVariant AMBIENT_FACTOR = QByteArray("AmbientFactor");
static const QVariant SHININESS = QByteArray("Shininess");
static const QVariant OPACITY = QByteArray("Shininess");
static const QVariant MAYA_USE_NORMAL_MAP = QByteArray("Maya|use_normal_map");
static const QVariant MAYA_BASE_COLOR = QByteArray("Maya|base_color");
static const QVariant MAYA_USE_COLOR_MAP = QByteArray("Maya|use_color_map");
static const QVariant MAYA_ROUGHNESS = QByteArray("Maya|roughness");
static const QVariant MAYA_USE_ROUGHNESS_MAP = QByteArray("Maya|use_roughness_map");
static const QVariant MAYA_METALLIC = QByteArray("Maya|metallic");
static const QVariant MAYA_USE_METALLIC_MAP = QByteArray("Maya|use_metallic_map");
static const QVariant MAYA_EMISSIVE = QByteArray("Maya|emissive");
static const QVariant MAYA_EMISSIVE_INTENSITY = QByteArray("Maya|emissive_intensity");
static const QVariant MAYA_USE_EMISSIVE_MAP = QByteArray("Maya|use_emissive_map");
static const QVariant MAYA_USE_AO_MAP = QByteArray("Maya|use_ao_map");
foreach(const FBXNode& property, subobject.children) { foreach(const FBXNode& property, subobject.children) {
if (property.name == propertyName) { if (property.name == propertyName) {
if (property.properties.at(0) == "DiffuseColor") { if (property.properties.at(0) == DIFFUSE_COLOR) {
material.diffuseColor = getVec3(property.properties, index); material.diffuseColor = getVec3(property.properties, index);
} else if (property.properties.at(0) == "DiffuseFactor") { } else if (property.properties.at(0) == DIFFUSE_FACTOR) {
material.diffuseFactor = property.properties.at(index).value<double>(); material.diffuseFactor = property.properties.at(index).value<double>();
} else if (property.properties.at(0) == "Diffuse") { } else if (property.properties.at(0) == DIFFUSE) {
// NOTE: this is uneeded but keep it for now for debug // NOTE: this is uneeded but keep it for now for debug
// material.diffuseColor = getVec3(property.properties, index); // material.diffuseColor = getVec3(property.properties, index);
// material.diffuseFactor = 1.0; // material.diffuseFactor = 1.0;
} else if (property.properties.at(0) == "SpecularColor") { } else if (property.properties.at(0) == SPECULAR_COLOR) {
material.specularColor = getVec3(property.properties, index); material.specularColor = getVec3(property.properties, index);
} else if (property.properties.at(0) == "SpecularFactor") { } else if (property.properties.at(0) == SPECULAR_FACTOR) {
material.specularFactor = property.properties.at(index).value<double>(); material.specularFactor = property.properties.at(index).value<double>();
} else if (property.properties.at(0) == "Specular") { } else if (property.properties.at(0) == SPECULAR) {
// NOTE: this is uneeded but keep it for now for debug // NOTE: this is uneeded but keep it for now for debug
// material.specularColor = getVec3(property.properties, index); // material.specularColor = getVec3(property.properties, index);
// material.specularFactor = 1.0; // material.specularFactor = 1.0;
} else if (property.properties.at(0) == "EmissiveColor") { } else if (property.properties.at(0) == EMISSIVE_COLOR) {
material.emissiveColor = getVec3(property.properties, index); material.emissiveColor = getVec3(property.properties, index);
} else if (property.properties.at(0) == "EmissiveFactor") { } else if (property.properties.at(0) == EMISSIVE_FACTOR) {
material.emissiveFactor = property.properties.at(index).value<double>(); material.emissiveFactor = property.properties.at(index).value<double>();
} else if (property.properties.at(0) == "Emissive") { } else if (property.properties.at(0) == EMISSIVE) {
// NOTE: this is uneeded but keep it for now for debug // NOTE: this is uneeded but keep it for now for debug
// material.emissiveColor = getVec3(property.properties, index); // material.emissiveColor = getVec3(property.properties, index);
// material.emissiveFactor = 1.0; // material.emissiveFactor = 1.0;
} else if (property.properties.at(0) == "AmbientFactor") { } else if (property.properties.at(0) == AMBIENT_FACTOR) {
material.ambientFactor = property.properties.at(index).value<double>(); material.ambientFactor = property.properties.at(index).value<double>();
// Detected just for BLender AO vs lightmap // Detected just for BLender AO vs lightmap
} else if (property.properties.at(0) == "Shininess") { } else if (property.properties.at(0) == SHININESS) {
material.shininess = property.properties.at(index).value<double>(); material.shininess = property.properties.at(index).value<double>();
} else if (property.properties.at(0) == "Opacity") { } else if (property.properties.at(0) == OPACITY) {
material.opacity = property.properties.at(index).value<double>(); material.opacity = property.properties.at(index).value<double>();
} }
// Sting Ray Material Properties!!!! // Sting Ray Material Properties!!!!
else if (property.properties.at(0) == "Maya|use_normal_map") { else if (property.properties.at(0) == MAYA_USE_NORMAL_MAP) {
material.isPBSMaterial = true; material.isPBSMaterial = true;
material.useNormalMap = (bool)property.properties.at(index).value<double>(); material.useNormalMap = (bool)property.properties.at(index).value<double>();
} else if (property.properties.at(0) == "Maya|base_color") { } else if (property.properties.at(0) == MAYA_BASE_COLOR) {
material.isPBSMaterial = true; material.isPBSMaterial = true;
material.diffuseColor = getVec3(property.properties, index); material.diffuseColor = getVec3(property.properties, index);
} else if (property.properties.at(0) == "Maya|use_color_map") { } else if (property.properties.at(0) == MAYA_USE_COLOR_MAP) {
material.isPBSMaterial = true; material.isPBSMaterial = true;
material.useAlbedoMap = (bool) property.properties.at(index).value<double>(); material.useAlbedoMap = (bool) property.properties.at(index).value<double>();
} else if (property.properties.at(0) == "Maya|roughness") { } else if (property.properties.at(0) == MAYA_ROUGHNESS) {
material.isPBSMaterial = true; material.isPBSMaterial = true;
material.roughness = property.properties.at(index).value<double>(); material.roughness = property.properties.at(index).value<double>();
} else if (property.properties.at(0) == "Maya|use_roughness_map") { } else if (property.properties.at(0) == MAYA_USE_ROUGHNESS_MAP) {
material.isPBSMaterial = true; material.isPBSMaterial = true;
material.useRoughnessMap = (bool)property.properties.at(index).value<double>(); material.useRoughnessMap = (bool)property.properties.at(index).value<double>();
} else if (property.properties.at(0) == "Maya|metallic") { } else if (property.properties.at(0) == MAYA_METALLIC) {
material.isPBSMaterial = true; material.isPBSMaterial = true;
material.metallic = property.properties.at(index).value<double>(); material.metallic = property.properties.at(index).value<double>();
} else if (property.properties.at(0) == "Maya|use_metallic_map") { } else if (property.properties.at(0) == MAYA_USE_METALLIC_MAP) {
material.isPBSMaterial = true; material.isPBSMaterial = true;
material.useMetallicMap = (bool)property.properties.at(index).value<double>(); material.useMetallicMap = (bool)property.properties.at(index).value<double>();
} else if (property.properties.at(0) == "Maya|emissive") { } else if (property.properties.at(0) == MAYA_EMISSIVE) {
material.isPBSMaterial = true; material.isPBSMaterial = true;
material.emissiveColor = getVec3(property.properties, index); material.emissiveColor = getVec3(property.properties, index);
} else if (property.properties.at(0) == "Maya|emissive_intensity") { } else if (property.properties.at(0) == MAYA_EMISSIVE_INTENSITY) {
material.isPBSMaterial = true; material.isPBSMaterial = true;
material.emissiveIntensity = property.properties.at(index).value<double>(); material.emissiveIntensity = property.properties.at(index).value<double>();
} else if (property.properties.at(0) == "Maya|use_emissive_map") { } else if (property.properties.at(0) == MAYA_USE_EMISSIVE_MAP) {
material.isPBSMaterial = true; material.isPBSMaterial = true;
material.useEmissiveMap = (bool)property.properties.at(index).value<double>(); material.useEmissiveMap = (bool)property.properties.at(index).value<double>();
} else if (property.properties.at(0) == "Maya|use_ao_map") { } else if (property.properties.at(0) == MAYA_USE_AO_MAP) {
material.isPBSMaterial = true; material.isPBSMaterial = true;
material.useOcclusionMap = (bool)property.properties.at(index).value<double>(); material.useOcclusionMap = (bool)property.properties.at(index).value<double>();
@ -1116,9 +1173,11 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QS
#endif #endif
} }
} else if (child.name == "Connections") { } else if (child.name == "Connections") {
static const QVariant OO = QByteArray("OO");
static const QVariant OP = QByteArray("OP");
foreach (const FBXNode& connection, child.children) { foreach (const FBXNode& connection, child.children) {
if (connection.name == "C" || connection.name == "Connect") { if (connection.name == "C" || connection.name == "Connect") {
if (connection.properties.at(0) == "OO") { if (connection.properties.at(0) == OO) {
QString childID = getID(connection.properties, 1); QString childID = getID(connection.properties, 1);
QString parentID = getID(connection.properties, 2); QString parentID = getID(connection.properties, 2);
ooChildToParent.insert(childID, parentID); ooChildToParent.insert(childID, parentID);
@ -1132,8 +1191,7 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QS
_lightmapOffset = glm::clamp((*lightIt).second.color.x, 0.f, 1.f); _lightmapOffset = glm::clamp((*lightIt).second.color.x, 0.f, 1.f);
} }
} }
} } else if (connection.properties.at(0) == OP) {
if (connection.properties.at(0) == "OP") {
int counter = 0; int counter = 0;
QByteArray type = connection.properties.at(3).toByteArray().toLower(); QByteArray type = connection.properties.at(3).toByteArray().toLower();
if (type.contains("DiffuseFactor")) { if (type.contains("DiffuseFactor")) {

View file

@ -171,7 +171,8 @@ ExtractedMesh FBXReader::extractMesh(const FBXNode& object, unsigned int& meshIn
QVector<int> materials; QVector<int> materials;
QVector<int> textures; QVector<int> textures;
bool isMaterialPerPolygon = false; bool isMaterialPerPolygon = false;
static const QVariant BY_VERTICE = QByteArray("ByVertice");
static const QVariant INDEX_TO_DIRECT = QByteArray("IndexToDirect");
foreach (const FBXNode& child, object.children) { foreach (const FBXNode& child, object.children) {
if (child.name == "Vertices") { if (child.name == "Vertices") {
data.vertices = createVec3Vector(getDoubleVector(child)); data.vertices = createVec3Vector(getDoubleVector(child));
@ -189,10 +190,10 @@ ExtractedMesh FBXReader::extractMesh(const FBXNode& object, unsigned int& meshIn
} else if (subdata.name == "NormalsIndex") { } else if (subdata.name == "NormalsIndex") {
data.normalIndices = getIntVector(subdata); data.normalIndices = getIntVector(subdata);
} else if (subdata.name == "MappingInformationType" && subdata.properties.at(0) == "ByVertice") { } else if (subdata.name == "MappingInformationType" && subdata.properties.at(0) == BY_VERTICE) {
data.normalsByVertex = true; data.normalsByVertex = true;
} else if (subdata.name == "ReferenceInformationType" && subdata.properties.at(0) == "IndexToDirect") { } else if (subdata.name == "ReferenceInformationType" && subdata.properties.at(0) == INDEX_TO_DIRECT) {
indexToDirect = true; indexToDirect = true;
} }
} }
@ -209,10 +210,10 @@ ExtractedMesh FBXReader::extractMesh(const FBXNode& object, unsigned int& meshIn
} else if (subdata.name == "ColorsIndex") { } else if (subdata.name == "ColorsIndex") {
data.colorIndices = getIntVector(subdata); data.colorIndices = getIntVector(subdata);
} else if (subdata.name == "MappingInformationType" && subdata.properties.at(0) == "ByVertice") { } else if (subdata.name == "MappingInformationType" && subdata.properties.at(0) == BY_VERTICE) {
data.colorsByVertex = true; data.colorsByVertex = true;
} else if (subdata.name == "ReferenceInformationType" && subdata.properties.at(0) == "IndexToDirect") { } else if (subdata.name == "ReferenceInformationType" && subdata.properties.at(0) == INDEX_TO_DIRECT) {
indexToDirect = true; indexToDirect = true;
} }
} }
@ -298,11 +299,12 @@ ExtractedMesh FBXReader::extractMesh(const FBXNode& object, unsigned int& meshIn
} }
} }
} else if (child.name == "LayerElementMaterial") { } else if (child.name == "LayerElementMaterial") {
static const QVariant BY_POLYGON = QByteArray("ByPolygon");
foreach (const FBXNode& subdata, child.children) { foreach (const FBXNode& subdata, child.children) {
if (subdata.name == "Materials") { if (subdata.name == "Materials") {
materials = getIntVector(subdata); materials = getIntVector(subdata);
} else if (subdata.name == "MappingInformationType") { } else if (subdata.name == "MappingInformationType") {
if (subdata.properties.at(0) == "ByPolygon") if (subdata.properties.at(0) == BY_POLYGON)
isMaterialPerPolygon = true; isMaterialPerPolygon = true;
} else { } else {
isMaterialPerPolygon = false; isMaterialPerPolygon = false;

View file

@ -43,31 +43,54 @@ template<class T> QVariant readBinaryArray(QDataStream& in, int& position) {
position += sizeof(quint32) * 3; position += sizeof(quint32) * 3;
QVector<T> values; QVector<T> values;
const unsigned int DEFLATE_ENCODING = 1; if ((int)QSysInfo::ByteOrder == (int)in.byteOrder()) {
if (encoding == DEFLATE_ENCODING) { values.resize(arrayLength);
// preface encoded data with uncompressed length const unsigned int DEFLATE_ENCODING = 1;
QByteArray compressed(sizeof(quint32) + compressedLength, 0); QByteArray arrayData;
*((quint32*)compressed.data()) = qToBigEndian<quint32>(arrayLength * sizeof(T)); if (encoding == DEFLATE_ENCODING) {
in.readRawData(compressed.data() + sizeof(quint32), compressedLength); // preface encoded data with uncompressed length
position += compressedLength; QByteArray compressed(sizeof(quint32) + compressedLength, 0);
QByteArray uncompressed = qUncompress(compressed); *((quint32*)compressed.data()) = qToBigEndian<quint32>(arrayLength * sizeof(T));
if (uncompressed.isEmpty()) { // answers empty byte array if corrupt in.readRawData(compressed.data() + sizeof(quint32), compressedLength);
throw QString("corrupt fbx file"); position += compressedLength;
} arrayData = qUncompress(compressed);
QDataStream uncompressedIn(uncompressed); if (arrayData.isEmpty() || arrayData.size() != (sizeof(T) * arrayLength)) { // answers empty byte array if corrupt
uncompressedIn.setByteOrder(QDataStream::LittleEndian); throw QString("corrupt fbx file");
uncompressedIn.setVersion(QDataStream::Qt_4_5); // for single/double precision switch }
for (quint32 i = 0; i < arrayLength; i++) { } else {
T value; arrayData.resize(sizeof(T) * arrayLength);
uncompressedIn >> value; position += sizeof(T) * arrayLength;
values.append(value); in.readRawData(arrayData.data(), arrayData.size());
} }
memcpy(&values[0], arrayData.constData(), arrayData.size());
} else { } else {
for (quint32 i = 0; i < arrayLength; i++) { values.reserve(arrayLength);
T value; const unsigned int DEFLATE_ENCODING = 1;
in >> value; if (encoding == DEFLATE_ENCODING) {
position += streamSize<T>(); // preface encoded data with uncompressed length
values.append(value); QByteArray compressed(sizeof(quint32) + compressedLength, 0);
*((quint32*)compressed.data()) = qToBigEndian<quint32>(arrayLength * sizeof(T));
in.readRawData(compressed.data() + sizeof(quint32), compressedLength);
position += compressedLength;
QByteArray uncompressed = qUncompress(compressed);
if (uncompressed.isEmpty()) { // answers empty byte array if corrupt
throw QString("corrupt fbx file");
}
QDataStream uncompressedIn(uncompressed);
uncompressedIn.setByteOrder(QDataStream::LittleEndian);
uncompressedIn.setVersion(QDataStream::Qt_4_5); // for single/double precision switch
for (quint32 i = 0; i < arrayLength; i++) {
T value;
uncompressedIn >> value;
values.append(value);
}
} else {
for (quint32 i = 0; i < arrayLength; i++) {
T value;
in >> value;
position += streamSize<T>();
values.append(value);
}
} }
} }
return QVariant::fromValue(values); return QVariant::fromValue(values);