Convert serializers and FBX.h to use HifiTypes.h

This commit is contained in:
sabrina-shanman 2019-02-25 12:04:26 -08:00
parent 8ff212ac95
commit 2af17015d3
10 changed files with 177 additions and 179 deletions

View file

@ -13,16 +13,17 @@
#define hifi_FBX_h_ #define hifi_FBX_h_
#include <QMetaType> #include <QMetaType>
#include <QVarLengthArray>
#include <QVariant> #include <QVariant>
#include <QVector> #include <QVector>
#include <glm/glm.hpp> #include <glm/glm.hpp>
#include <shared/HifiTypes.h>
// See comment in FBXSerializer::parseFBX(). // See comment in FBXSerializer::parseFBX().
static const int FBX_HEADER_BYTES_BEFORE_VERSION = 23; static const int FBX_HEADER_BYTES_BEFORE_VERSION = 23;
static const QByteArray FBX_BINARY_PROLOG("Kaydara FBX Binary "); static const hifi::ByteArray FBX_BINARY_PROLOG("Kaydara FBX Binary ");
static const QByteArray FBX_BINARY_PROLOG2("\0\x1a\0", 3); static const hifi::ByteArray FBX_BINARY_PROLOG2("\0\x1a\0", 3);
static const quint32 FBX_VERSION_2015 = 7400; static const quint32 FBX_VERSION_2015 = 7400;
static const quint32 FBX_VERSION_2016 = 7500; static const quint32 FBX_VERSION_2016 = 7500;
@ -36,7 +37,7 @@ using FBXNodeList = QList<FBXNode>;
/// A node within an FBX document. /// A node within an FBX document.
class FBXNode { class FBXNode {
public: public:
QByteArray name; hifi::ByteArray name;
QVariantList properties; QVariantList properties;
FBXNodeList children; FBXNodeList children;
}; };

View file

@ -179,7 +179,7 @@ public:
void printNode(const FBXNode& node, int indentLevel) { void printNode(const FBXNode& node, int indentLevel) {
int indentLength = 2; int indentLength = 2;
QByteArray spaces(indentLevel * indentLength, ' '); hifi::ByteArray spaces(indentLevel * indentLength, ' ');
QDebug nodeDebug = qDebug(modelformat); QDebug nodeDebug = qDebug(modelformat);
nodeDebug.nospace() << spaces.data() << node.name.data() << ": "; nodeDebug.nospace() << spaces.data() << node.name.data() << ": ";
@ -309,7 +309,7 @@ public:
}; };
bool checkMaterialsHaveTextures(const QHash<QString, HFMMaterial>& materials, bool checkMaterialsHaveTextures(const QHash<QString, HFMMaterial>& materials,
const QHash<QString, QByteArray>& textureFilenames, const QMultiMap<QString, QString>& _connectionChildMap) { const QHash<QString, hifi::ByteArray>& textureFilenames, const QMultiMap<QString, QString>& _connectionChildMap) {
foreach (const QString& materialID, materials.keys()) { foreach (const QString& materialID, materials.keys()) {
foreach (const QString& childID, _connectionChildMap.values(materialID)) { foreach (const QString& childID, _connectionChildMap.values(materialID)) {
if (textureFilenames.contains(childID)) { if (textureFilenames.contains(childID)) {
@ -376,7 +376,7 @@ HFMLight extractLight(const FBXNode& object) {
return light; return light;
} }
QByteArray fileOnUrl(const QByteArray& filepath, const QString& url) { hifi::ByteArray fileOnUrl(const hifi::ByteArray& filepath, const QString& url) {
// in order to match the behaviour when loading models from remote URLs // in order to match the behaviour when loading models from remote URLs
// we assume that all external textures are right beside the loaded model // we assume that all external textures are right beside the loaded model
// ignoring any relative paths or absolute paths inside of models // ignoring any relative paths or absolute paths inside of models
@ -384,7 +384,7 @@ QByteArray fileOnUrl(const QByteArray& filepath, const QString& url) {
return filepath.mid(filepath.lastIndexOf('/') + 1); return filepath.mid(filepath.lastIndexOf('/') + 1);
} }
HFMModel* FBXSerializer::extractHFMModel(const QVariantHash& mapping, const QString& url) { HFMModel* FBXSerializer::extractHFMModel(const hifi::VariantHash& mapping, const QString& url) {
const FBXNode& node = _rootNode; const FBXNode& node = _rootNode;
QMap<QString, ExtractedMesh> meshes; QMap<QString, ExtractedMesh> meshes;
QHash<QString, QString> modelIDsToNames; QHash<QString, QString> modelIDsToNames;
@ -407,11 +407,11 @@ HFMModel* FBXSerializer::extractHFMModel(const QVariantHash& mapping, const QStr
std::map<QString, HFMLight> lights; std::map<QString, HFMLight> lights;
QVariantHash blendshapeMappings = mapping.value("bs").toHash(); hifi::VariantHash blendshapeMappings = mapping.value("bs").toHash();
QMultiHash<QByteArray, WeightedIndex> blendshapeIndices; QMultiHash<hifi::ByteArray, WeightedIndex> blendshapeIndices;
for (int i = 0;; i++) { for (int i = 0;; i++) {
QByteArray blendshapeName = FACESHIFT_BLENDSHAPES[i]; hifi::ByteArray blendshapeName = FACESHIFT_BLENDSHAPES[i];
if (blendshapeName.isEmpty()) { if (blendshapeName.isEmpty()) {
break; break;
} }
@ -454,7 +454,7 @@ HFMModel* FBXSerializer::extractHFMModel(const QVariantHash& mapping, const QStr
} }
} 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")); static const QVariant APPLICATION_NAME = QVariant(hifi::ByteArray("Original|ApplicationName"));
if (subsubobject.name == "P" && subsubobject.properties.size() >= 5 && if (subsubobject.name == "P" && subsubobject.properties.size() >= 5 &&
subsubobject.properties.at(0) == APPLICATION_NAME) { subsubobject.properties.at(0) == APPLICATION_NAME) {
hfmModel.applicationName = subsubobject.properties.at(4).toString(); hfmModel.applicationName = subsubobject.properties.at(4).toString();
@ -471,8 +471,8 @@ HFMModel* FBXSerializer::extractHFMModel(const QVariantHash& mapping, const QStr
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) {
static const QVariant UNIT_SCALE_FACTOR = QByteArray("UnitScaleFactor"); static const QVariant UNIT_SCALE_FACTOR = hifi::ByteArray("UnitScaleFactor");
static const QVariant AMBIENT_COLOR = QByteArray("AmbientColor"); static const QVariant AMBIENT_COLOR = hifi::ByteArray("AmbientColor");
const auto& subpropName = subobject.properties.at(0); const auto& subpropName = subobject.properties.at(0);
if (subpropName == UNIT_SCALE_FACTOR) { if (subpropName == UNIT_SCALE_FACTOR) {
unitScaleFactor = subobject.properties.at(index).toFloat(); unitScaleFactor = subobject.properties.at(index).toFloat();
@ -528,7 +528,7 @@ HFMModel* FBXSerializer::extractHFMModel(const QVariantHash& mapping, const QStr
QVector<ExtractedBlendshape> blendshapes; QVector<ExtractedBlendshape> blendshapes;
foreach (const FBXNode& subobject, object.children) { foreach (const FBXNode& subobject, object.children) {
bool properties = false; bool properties = false;
QByteArray propertyName; hifi::ByteArray propertyName;
int index; int index;
if (subobject.name == "Properties60") { if (subobject.name == "Properties60") {
properties = true; properties = true;
@ -541,27 +541,27 @@ HFMModel* FBXSerializer::extractHFMModel(const QVariantHash& mapping, const QStr
index = 4; index = 4;
} }
if (properties) { if (properties) {
static const QVariant ROTATION_ORDER = QByteArray("RotationOrder"); static const QVariant ROTATION_ORDER = hifi::ByteArray("RotationOrder");
static const QVariant GEOMETRIC_TRANSLATION = QByteArray("GeometricTranslation"); static const QVariant GEOMETRIC_TRANSLATION = hifi::ByteArray("GeometricTranslation");
static const QVariant GEOMETRIC_ROTATION = QByteArray("GeometricRotation"); static const QVariant GEOMETRIC_ROTATION = hifi::ByteArray("GeometricRotation");
static const QVariant GEOMETRIC_SCALING = QByteArray("GeometricScaling"); static const QVariant GEOMETRIC_SCALING = hifi::ByteArray("GeometricScaling");
static const QVariant LCL_TRANSLATION = QByteArray("Lcl Translation"); static const QVariant LCL_TRANSLATION = hifi::ByteArray("Lcl Translation");
static const QVariant LCL_ROTATION = QByteArray("Lcl Rotation"); static const QVariant LCL_ROTATION = hifi::ByteArray("Lcl Rotation");
static const QVariant LCL_SCALING = QByteArray("Lcl Scaling"); static const QVariant LCL_SCALING = hifi::ByteArray("Lcl Scaling");
static const QVariant ROTATION_MAX = QByteArray("RotationMax"); static const QVariant ROTATION_MAX = hifi::ByteArray("RotationMax");
static const QVariant ROTATION_MAX_X = QByteArray("RotationMaxX"); static const QVariant ROTATION_MAX_X = hifi::ByteArray("RotationMaxX");
static const QVariant ROTATION_MAX_Y = QByteArray("RotationMaxY"); static const QVariant ROTATION_MAX_Y = hifi::ByteArray("RotationMaxY");
static const QVariant ROTATION_MAX_Z = QByteArray("RotationMaxZ"); static const QVariant ROTATION_MAX_Z = hifi::ByteArray("RotationMaxZ");
static const QVariant ROTATION_MIN = QByteArray("RotationMin"); static const QVariant ROTATION_MIN = hifi::ByteArray("RotationMin");
static const QVariant ROTATION_MIN_X = QByteArray("RotationMinX"); static const QVariant ROTATION_MIN_X = hifi::ByteArray("RotationMinX");
static const QVariant ROTATION_MIN_Y = QByteArray("RotationMinY"); static const QVariant ROTATION_MIN_Y = hifi::ByteArray("RotationMinY");
static const QVariant ROTATION_MIN_Z = QByteArray("RotationMinZ"); static const QVariant ROTATION_MIN_Z = hifi::ByteArray("RotationMinZ");
static const QVariant ROTATION_OFFSET = QByteArray("RotationOffset"); static const QVariant ROTATION_OFFSET = hifi::ByteArray("RotationOffset");
static const QVariant ROTATION_PIVOT = QByteArray("RotationPivot"); static const QVariant ROTATION_PIVOT = hifi::ByteArray("RotationPivot");
static const QVariant SCALING_OFFSET = QByteArray("ScalingOffset"); static const QVariant SCALING_OFFSET = hifi::ByteArray("ScalingOffset");
static const QVariant SCALING_PIVOT = QByteArray("ScalingPivot"); static const QVariant SCALING_PIVOT = hifi::ByteArray("ScalingPivot");
static const QVariant PRE_ROTATION = QByteArray("PreRotation"); static const QVariant PRE_ROTATION = hifi::ByteArray("PreRotation");
static const QVariant POST_ROTATION = QByteArray("PostRotation"); static const QVariant POST_ROTATION = hifi::ByteArray("PostRotation");
foreach(const FBXNode& property, subobject.children) { foreach(const FBXNode& property, subobject.children) {
const auto& childProperty = property.properties.at(0); const auto& childProperty = property.properties.at(0);
if (property.name == propertyName) { if (property.name == propertyName) {
@ -701,8 +701,8 @@ HFMModel* FBXSerializer::extractHFMModel(const QVariantHash& mapping, const QStr
const int MODEL_UV_SCALING_MIN_SIZE = 2; const int MODEL_UV_SCALING_MIN_SIZE = 2;
const int CROPPING_MIN_SIZE = 4; const int CROPPING_MIN_SIZE = 4;
if (subobject.name == "RelativeFilename" && subobject.properties.length() >= RELATIVE_FILENAME_MIN_SIZE) { if (subobject.name == "RelativeFilename" && subobject.properties.length() >= RELATIVE_FILENAME_MIN_SIZE) {
QByteArray filename = subobject.properties.at(0).toByteArray(); hifi::ByteArray filename = subobject.properties.at(0).toByteArray();
QByteArray filepath = filename.replace('\\', '/'); hifi::ByteArray filepath = filename.replace('\\', '/');
filename = fileOnUrl(filepath, url); filename = fileOnUrl(filepath, url);
_textureFilepaths.insert(getID(object.properties), filepath); _textureFilepaths.insert(getID(object.properties), filepath);
_textureFilenames.insert(getID(object.properties), filename); _textureFilenames.insert(getID(object.properties), filename);
@ -731,17 +731,17 @@ HFMModel* FBXSerializer::extractHFMModel(const QVariantHash& mapping, const QStr
subobject.properties.at(2).value<int>(), subobject.properties.at(2).value<int>(),
subobject.properties.at(3).value<int>())); subobject.properties.at(3).value<int>()));
} else if (subobject.name == "Properties70") { } else if (subobject.name == "Properties70") {
QByteArray propertyName; hifi::ByteArray propertyName;
int index; int index;
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 UV_SET = hifi::ByteArray("UVSet");
static const QVariant CURRENT_TEXTURE_BLEND_MODE = QByteArray("CurrentTextureBlendMode"); static const QVariant CURRENT_TEXTURE_BLEND_MODE = hifi::ByteArray("CurrentTextureBlendMode");
static const QVariant USE_MATERIAL = QByteArray("UseMaterial"); static const QVariant USE_MATERIAL = hifi::ByteArray("UseMaterial");
static const QVariant TRANSLATION = QByteArray("Translation"); static const QVariant TRANSLATION = hifi::ByteArray("Translation");
static const QVariant ROTATION = QByteArray("Rotation"); static const QVariant ROTATION = hifi::ByteArray("Rotation");
static const QVariant SCALING = QByteArray("Scaling"); static const QVariant SCALING = hifi::ByteArray("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) == UV_SET) { if (property.properties.at(0) == UV_SET) {
@ -795,8 +795,8 @@ HFMModel* FBXSerializer::extractHFMModel(const QVariantHash& mapping, const QStr
_textureParams.insert(getID(object.properties), tex); _textureParams.insert(getID(object.properties), tex);
} }
} else if (object.name == "Video") { } else if (object.name == "Video") {
QByteArray filepath; hifi::ByteArray filepath;
QByteArray content; hifi::ByteArray content;
foreach (const FBXNode& subobject, object.children) { foreach (const FBXNode& subobject, object.children) {
if (subobject.name == "RelativeFilename") { if (subobject.name == "RelativeFilename") {
filepath = subobject.properties.at(0).toByteArray(); filepath = subobject.properties.at(0).toByteArray();
@ -816,7 +816,7 @@ HFMModel* FBXSerializer::extractHFMModel(const QVariantHash& mapping, const QStr
foreach (const FBXNode& subobject, object.children) { foreach (const FBXNode& subobject, object.children) {
bool properties = false; bool properties = false;
QByteArray propertyName; hifi::ByteArray propertyName;
int index; int index;
if (subobject.name == "Properties60") { if (subobject.name == "Properties60") {
properties = true; properties = true;
@ -833,31 +833,31 @@ HFMModel* FBXSerializer::extractHFMModel(const QVariantHash& mapping, const QStr
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_COLOR = hifi::ByteArray("DiffuseColor");
static const QVariant DIFFUSE_FACTOR = QByteArray("DiffuseFactor"); static const QVariant DIFFUSE_FACTOR = hifi::ByteArray("DiffuseFactor");
static const QVariant DIFFUSE = QByteArray("Diffuse"); static const QVariant DIFFUSE = hifi::ByteArray("Diffuse");
static const QVariant SPECULAR_COLOR = QByteArray("SpecularColor"); static const QVariant SPECULAR_COLOR = hifi::ByteArray("SpecularColor");
static const QVariant SPECULAR_FACTOR = QByteArray("SpecularFactor"); static const QVariant SPECULAR_FACTOR = hifi::ByteArray("SpecularFactor");
static const QVariant SPECULAR = QByteArray("Specular"); static const QVariant SPECULAR = hifi::ByteArray("Specular");
static const QVariant EMISSIVE_COLOR = QByteArray("EmissiveColor"); static const QVariant EMISSIVE_COLOR = hifi::ByteArray("EmissiveColor");
static const QVariant EMISSIVE_FACTOR = QByteArray("EmissiveFactor"); static const QVariant EMISSIVE_FACTOR = hifi::ByteArray("EmissiveFactor");
static const QVariant EMISSIVE = QByteArray("Emissive"); static const QVariant EMISSIVE = hifi::ByteArray("Emissive");
static const QVariant AMBIENT_FACTOR = QByteArray("AmbientFactor"); static const QVariant AMBIENT_FACTOR = hifi::ByteArray("AmbientFactor");
static const QVariant SHININESS = QByteArray("Shininess"); static const QVariant SHININESS = hifi::ByteArray("Shininess");
static const QVariant OPACITY = QByteArray("Opacity"); static const QVariant OPACITY = hifi::ByteArray("Opacity");
static const QVariant MAYA_USE_NORMAL_MAP = QByteArray("Maya|use_normal_map"); static const QVariant MAYA_USE_NORMAL_MAP = hifi::ByteArray("Maya|use_normal_map");
static const QVariant MAYA_BASE_COLOR = QByteArray("Maya|base_color"); static const QVariant MAYA_BASE_COLOR = hifi::ByteArray("Maya|base_color");
static const QVariant MAYA_USE_COLOR_MAP = QByteArray("Maya|use_color_map"); static const QVariant MAYA_USE_COLOR_MAP = hifi::ByteArray("Maya|use_color_map");
static const QVariant MAYA_ROUGHNESS = QByteArray("Maya|roughness"); static const QVariant MAYA_ROUGHNESS = hifi::ByteArray("Maya|roughness");
static const QVariant MAYA_USE_ROUGHNESS_MAP = QByteArray("Maya|use_roughness_map"); static const QVariant MAYA_USE_ROUGHNESS_MAP = hifi::ByteArray("Maya|use_roughness_map");
static const QVariant MAYA_METALLIC = QByteArray("Maya|metallic"); static const QVariant MAYA_METALLIC = hifi::ByteArray("Maya|metallic");
static const QVariant MAYA_USE_METALLIC_MAP = QByteArray("Maya|use_metallic_map"); static const QVariant MAYA_USE_METALLIC_MAP = hifi::ByteArray("Maya|use_metallic_map");
static const QVariant MAYA_EMISSIVE = QByteArray("Maya|emissive"); static const QVariant MAYA_EMISSIVE = hifi::ByteArray("Maya|emissive");
static const QVariant MAYA_EMISSIVE_INTENSITY = QByteArray("Maya|emissive_intensity"); static const QVariant MAYA_EMISSIVE_INTENSITY = hifi::ByteArray("Maya|emissive_intensity");
static const QVariant MAYA_USE_EMISSIVE_MAP = QByteArray("Maya|use_emissive_map"); static const QVariant MAYA_USE_EMISSIVE_MAP = hifi::ByteArray("Maya|use_emissive_map");
static const QVariant MAYA_USE_AO_MAP = QByteArray("Maya|use_ao_map"); static const QVariant MAYA_USE_AO_MAP = hifi::ByteArray("Maya|use_ao_map");
static const QVariant MAYA_UV_SCALE = QByteArray("Maya|uv_scale"); static const QVariant MAYA_UV_SCALE = hifi::ByteArray("Maya|uv_scale");
static const QVariant MAYA_UV_OFFSET = QByteArray("Maya|uv_offset"); static const QVariant MAYA_UV_OFFSET = hifi::ByteArray("Maya|uv_offset");
static const int MAYA_UV_OFFSET_PROPERTY_LENGTH = 6; static const int MAYA_UV_OFFSET_PROPERTY_LENGTH = 6;
static const int MAYA_UV_SCALE_PROPERTY_LENGTH = 6; static const int MAYA_UV_SCALE_PROPERTY_LENGTH = 6;
@ -1034,7 +1034,7 @@ HFMModel* FBXSerializer::extractHFMModel(const QVariantHash& mapping, const QStr
clusters.insert(getID(object.properties), cluster); clusters.insert(getID(object.properties), cluster);
} else if (object.properties.last() == "BlendShapeChannel") { } else if (object.properties.last() == "BlendShapeChannel") {
QByteArray name = object.properties.at(1).toByteArray(); hifi::ByteArray name = object.properties.at(1).toByteArray();
name = name.left(name.indexOf('\0')); name = name.left(name.indexOf('\0'));
if (!blendshapeIndices.contains(name)) { if (!blendshapeIndices.contains(name)) {
@ -1071,8 +1071,8 @@ HFMModel* FBXSerializer::extractHFMModel(const QVariantHash& mapping, const QStr
#endif #endif
} }
} else if (child.name == "Connections") { } else if (child.name == "Connections") {
static const QVariant OO = QByteArray("OO"); static const QVariant OO = hifi::ByteArray("OO");
static const QVariant OP = QByteArray("OP"); static const QVariant OP = hifi::ByteArray("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) {
@ -1091,7 +1091,7 @@ HFMModel* FBXSerializer::extractHFMModel(const QVariantHash& mapping, const QStr
} }
} else if (connection.properties.at(0) == OP) { } else if (connection.properties.at(0) == OP) {
int counter = 0; int counter = 0;
QByteArray type = connection.properties.at(3).toByteArray().toLower(); hifi::ByteArray type = connection.properties.at(3).toByteArray().toLower();
if (type.contains("DiffuseFactor")) { if (type.contains("DiffuseFactor")) {
diffuseFactorTextures.insert(getID(connection.properties, 2), getID(connection.properties, 1)); diffuseFactorTextures.insert(getID(connection.properties, 2), getID(connection.properties, 1));
} else if ((type.contains("diffuse") && !type.contains("tex_global_diffuse"))) { } else if ((type.contains("diffuse") && !type.contains("tex_global_diffuse"))) {
@ -1678,8 +1678,8 @@ std::unique_ptr<hfm::Serializer::Factory> FBXSerializer::getFactory() const {
return std::make_unique<hfm::Serializer::SimpleFactory<FBXSerializer>>(); return std::make_unique<hfm::Serializer::SimpleFactory<FBXSerializer>>();
} }
HFMModel::Pointer FBXSerializer::read(const QByteArray& data, const QVariantHash& mapping, const QUrl& url) { HFMModel::Pointer FBXSerializer::read(const hifi::ByteArray& data, const hifi::VariantHash& mapping, const hifi::URL& url) {
QBuffer buffer(const_cast<QByteArray*>(&data)); QBuffer buffer(const_cast<hifi::ByteArray*>(&data));
buffer.open(QIODevice::ReadOnly); buffer.open(QIODevice::ReadOnly);
_rootNode = parseFBX(&buffer); _rootNode = parseFBX(&buffer);

View file

@ -15,9 +15,6 @@
#include <QtGlobal> #include <QtGlobal>
#include <QMetaType> #include <QMetaType>
#include <QSet> #include <QSet>
#include <QUrl>
#include <QVarLengthArray>
#include <QVariant>
#include <QVector> #include <QVector>
#include <glm/glm.hpp> #include <glm/glm.hpp>
@ -25,6 +22,7 @@
#include <Extents.h> #include <Extents.h>
#include <Transform.h> #include <Transform.h>
#include <shared/HifiTypes.h>
#include "FBX.h" #include "FBX.h"
#include <hfm/HFMSerializer.h> #include <hfm/HFMSerializer.h>
@ -114,12 +112,12 @@ public:
HFMModel* _hfmModel; HFMModel* _hfmModel;
/// Reads HFMModel from the supplied model and mapping data. /// Reads HFMModel from the supplied model and mapping data.
/// \exception QString if an error occurs in parsing /// \exception QString if an error occurs in parsing
HFMModel::Pointer read(const QByteArray& data, const QVariantHash& mapping, const QUrl& url = QUrl()) override; HFMModel::Pointer read(const hifi::ByteArray& data, const hifi::VariantHash& mapping, const hifi::URL& url = hifi::URL()) override;
FBXNode _rootNode; FBXNode _rootNode;
static FBXNode parseFBX(QIODevice* device); static FBXNode parseFBX(QIODevice* device);
HFMModel* extractHFMModel(const QVariantHash& mapping, const QString& url); HFMModel* extractHFMModel(const hifi::VariantHash& mapping, const QString& url);
static ExtractedMesh extractMesh(const FBXNode& object, unsigned int& meshIndex, bool deduplicate = true); static ExtractedMesh extractMesh(const FBXNode& object, unsigned int& meshIndex, bool deduplicate = true);
QHash<QString, ExtractedMesh> meshes; QHash<QString, ExtractedMesh> meshes;
@ -128,11 +126,11 @@ public:
QHash<QString, QString> _textureNames; QHash<QString, QString> _textureNames;
// Hashes the original RelativeFilename of textures // Hashes the original RelativeFilename of textures
QHash<QString, QByteArray> _textureFilepaths; QHash<QString, hifi::ByteArray> _textureFilepaths;
// Hashes the place to look for textures, in case they are not inlined // Hashes the place to look for textures, in case they are not inlined
QHash<QString, QByteArray> _textureFilenames; QHash<QString, hifi::ByteArray> _textureFilenames;
// Hashes texture content by filepath, in case they are inlined // Hashes texture content by filepath, in case they are inlined
QHash<QByteArray, QByteArray> _textureContent; QHash<hifi::ByteArray, hifi::ByteArray> _textureContent;
QHash<QString, TextureParam> _textureParams; QHash<QString, TextureParam> _textureParams;

View file

@ -15,7 +15,6 @@
#include <memory> #include <memory>
#include <QBuffer> #include <QBuffer>
#include <QDataStream>
#include <QIODevice> #include <QIODevice>
#include <QStringList> #include <QStringList>
#include <QTextStream> #include <QTextStream>
@ -29,7 +28,7 @@
HFMTexture FBXSerializer::getTexture(const QString& textureID, const QString& materialID) { HFMTexture FBXSerializer::getTexture(const QString& textureID, const QString& materialID) {
HFMTexture texture; HFMTexture texture;
const QByteArray& filepath = _textureFilepaths.value(textureID); const hifi::ByteArray& filepath = _textureFilepaths.value(textureID);
texture.content = _textureContent.value(filepath); texture.content = _textureContent.value(filepath);
if (texture.content.isEmpty()) { // the content is not inlined if (texture.content.isEmpty()) { // the content is not inlined

View file

@ -190,8 +190,8 @@ ExtractedMesh FBXSerializer::extractMesh(const FBXNode& object, unsigned int& me
bool isMaterialPerPolygon = false; bool isMaterialPerPolygon = false;
static const QVariant BY_VERTICE = QByteArray("ByVertice"); static const QVariant BY_VERTICE = hifi::ByteArray("ByVertice");
static const QVariant INDEX_TO_DIRECT = QByteArray("IndexToDirect"); static const QVariant INDEX_TO_DIRECT = hifi::ByteArray("IndexToDirect");
bool isDracoMesh = false; bool isDracoMesh = false;
@ -321,7 +321,7 @@ ExtractedMesh FBXSerializer::extractMesh(const FBXNode& object, unsigned int& me
} }
} }
} else if (child.name == "LayerElementMaterial") { } else if (child.name == "LayerElementMaterial") {
static const QVariant BY_POLYGON = QByteArray("ByPolygon"); static const QVariant BY_POLYGON = hifi::ByteArray("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);
@ -348,7 +348,7 @@ ExtractedMesh FBXSerializer::extractMesh(const FBXNode& object, unsigned int& me
// load the draco mesh from the FBX and create a draco::Mesh // load the draco mesh from the FBX and create a draco::Mesh
draco::Decoder decoder; draco::Decoder decoder;
draco::DecoderBuffer decodedBuffer; draco::DecoderBuffer decodedBuffer;
QByteArray dracoArray = child.properties.at(0).value<QByteArray>(); hifi::ByteArray dracoArray = child.properties.at(0).value<hifi::ByteArray>();
decodedBuffer.Init(dracoArray.data(), dracoArray.size()); decodedBuffer.Init(dracoArray.data(), dracoArray.size());
std::unique_ptr<draco::Mesh> dracoMesh(new draco::Mesh()); std::unique_ptr<draco::Mesh> dracoMesh(new draco::Mesh());

View file

@ -48,10 +48,10 @@ QVariant readBinaryArray(QDataStream& in, int& position) {
QVector<T> values; QVector<T> values;
if ((int)QSysInfo::ByteOrder == (int)in.byteOrder()) { if ((int)QSysInfo::ByteOrder == (int)in.byteOrder()) {
values.resize(arrayLength); values.resize(arrayLength);
QByteArray arrayData; hifi::ByteArray arrayData;
if (encoding == FBX_PROPERTY_COMPRESSED_FLAG) { if (encoding == FBX_PROPERTY_COMPRESSED_FLAG) {
// preface encoded data with uncompressed length // preface encoded data with uncompressed length
QByteArray compressed(sizeof(quint32) + compressedLength, 0); hifi::ByteArray compressed(sizeof(quint32) + compressedLength, 0);
*((quint32*)compressed.data()) = qToBigEndian<quint32>(arrayLength * sizeof(T)); *((quint32*)compressed.data()) = qToBigEndian<quint32>(arrayLength * sizeof(T));
in.readRawData(compressed.data() + sizeof(quint32), compressedLength); in.readRawData(compressed.data() + sizeof(quint32), compressedLength);
position += compressedLength; position += compressedLength;
@ -73,11 +73,11 @@ QVariant readBinaryArray(QDataStream& in, int& position) {
values.reserve(arrayLength); values.reserve(arrayLength);
if (encoding == FBX_PROPERTY_COMPRESSED_FLAG) { if (encoding == FBX_PROPERTY_COMPRESSED_FLAG) {
// preface encoded data with uncompressed length // preface encoded data with uncompressed length
QByteArray compressed(sizeof(quint32) + compressedLength, 0); hifi::ByteArray compressed(sizeof(quint32) + compressedLength, 0);
*((quint32*)compressed.data()) = qToBigEndian<quint32>(arrayLength * sizeof(T)); *((quint32*)compressed.data()) = qToBigEndian<quint32>(arrayLength * sizeof(T));
in.readRawData(compressed.data() + sizeof(quint32), compressedLength); in.readRawData(compressed.data() + sizeof(quint32), compressedLength);
position += compressedLength; position += compressedLength;
QByteArray uncompressed = qUncompress(compressed); hifi::ByteArray uncompressed = qUncompress(compressed);
if (uncompressed.isEmpty()) { // answers empty byte array if corrupt if (uncompressed.isEmpty()) { // answers empty byte array if corrupt
throw QString("corrupt fbx file"); throw QString("corrupt fbx file");
} }
@ -234,7 +234,7 @@ public:
}; };
int nextToken(); int nextToken();
const QByteArray& getDatum() const { return _datum; } const hifi::ByteArray& getDatum() const { return _datum; }
void pushBackToken(int token) { _pushedBackToken = token; } void pushBackToken(int token) { _pushedBackToken = token; }
void ungetChar(char ch) { _device->ungetChar(ch); } void ungetChar(char ch) { _device->ungetChar(ch); }
@ -242,7 +242,7 @@ public:
private: private:
QIODevice* _device; QIODevice* _device;
QByteArray _datum; hifi::ByteArray _datum;
int _pushedBackToken; int _pushedBackToken;
}; };
@ -325,7 +325,7 @@ FBXNode parseTextFBXNode(Tokenizer& tokenizer) {
expectingDatum = true; expectingDatum = true;
} else if (token == Tokenizer::DATUM_TOKEN && expectingDatum) { } else if (token == Tokenizer::DATUM_TOKEN && expectingDatum) {
QByteArray datum = tokenizer.getDatum(); hifi::ByteArray datum = tokenizer.getDatum();
if ((token = tokenizer.nextToken()) == ':') { if ((token = tokenizer.nextToken()) == ':') {
tokenizer.ungetChar(':'); tokenizer.ungetChar(':');
tokenizer.pushBackToken(Tokenizer::DATUM_TOKEN); tokenizer.pushBackToken(Tokenizer::DATUM_TOKEN);

View file

@ -125,18 +125,18 @@ bool GLTFSerializer::getObjectArrayVal(const QJsonObject& object, const QString&
return _defined; return _defined;
} }
QByteArray GLTFSerializer::setGLBChunks(const QByteArray& data) { hifi::ByteArray GLTFSerializer::setGLBChunks(const hifi::ByteArray& data) {
int byte = 4; int byte = 4;
int jsonStart = data.indexOf("JSON", Qt::CaseSensitive); int jsonStart = data.indexOf("JSON", Qt::CaseSensitive);
int binStart = data.indexOf("BIN", Qt::CaseSensitive); int binStart = data.indexOf("BIN", Qt::CaseSensitive);
int jsonLength, binLength; int jsonLength, binLength;
QByteArray jsonLengthChunk, binLengthChunk; hifi::ByteArray jsonLengthChunk, binLengthChunk;
jsonLengthChunk = data.mid(jsonStart - byte, byte); jsonLengthChunk = data.mid(jsonStart - byte, byte);
QDataStream tempJsonLen(jsonLengthChunk); QDataStream tempJsonLen(jsonLengthChunk);
tempJsonLen.setByteOrder(QDataStream::LittleEndian); tempJsonLen.setByteOrder(QDataStream::LittleEndian);
tempJsonLen >> jsonLength; tempJsonLen >> jsonLength;
QByteArray jsonChunk = data.mid(jsonStart + byte, jsonLength); hifi::ByteArray jsonChunk = data.mid(jsonStart + byte, jsonLength);
if (binStart != -1) { if (binStart != -1) {
binLengthChunk = data.mid(binStart - byte, byte); binLengthChunk = data.mid(binStart - byte, byte);
@ -567,10 +567,10 @@ bool GLTFSerializer::addTexture(const QJsonObject& object) {
return true; return true;
} }
bool GLTFSerializer::parseGLTF(const QByteArray& data) { bool GLTFSerializer::parseGLTF(const hifi::ByteArray& data) {
PROFILE_RANGE_EX(resource_parse, __FUNCTION__, 0xffff0000, nullptr); PROFILE_RANGE_EX(resource_parse, __FUNCTION__, 0xffff0000, nullptr);
QByteArray jsonChunk = data; hifi::ByteArray jsonChunk = data;
if (_url.toString().endsWith("glb") && data.indexOf("glTF") == 0 && data.contains("JSON")) { if (_url.toString().endsWith("glb") && data.indexOf("glTF") == 0 && data.contains("JSON")) {
jsonChunk = setGLBChunks(data); jsonChunk = setGLBChunks(data);
@ -734,7 +734,7 @@ glm::mat4 GLTFSerializer::getModelTransform(const GLTFNode& node) {
return tmat; return tmat;
} }
bool GLTFSerializer::buildGeometry(HFMModel& hfmModel, const QUrl& url) { bool GLTFSerializer::buildGeometry(HFMModel& hfmModel, const hifi::URL& url) {
//Build dependencies //Build dependencies
QVector<QVector<int>> nodeDependencies(_file.nodes.size()); QVector<QVector<int>> nodeDependencies(_file.nodes.size());
@ -993,15 +993,15 @@ std::unique_ptr<hfm::Serializer::Factory> GLTFSerializer::getFactory() const {
return std::make_unique<hfm::Serializer::SimpleFactory<GLTFSerializer>>(); return std::make_unique<hfm::Serializer::SimpleFactory<GLTFSerializer>>();
} }
HFMModel::Pointer GLTFSerializer::read(const QByteArray& data, const QVariantHash& mapping, const QUrl& url) { HFMModel::Pointer GLTFSerializer::read(const hifi::ByteArray& data, const hifi::VariantHash& mapping, const hifi::URL& url) {
_url = url; _url = url;
// Normalize url for local files // Normalize url for local files
QUrl normalizeUrl = DependencyManager::get<ResourceManager>()->normalizeURL(_url); hifi::URL normalizeUrl = DependencyManager::get<ResourceManager>()->normalizeURL(_url);
if (normalizeUrl.scheme().isEmpty() || (normalizeUrl.scheme() == "file")) { if (normalizeUrl.scheme().isEmpty() || (normalizeUrl.scheme() == "file")) {
QString localFileName = PathUtils::expandToLocalDataAbsolutePath(normalizeUrl).toLocalFile(); QString localFileName = PathUtils::expandToLocalDataAbsolutePath(normalizeUrl).toLocalFile();
_url = QUrl(QFileInfo(localFileName).absoluteFilePath()); _url = hifi::URL(QFileInfo(localFileName).absoluteFilePath());
} }
if (parseGLTF(data)) { if (parseGLTF(data)) {
@ -1019,15 +1019,15 @@ HFMModel::Pointer GLTFSerializer::read(const QByteArray& data, const QVariantHas
return nullptr; return nullptr;
} }
bool GLTFSerializer::readBinary(const QString& url, QByteArray& outdata) { bool GLTFSerializer::readBinary(const QString& url, hifi::ByteArray& outdata) {
bool success; bool success;
if (url.contains("data:application/octet-stream;base64,")) { if (url.contains("data:application/octet-stream;base64,")) {
outdata = requestEmbeddedData(url); outdata = requestEmbeddedData(url);
success = !outdata.isEmpty(); success = !outdata.isEmpty();
} else { } else {
QUrl binaryUrl = _url.resolved(url); hifi::URL binaryUrl = _url.resolved(url);
std::tie<bool, QByteArray>(success, outdata) = requestData(binaryUrl); std::tie<bool, hifi::ByteArray>(success, outdata) = requestData(binaryUrl);
} }
return success; return success;
@ -1037,16 +1037,16 @@ bool GLTFSerializer::doesResourceExist(const QString& url) {
if (_url.isEmpty()) { if (_url.isEmpty()) {
return false; return false;
} }
QUrl candidateUrl = _url.resolved(url); hifi::URL candidateUrl = _url.resolved(url);
return DependencyManager::get<ResourceManager>()->resourceExists(candidateUrl); return DependencyManager::get<ResourceManager>()->resourceExists(candidateUrl);
} }
std::tuple<bool, QByteArray> GLTFSerializer::requestData(QUrl& url) { std::tuple<bool, hifi::ByteArray> GLTFSerializer::requestData(hifi::URL& url) {
auto request = DependencyManager::get<ResourceManager>()->createResourceRequest( auto request = DependencyManager::get<ResourceManager>()->createResourceRequest(
nullptr, url, true, -1, "GLTFSerializer::requestData"); nullptr, url, true, -1, "GLTFSerializer::requestData");
if (!request) { if (!request) {
return std::make_tuple(false, QByteArray()); return std::make_tuple(false, hifi::ByteArray());
} }
QEventLoop loop; QEventLoop loop;
@ -1057,17 +1057,17 @@ std::tuple<bool, QByteArray> GLTFSerializer::requestData(QUrl& url) {
if (request->getResult() == ResourceRequest::Success) { if (request->getResult() == ResourceRequest::Success) {
return std::make_tuple(true, request->getData()); return std::make_tuple(true, request->getData());
} else { } else {
return std::make_tuple(false, QByteArray()); return std::make_tuple(false, hifi::ByteArray());
} }
} }
QByteArray GLTFSerializer::requestEmbeddedData(const QString& url) { hifi::ByteArray GLTFSerializer::requestEmbeddedData(const QString& url) {
QString binaryUrl = url.split(",")[1]; QString binaryUrl = url.split(",")[1];
return binaryUrl.isEmpty() ? QByteArray() : QByteArray::fromBase64(binaryUrl.toUtf8()); return binaryUrl.isEmpty() ? hifi::ByteArray() : QByteArray::fromBase64(binaryUrl.toUtf8());
} }
QNetworkReply* GLTFSerializer::request(QUrl& url, bool isTest) { QNetworkReply* GLTFSerializer::request(hifi::URL& url, bool isTest) {
if (!qApp) { if (!qApp) {
return nullptr; return nullptr;
} }
@ -1098,8 +1098,8 @@ HFMTexture GLTFSerializer::getHFMTexture(const GLTFTexture& texture) {
if (texture.defined["source"]) { if (texture.defined["source"]) {
QString url = _file.images[texture.source].uri; QString url = _file.images[texture.source].uri;
QString fname = QUrl(url).fileName(); QString fname = hifi::URL(url).fileName();
QUrl textureUrl = _url.resolved(url); hifi::URL textureUrl = _url.resolved(url);
qCDebug(modelformat) << "fname: " << fname; qCDebug(modelformat) << "fname: " << fname;
fbxtex.name = fname; fbxtex.name = fname;
fbxtex.filename = textureUrl.toEncoded(); fbxtex.filename = textureUrl.toEncoded();
@ -1187,7 +1187,7 @@ void GLTFSerializer::setHFMMaterial(HFMMaterial& fbxmat, const GLTFMaterial& mat
} }
template<typename T, typename L> template<typename T, typename L>
bool GLTFSerializer::readArray(const QByteArray& bin, int byteOffset, int count, bool GLTFSerializer::readArray(const hifi::ByteArray& bin, int byteOffset, int count,
QVector<L>& outarray, int accessorType) { QVector<L>& outarray, int accessorType) {
QDataStream blobstream(bin); QDataStream blobstream(bin);
@ -1244,7 +1244,7 @@ bool GLTFSerializer::readArray(const QByteArray& bin, int byteOffset, int count,
return true; return true;
} }
template<typename T> template<typename T>
bool GLTFSerializer::addArrayOfType(const QByteArray& bin, int byteOffset, int count, bool GLTFSerializer::addArrayOfType(const hifi::ByteArray& bin, int byteOffset, int count,
QVector<T>& outarray, int accessorType, int componentType) { QVector<T>& outarray, int accessorType, int componentType) {
switch (componentType) { switch (componentType) {

View file

@ -214,7 +214,7 @@ struct GLTFBufferView {
struct GLTFBuffer { struct GLTFBuffer {
int byteLength; //required int byteLength; //required
QString uri; QString uri;
QByteArray blob; hifi::ByteArray blob;
QMap<QString, bool> defined; QMap<QString, bool> defined;
void dump() { void dump() {
if (defined["byteLength"]) { if (defined["byteLength"]) {
@ -705,16 +705,16 @@ public:
MediaType getMediaType() const override; MediaType getMediaType() const override;
std::unique_ptr<hfm::Serializer::Factory> getFactory() const override; std::unique_ptr<hfm::Serializer::Factory> getFactory() const override;
HFMModel::Pointer read(const QByteArray& data, const QVariantHash& mapping, const QUrl& url = QUrl()) override; HFMModel::Pointer read(const hifi::ByteArray& data, const hifi::VariantHash& mapping, const hifi::URL& url = hifi::URL()) override;
private: private:
GLTFFile _file; GLTFFile _file;
QUrl _url; hifi::URL _url;
QByteArray _glbBinary; hifi::ByteArray _glbBinary;
glm::mat4 getModelTransform(const GLTFNode& node); glm::mat4 getModelTransform(const GLTFNode& node);
bool buildGeometry(HFMModel& hfmModel, const QUrl& url); bool buildGeometry(HFMModel& hfmModel, const hifi::URL& url);
bool parseGLTF(const QByteArray& data); bool parseGLTF(const hifi::ByteArray& data);
bool getStringVal(const QJsonObject& object, const QString& fieldname, bool getStringVal(const QJsonObject& object, const QString& fieldname,
QString& value, QMap<QString, bool>& defined); QString& value, QMap<QString, bool>& defined);
@ -733,7 +733,7 @@ private:
bool getObjectArrayVal(const QJsonObject& object, const QString& fieldname, bool getObjectArrayVal(const QJsonObject& object, const QString& fieldname,
QJsonArray& objects, QMap<QString, bool>& defined); QJsonArray& objects, QMap<QString, bool>& defined);
QByteArray setGLBChunks(const QByteArray& data); hifi::ByteArray setGLBChunks(const hifi::ByteArray& data);
int getMaterialAlphaMode(const QString& type); int getMaterialAlphaMode(const QString& type);
int getAccessorType(const QString& type); int getAccessorType(const QString& type);
@ -760,24 +760,24 @@ private:
bool addSkin(const QJsonObject& object); bool addSkin(const QJsonObject& object);
bool addTexture(const QJsonObject& object); bool addTexture(const QJsonObject& object);
bool readBinary(const QString& url, QByteArray& outdata); bool readBinary(const QString& url, hifi::ByteArray& outdata);
template<typename T, typename L> template<typename T, typename L>
bool readArray(const QByteArray& bin, int byteOffset, int count, bool readArray(const hifi::ByteArray& bin, int byteOffset, int count,
QVector<L>& outarray, int accessorType); QVector<L>& outarray, int accessorType);
template<typename T> template<typename T>
bool addArrayOfType(const QByteArray& bin, int byteOffset, int count, bool addArrayOfType(const hifi::ByteArray& bin, int byteOffset, int count,
QVector<T>& outarray, int accessorType, int componentType); QVector<T>& outarray, int accessorType, int componentType);
void retriangulate(const QVector<int>& in_indices, const QVector<glm::vec3>& in_vertices, void retriangulate(const QVector<int>& in_indices, const QVector<glm::vec3>& in_vertices,
const QVector<glm::vec3>& in_normals, QVector<int>& out_indices, const QVector<glm::vec3>& in_normals, QVector<int>& out_indices,
QVector<glm::vec3>& out_vertices, QVector<glm::vec3>& out_normals); QVector<glm::vec3>& out_vertices, QVector<glm::vec3>& out_normals);
std::tuple<bool, QByteArray> requestData(QUrl& url); std::tuple<bool, hifi::ByteArray> requestData(hifi::URL& url);
QByteArray requestEmbeddedData(const QString& url); hifi::ByteArray requestEmbeddedData(const QString& url);
QNetworkReply* request(QUrl& url, bool isTest); QNetworkReply* request(hifi::URL& url, bool isTest);
bool doesResourceExist(const QString& url); bool doesResourceExist(const QString& url);

View file

@ -54,7 +54,7 @@ T& checked_at(QVector<T>& vector, int i) {
OBJTokenizer::OBJTokenizer(QIODevice* device) : _device(device), _pushedBackToken(-1) { OBJTokenizer::OBJTokenizer(QIODevice* device) : _device(device), _pushedBackToken(-1) {
} }
const QByteArray OBJTokenizer::getLineAsDatum() { const hifi::ByteArray OBJTokenizer::getLineAsDatum() {
return _device->readLine().trimmed(); return _device->readLine().trimmed();
} }
@ -117,7 +117,7 @@ bool OBJTokenizer::isNextTokenFloat() {
if (nextToken() != OBJTokenizer::DATUM_TOKEN) { if (nextToken() != OBJTokenizer::DATUM_TOKEN) {
return false; return false;
} }
QByteArray token = getDatum(); hifi::ByteArray token = getDatum();
pushBackToken(OBJTokenizer::DATUM_TOKEN); pushBackToken(OBJTokenizer::DATUM_TOKEN);
bool ok; bool ok;
token.toFloat(&ok); token.toFloat(&ok);
@ -182,7 +182,7 @@ void setMeshPartDefaults(HFMMeshPart& meshPart, QString materialID) {
// OBJFace // OBJFace
// NOTE (trent, 7/20/17): The vertexColors vector being passed-in isn't necessary here, but I'm just // NOTE (trent, 7/20/17): The vertexColors vector being passed-in isn't necessary here, but I'm just
// pairing it with the vertices vector for consistency. // pairing it with the vertices vector for consistency.
bool OBJFace::add(const QByteArray& vertexIndex, const QByteArray& textureIndex, const QByteArray& normalIndex, const QVector<glm::vec3>& vertices, const QVector<glm::vec3>& vertexColors) { bool OBJFace::add(const hifi::ByteArray& vertexIndex, const hifi::ByteArray& textureIndex, const hifi::ByteArray& normalIndex, const QVector<glm::vec3>& vertices, const QVector<glm::vec3>& vertexColors) {
bool ok; bool ok;
int index = vertexIndex.toInt(&ok); int index = vertexIndex.toInt(&ok);
if (!ok) { if (!ok) {
@ -238,11 +238,11 @@ void OBJFace::addFrom(const OBJFace* face, int index) { // add using data from f
} }
} }
bool OBJSerializer::isValidTexture(const QByteArray &filename) { bool OBJSerializer::isValidTexture(const hifi::ByteArray &filename) {
if (_url.isEmpty()) { if (_url.isEmpty()) {
return false; return false;
} }
QUrl candidateUrl = _url.resolved(QUrl(filename)); hifi::URL candidateUrl = _url.resolved(hifi::URL(filename));
return DependencyManager::get<ResourceManager>()->resourceExists(candidateUrl); return DependencyManager::get<ResourceManager>()->resourceExists(candidateUrl);
} }
@ -278,7 +278,7 @@ void OBJSerializer::parseMaterialLibrary(QIODevice* device) {
#endif #endif
return; return;
} }
QByteArray token = tokenizer.getDatum(); hifi::ByteArray token = tokenizer.getDatum();
if (token == "newmtl") { if (token == "newmtl") {
if (tokenizer.nextToken() != OBJTokenizer::DATUM_TOKEN) { if (tokenizer.nextToken() != OBJTokenizer::DATUM_TOKEN) {
return; return;
@ -328,8 +328,8 @@ void OBJSerializer::parseMaterialLibrary(QIODevice* device) {
} else if (token == "Ks") { } else if (token == "Ks") {
currentMaterial.specularColor = tokenizer.getVec3(); currentMaterial.specularColor = tokenizer.getVec3();
} else if ((token == "map_Kd") || (token == "map_Ke") || (token == "map_Ks") || (token == "map_bump") || (token == "bump") || (token == "map_d")) { } else if ((token == "map_Kd") || (token == "map_Ke") || (token == "map_Ks") || (token == "map_bump") || (token == "bump") || (token == "map_d")) {
const QByteArray textureLine = tokenizer.getLineAsDatum(); const hifi::ByteArray textureLine = tokenizer.getLineAsDatum();
QByteArray filename; hifi::ByteArray filename;
OBJMaterialTextureOptions textureOptions; OBJMaterialTextureOptions textureOptions;
parseTextureLine(textureLine, filename, textureOptions); parseTextureLine(textureLine, filename, textureOptions);
if (filename.endsWith(".tga")) { if (filename.endsWith(".tga")) {
@ -354,7 +354,7 @@ void OBJSerializer::parseMaterialLibrary(QIODevice* device) {
} }
} }
void OBJSerializer::parseTextureLine(const QByteArray& textureLine, QByteArray& filename, OBJMaterialTextureOptions& textureOptions) { void OBJSerializer::parseTextureLine(const hifi::ByteArray& textureLine, hifi::ByteArray& filename, OBJMaterialTextureOptions& textureOptions) {
// Texture options reference http://paulbourke.net/dataformats/mtl/ // Texture options reference http://paulbourke.net/dataformats/mtl/
// and https://wikivisually.com/wiki/Material_Template_Library // and https://wikivisually.com/wiki/Material_Template_Library
@ -442,12 +442,12 @@ void OBJSerializer::parseTextureLine(const QByteArray& textureLine, QByteArray&
} }
} }
std::tuple<bool, QByteArray> requestData(QUrl& url) { std::tuple<bool, hifi::ByteArray> requestData(hifi::URL& url) {
auto request = DependencyManager::get<ResourceManager>()->createResourceRequest( auto request = DependencyManager::get<ResourceManager>()->createResourceRequest(
nullptr, url, true, -1, "(OBJSerializer) requestData"); nullptr, url, true, -1, "(OBJSerializer) requestData");
if (!request) { if (!request) {
return std::make_tuple(false, QByteArray()); return std::make_tuple(false, hifi::ByteArray());
} }
QEventLoop loop; QEventLoop loop;
@ -458,12 +458,12 @@ std::tuple<bool, QByteArray> requestData(QUrl& url) {
if (request->getResult() == ResourceRequest::Success) { if (request->getResult() == ResourceRequest::Success) {
return std::make_tuple(true, request->getData()); return std::make_tuple(true, request->getData());
} else { } else {
return std::make_tuple(false, QByteArray()); return std::make_tuple(false, hifi::ByteArray());
} }
} }
QNetworkReply* request(QUrl& url, bool isTest) { QNetworkReply* request(hifi::URL& url, bool isTest) {
if (!qApp) { if (!qApp) {
return nullptr; return nullptr;
} }
@ -488,7 +488,7 @@ QNetworkReply* request(QUrl& url, bool isTest) {
} }
bool OBJSerializer::parseOBJGroup(OBJTokenizer& tokenizer, const QVariantHash& mapping, HFMModel& hfmModel, bool OBJSerializer::parseOBJGroup(OBJTokenizer& tokenizer, const hifi::VariantHash& mapping, HFMModel& hfmModel,
float& scaleGuess, bool combineParts) { float& scaleGuess, bool combineParts) {
FaceGroup faces; FaceGroup faces;
HFMMesh& mesh = hfmModel.meshes[0]; HFMMesh& mesh = hfmModel.meshes[0];
@ -522,7 +522,7 @@ bool OBJSerializer::parseOBJGroup(OBJTokenizer& tokenizer, const QVariantHash& m
result = false; result = false;
break; break;
} }
QByteArray token = tokenizer.getDatum(); hifi::ByteArray token = tokenizer.getDatum();
//qCDebug(modelformat) << token; //qCDebug(modelformat) << token;
// we don't support separate objects in the same file, so treat "o" the same as "g". // we don't support separate objects in the same file, so treat "o" the same as "g".
if (token == "g" || token == "o") { if (token == "g" || token == "o") {
@ -535,7 +535,7 @@ bool OBJSerializer::parseOBJGroup(OBJTokenizer& tokenizer, const QVariantHash& m
if (tokenizer.nextToken() != OBJTokenizer::DATUM_TOKEN) { if (tokenizer.nextToken() != OBJTokenizer::DATUM_TOKEN) {
break; break;
} }
QByteArray groupName = tokenizer.getDatum(); hifi::ByteArray groupName = tokenizer.getDatum();
currentGroup = groupName; currentGroup = groupName;
if (!combineParts) { if (!combineParts) {
currentMaterialName = QString("part-") + QString::number(_partCounter++); currentMaterialName = QString("part-") + QString::number(_partCounter++);
@ -544,7 +544,7 @@ bool OBJSerializer::parseOBJGroup(OBJTokenizer& tokenizer, const QVariantHash& m
if (tokenizer.nextToken(true) != OBJTokenizer::DATUM_TOKEN) { if (tokenizer.nextToken(true) != OBJTokenizer::DATUM_TOKEN) {
break; break;
} }
QByteArray libraryName = tokenizer.getDatum(); hifi::ByteArray libraryName = tokenizer.getDatum();
librariesSeen[libraryName] = true; librariesSeen[libraryName] = true;
// We'll read it later only if we actually need it. // We'll read it later only if we actually need it.
} else if (token == "usemtl") { } else if (token == "usemtl") {
@ -598,14 +598,14 @@ bool OBJSerializer::parseOBJGroup(OBJTokenizer& tokenizer, const QVariantHash& m
// vertex-index // vertex-index
// vertex-index/texture-index // vertex-index/texture-index
// vertex-index/texture-index/surface-normal-index // vertex-index/texture-index/surface-normal-index
QByteArray token = tokenizer.getDatum(); hifi::ByteArray token = tokenizer.getDatum();
auto firstChar = token[0]; auto firstChar = token[0];
// Tokenizer treats line endings as whitespace. Non-digit and non-negative sign indicates done; // Tokenizer treats line endings as whitespace. Non-digit and non-negative sign indicates done;
if (!isdigit(firstChar) && firstChar != '-') { if (!isdigit(firstChar) && firstChar != '-') {
tokenizer.pushBackToken(OBJTokenizer::DATUM_TOKEN); tokenizer.pushBackToken(OBJTokenizer::DATUM_TOKEN);
break; break;
} }
QList<QByteArray> parts = token.split('/'); QList<hifi::ByteArray> parts = token.split('/');
assert(parts.count() >= 1); assert(parts.count() >= 1);
assert(parts.count() <= 3); assert(parts.count() <= 3);
// If indices are negative relative indices then adjust them to absolute indices based on current vector sizes // If indices are negative relative indices then adjust them to absolute indices based on current vector sizes
@ -626,7 +626,7 @@ bool OBJSerializer::parseOBJGroup(OBJTokenizer& tokenizer, const QVariantHash& m
} }
} }
} }
const QByteArray noData {}; const hifi::ByteArray noData {};
face.add(parts[0], (parts.count() > 1) ? parts[1] : noData, (parts.count() > 2) ? parts[2] : noData, face.add(parts[0], (parts.count() > 1) ? parts[1] : noData, (parts.count() > 2) ? parts[2] : noData,
vertices, vertexColors); vertices, vertexColors);
face.groupName = currentGroup; face.groupName = currentGroup;
@ -661,9 +661,9 @@ std::unique_ptr<hfm::Serializer::Factory> OBJSerializer::getFactory() const {
return std::make_unique<hfm::Serializer::SimpleFactory<OBJSerializer>>(); return std::make_unique<hfm::Serializer::SimpleFactory<OBJSerializer>>();
} }
HFMModel::Pointer OBJSerializer::read(const QByteArray& data, const QVariantHash& mapping, const QUrl& url) { HFMModel::Pointer OBJSerializer::read(const hifi::ByteArray& data, const hifi::VariantHash& mapping, const hifi::URL& url) {
PROFILE_RANGE_EX(resource_parse, __FUNCTION__, 0xffff0000, nullptr); PROFILE_RANGE_EX(resource_parse, __FUNCTION__, 0xffff0000, nullptr);
QBuffer buffer { const_cast<QByteArray*>(&data) }; QBuffer buffer { const_cast<hifi::ByteArray*>(&data) };
buffer.open(QIODevice::ReadOnly); buffer.open(QIODevice::ReadOnly);
auto hfmModelPtr = std::make_shared<HFMModel>(); auto hfmModelPtr = std::make_shared<HFMModel>();
@ -849,11 +849,11 @@ HFMModel::Pointer OBJSerializer::read(const QByteArray& data, const QVariantHash
int extIndex = filename.lastIndexOf('.'); // by construction, this does not fail int extIndex = filename.lastIndexOf('.'); // by construction, this does not fail
QString basename = filename.remove(extIndex + 1, sizeof("obj")); QString basename = filename.remove(extIndex + 1, sizeof("obj"));
preDefinedMaterial.diffuseColor = glm::vec3(1.0f); preDefinedMaterial.diffuseColor = glm::vec3(1.0f);
QVector<QByteArray> extensions = { "jpg", "jpeg", "png", "tga" }; QVector<hifi::ByteArray> extensions = { "jpg", "jpeg", "png", "tga" };
QByteArray base = basename.toUtf8(), textName = ""; hifi::ByteArray base = basename.toUtf8(), textName = "";
qCDebug(modelformat) << "OBJSerializer looking for default texture"; qCDebug(modelformat) << "OBJSerializer looking for default texture";
for (int i = 0; i < extensions.count(); i++) { for (int i = 0; i < extensions.count(); i++) {
QByteArray candidateString = base + extensions[i]; hifi::ByteArray candidateString = base + extensions[i];
if (isValidTexture(candidateString)) { if (isValidTexture(candidateString)) {
textName = candidateString; textName = candidateString;
break; break;
@ -871,11 +871,11 @@ HFMModel::Pointer OBJSerializer::read(const QByteArray& data, const QVariantHash
if (needsMaterialLibrary) { if (needsMaterialLibrary) {
foreach (QString libraryName, librariesSeen.keys()) { foreach (QString libraryName, librariesSeen.keys()) {
// Throw away any path part of libraryName, and merge against original url. // Throw away any path part of libraryName, and merge against original url.
QUrl libraryUrl = _url.resolved(QUrl(libraryName).fileName()); hifi::URL libraryUrl = _url.resolved(hifi::URL(libraryName).fileName());
qCDebug(modelformat) << "OBJSerializer material library" << libraryName; qCDebug(modelformat) << "OBJSerializer material library" << libraryName;
bool success; bool success;
QByteArray data; hifi::ByteArray data;
std::tie<bool, QByteArray>(success, data) = requestData(libraryUrl); std::tie<bool, hifi::ByteArray>(success, data) = requestData(libraryUrl);
if (success) { if (success) {
QBuffer buffer { &data }; QBuffer buffer { &data };
buffer.open(QIODevice::ReadOnly); buffer.open(QIODevice::ReadOnly);

View file

@ -25,9 +25,9 @@ public:
COMMENT_TOKEN = 0x101 COMMENT_TOKEN = 0x101
}; };
int nextToken(bool allowSpaceChar = false); int nextToken(bool allowSpaceChar = false);
const QByteArray& getDatum() const { return _datum; } const hifi::ByteArray& getDatum() const { return _datum; }
bool isNextTokenFloat(); bool isNextTokenFloat();
const QByteArray getLineAsDatum(); // some "filenames" have spaces in them const hifi::ByteArray getLineAsDatum(); // some "filenames" have spaces in them
void skipLine() { _device->readLine(); } void skipLine() { _device->readLine(); }
void pushBackToken(int token) { _pushedBackToken = token; } void pushBackToken(int token) { _pushedBackToken = token; }
void ungetChar(char ch) { _device->ungetChar(ch); } void ungetChar(char ch) { _device->ungetChar(ch); }
@ -39,7 +39,7 @@ public:
private: private:
QIODevice* _device; QIODevice* _device;
QByteArray _datum; hifi::ByteArray _datum;
int _pushedBackToken; int _pushedBackToken;
QString _comment; QString _comment;
}; };
@ -52,7 +52,7 @@ public:
QString groupName; // We don't make use of hierarchical structure, but it can be preserved for debugging and future use. QString groupName; // We don't make use of hierarchical structure, but it can be preserved for debugging and future use.
QString materialName; QString materialName;
// Add one more set of vertex data. Answers true if successful // Add one more set of vertex data. Answers true if successful
bool add(const QByteArray& vertexIndex, const QByteArray& textureIndex, const QByteArray& normalIndex, bool add(const hifi::ByteArray& vertexIndex, const hifi::ByteArray& textureIndex, const hifi::ByteArray& normalIndex,
const QVector<glm::vec3>& vertices, const QVector<glm::vec3>& vertexColors); const QVector<glm::vec3>& vertices, const QVector<glm::vec3>& vertexColors);
// Return a set of one or more OBJFaces from this one, in which each is just a triangle. // Return a set of one or more OBJFaces from this one, in which each is just a triangle.
// Even though HFMMeshPart can handle quads, it would be messy to try to keep track of mixed-size faces, so we treat everything as triangles. // Even though HFMMeshPart can handle quads, it would be messy to try to keep track of mixed-size faces, so we treat everything as triangles.
@ -75,11 +75,11 @@ public:
glm::vec3 diffuseColor; glm::vec3 diffuseColor;
glm::vec3 specularColor; glm::vec3 specularColor;
glm::vec3 emissiveColor; glm::vec3 emissiveColor;
QByteArray diffuseTextureFilename; hifi::ByteArray diffuseTextureFilename;
QByteArray specularTextureFilename; hifi::ByteArray specularTextureFilename;
QByteArray emissiveTextureFilename; hifi::ByteArray emissiveTextureFilename;
QByteArray bumpTextureFilename; hifi::ByteArray bumpTextureFilename;
QByteArray opacityTextureFilename; hifi::ByteArray opacityTextureFilename;
OBJMaterialTextureOptions bumpTextureOptions; OBJMaterialTextureOptions bumpTextureOptions;
int illuminationModel; int illuminationModel;
@ -103,17 +103,17 @@ public:
QString currentMaterialName; QString currentMaterialName;
QHash<QString, OBJMaterial> materials; QHash<QString, OBJMaterial> materials;
HFMModel::Pointer read(const QByteArray& data, const QVariantHash& mapping, const QUrl& url = QUrl()) override; HFMModel::Pointer read(const hifi::ByteArray& data, const hifi::VariantHash& mapping, const hifi::URL& url = hifi::URL()) override;
private: private:
QUrl _url; hifi::URL _url;
QHash<QByteArray, bool> librariesSeen; QHash<hifi::ByteArray, bool> librariesSeen;
bool parseOBJGroup(OBJTokenizer& tokenizer, const QVariantHash& mapping, HFMModel& hfmModel, bool parseOBJGroup(OBJTokenizer& tokenizer, const hifi::VariantHash& mapping, HFMModel& hfmModel,
float& scaleGuess, bool combineParts); float& scaleGuess, bool combineParts);
void parseMaterialLibrary(QIODevice* device); void parseMaterialLibrary(QIODevice* device);
void parseTextureLine(const QByteArray& textureLine, QByteArray& filename, OBJMaterialTextureOptions& textureOptions); void parseTextureLine(const hifi::ByteArray& textureLine, hifi::ByteArray& filename, OBJMaterialTextureOptions& textureOptions);
bool isValidTexture(const QByteArray &filename); // true if the file exists. TODO?: check content-type header and that it is a supported format. bool isValidTexture(const hifi::ByteArray &filename); // true if the file exists. TODO?: check content-type header and that it is a supported format.
int _partCounter { 0 }; int _partCounter { 0 };
}; };