diff --git a/libraries/model-networking/src/model-networking/ModelCache.cpp b/libraries/model-networking/src/model-networking/ModelCache.cpp index 53a0ec14a1..81188031e1 100644 --- a/libraries/model-networking/src/model-networking/ModelCache.cpp +++ b/libraries/model-networking/src/model-networking/ModelCache.cpp @@ -144,9 +144,9 @@ void GeometryMappingResource::onGeometryMappingLoaded(bool success) { class GeometryReader : public QRunnable { public: - GeometryReader(QWeakPointer& resource, const QUrl& url, const QVariantHash& mapping, - const QByteArray& data, bool combineParts) : - _resource(resource), _url(url), _mapping(mapping), _data(data), _combineParts(combineParts) { + GeometryReader(const ModelLoader& modelLoader, QWeakPointer& resource, const QUrl& url, const QVariantHash& mapping, + const QByteArray& data, bool combineParts, const QString& webMediaType) : + _modelLoader(modelLoader), _resource(resource), _url(url), _mapping(mapping), _data(data), _combineParts(combineParts), _webMediaType(webMediaType) { DependencyManager::get()->incrementStat("PendingProcessing"); } @@ -154,11 +154,13 @@ public: virtual void run() override; private: + ModelLoader _modelLoader; QWeakPointer _resource; QUrl _url; QVariantHash _mapping; QByteArray _data; bool _combineParts; + QString _webMediaType; }; void GeometryReader::run() { @@ -183,62 +185,54 @@ void GeometryReader::run() { throw QString("reply is NULL"); } + // Ensure the resource has not been deleted + auto resource = _resource.toStrongRef(); + if (!resource) { + qCWarning(modelnetworking) << "Abandoning load of" << _url << "; could not get strong ref"; + return; + } + QString urlname = _url.path().toLower(); - if (!urlname.isEmpty() && !_url.path().isEmpty() && - - (_url.path().toLower().endsWith(".fbx") || - _url.path().toLower().endsWith(".obj") || - _url.path().toLower().endsWith(".obj.gz") || - _url.path().toLower().endsWith(".gltf"))) { - - HFMModel::Pointer hfmModel; - - QVariantHash serializerMapping = _mapping; - serializerMapping["combineParts"] = _combineParts; - - if (_url.path().toLower().endsWith(".fbx")) { - hfmModel = FBXSerializer().read(_data, serializerMapping, _url); - if (hfmModel->meshes.size() == 0 && hfmModel->joints.size() == 0) { - throw QString("empty geometry, possibly due to an unsupported FBX version"); - } - } else if (_url.path().toLower().endsWith(".obj")) { - hfmModel = OBJSerializer().read(_data, serializerMapping, _url); - } else if (_url.path().toLower().endsWith(".obj.gz")) { - QByteArray uncompressedData; - if (gunzip(_data, uncompressedData)){ - hfmModel = OBJSerializer().read(uncompressedData, serializerMapping, _url); - } else { - throw QString("failed to decompress .obj.gz"); - } - - } else if (_url.path().toLower().endsWith(".gltf")) { - hfmModel = GLTFSerializer().read(_data, serializerMapping, _url); - if (hfmModel->meshes.size() == 0 && hfmModel->joints.size() == 0) { - throw QString("empty geometry, possibly due to an unsupported GLTF version"); - } - } else { - throw QString("unsupported format"); - } - - // Add scripts to hfmModel - if (!_mapping.value(SCRIPT_FIELD).isNull()) { - QVariantList scripts = _mapping.values(SCRIPT_FIELD); - for (auto &script : scripts) { - hfmModel->scripts.push_back(script.toString()); - } - } - - // Ensure the resource has not been deleted - auto resource = _resource.toStrongRef(); - if (!resource) { - qCWarning(modelnetworking) << "Abandoning load of" << _url << "; could not get strong ref"; - } else { - QMetaObject::invokeMethod(resource.data(), "setGeometryDefinition", - Q_ARG(HFMModel::Pointer, hfmModel)); - } - } else { + if (urlname.isEmpty() || _url.path().isEmpty()) { throw QString("url is invalid"); } + + HFMModel::Pointer hfmModel; + QVariantHash serializerMapping = _mapping; + serializerMapping["combineParts"] = _combineParts; + + if (_url.path().toLower().endsWith(".gz")) { + QByteArray uncompressedData; + if (!gunzip(_data, uncompressedData)) { + throw QString("failed to decompress .gz model"); + } + // Strip the compression extension from the path, so the loader can infer the file type from what remains. + // This is okay because we don't expect the serializer to be able to read the contents of a compressed model file. + auto strippedUrl = _url; + strippedUrl.setPath(_url.path().left(_url.path().size() - 3)); + hfmModel = _modelLoader.load(uncompressedData, serializerMapping, strippedUrl, ""); + } else { + hfmModel = _modelLoader.load(_data, serializerMapping, _url, _webMediaType.toStdString()); + } + + if (!hfmModel) { + throw QString("unsupported format"); + } + + if (hfmModel->meshes.size() == 0 && hfmModel->joints.size() == 0) { + throw QString("empty geometry, possibly due to an unsupported model version"); + } + + // Add scripts to hfmModel + if (!_mapping.value(SCRIPT_FIELD).isNull()) { + QVariantList scripts = _mapping.values(SCRIPT_FIELD); + for (auto &script : scripts) { + hfmModel->scripts.push_back(script.toString()); + } + } + + QMetaObject::invokeMethod(resource.data(), "setGeometryDefinition", + Q_ARG(HFMModel::Pointer, hfmModel)); } catch (const std::exception&) { auto resource = _resource.toStrongRef(); if (resource) { @@ -258,8 +252,8 @@ void GeometryReader::run() { class GeometryDefinitionResource : public GeometryResource { Q_OBJECT public: - GeometryDefinitionResource(const QUrl& url, const QVariantHash& mapping, const QUrl& textureBaseUrl, bool combineParts) : - GeometryResource(url, resolveTextureBaseUrl(url, textureBaseUrl)), _mapping(mapping), _combineParts(combineParts) {} + GeometryDefinitionResource(const ModelLoader& modelLoader, const QUrl& url, const QVariantHash& mapping, const QUrl& textureBaseUrl, bool combineParts) : + GeometryResource(url, resolveTextureBaseUrl(url, textureBaseUrl)), _modelLoader(modelLoader), _mapping(mapping), _combineParts(combineParts) {} QString getType() const override { return "GeometryDefinition"; } @@ -269,6 +263,7 @@ protected: Q_INVOKABLE void setGeometryDefinition(HFMModel::Pointer hfmModel); private: + ModelLoader _modelLoader; QVariantHash _mapping; bool _combineParts; }; @@ -278,7 +273,7 @@ void GeometryDefinitionResource::downloadFinished(const QByteArray& data) { _url = _effectiveBaseURL; _textureBaseUrl = _effectiveBaseURL; } - QThreadPool::globalInstance()->start(new GeometryReader(_self, _effectiveBaseURL, _mapping, data, _combineParts)); + QThreadPool::globalInstance()->start(new GeometryReader(_modelLoader, _self, _effectiveBaseURL, _mapping, data, _combineParts, _request->getWebMediaType())); } void GeometryDefinitionResource::setGeometryDefinition(HFMModel::Pointer hfmModel) { @@ -344,7 +339,7 @@ QSharedPointer ModelCache::createResource(const QUrl& url, const QShar auto mapping = geometryExtra ? geometryExtra->mapping : QVariantHash(); auto textureBaseUrl = geometryExtra ? geometryExtra->textureBaseUrl : QUrl(); bool combineParts = geometryExtra ? geometryExtra->combineParts : true; - resource = new GeometryDefinitionResource(url, mapping, textureBaseUrl, combineParts); + resource = new GeometryDefinitionResource(_modelLoader, url, mapping, textureBaseUrl, combineParts); } return QSharedPointer(resource, &Resource::deleter);