Add support for atp and file urls in OBJReader

This commit is contained in:
Ryan Huffman 2017-05-01 13:21:52 -07:00
parent a057400a92
commit 074a11306c
5 changed files with 167 additions and 158 deletions

View file

@ -24,6 +24,7 @@
#include <shared/NsightHelpers.h>
#include <NetworkAccessManager.h>
#include <ResourceManager.h>
#include "FBXReader.h"
#include "ModelFormatLogging.h"
@ -165,6 +166,7 @@ bool OBJFace::add(const QByteArray& vertexIndex, const QByteArray& textureIndex,
}
return true;
}
QVector<OBJFace> OBJFace::triangulate() {
QVector<OBJFace> newFaces;
const int nVerticesInATriangle = 3;
@ -183,6 +185,7 @@ QVector<OBJFace> OBJFace::triangulate() {
}
return newFaces;
}
void OBJFace::addFrom(const OBJFace* face, int index) { // add using data from f at index i
vertexIndices.append(face->vertexIndices[index]);
if (face->textureUVIndices.count() > 0) { // Any at all. Runtime error if not consistent.
@ -193,24 +196,13 @@ void OBJFace::addFrom(const OBJFace* face, int index) { // add using data from f
}
}
static bool replyOK(QNetworkReply* netReply, QUrl url) { // This will be reworked when we make things asynchronous
return (netReply && netReply->isFinished() &&
(url.toString().startsWith("file", Qt::CaseInsensitive) ? // file urls don't have http status codes
netReply->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toString().isEmpty() :
(netReply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt() == 200)));
}
bool OBJReader::isValidTexture(const QByteArray &filename) {
if (_url.isEmpty()) {
return false;
}
QUrl candidateUrl = _url.resolved(QUrl(filename));
QNetworkReply *netReply = request(candidateUrl, true);
bool isValid = replyOK(netReply, candidateUrl);
if (netReply) {
netReply->deleteLater();
}
return isValid;
return ResourceManager::resourceExists(candidateUrl);
}
void OBJReader::parseMaterialLibrary(QIODevice* device) {
@ -274,7 +266,28 @@ void OBJReader::parseMaterialLibrary(QIODevice* device) {
}
}
QNetworkReply* OBJReader::request(QUrl& url, bool isTest) {
std::tuple<bool, QByteArray> requestData(QUrl& url) {
auto request = ResourceManager::createResourceRequest(nullptr, url);
if (!request) {
return std::make_tuple(false, QByteArray());
}
request->send();
QEventLoop loop;
QObject::connect(request, &ResourceRequest::finished, &loop, &QEventLoop::quit);
loop.exec();
if (request->getResult() == ResourceRequest::Success) {
return std::make_tuple(true, request->getData());
} else {
return std::make_tuple(false, QByteArray());
}
}
QNetworkReply* request(QUrl& url, bool isTest) {
if (!qApp) {
return nullptr;
}
@ -293,10 +306,7 @@ QNetworkReply* OBJReader::request(QUrl& url, bool isTest) {
QEventLoop loop; // Create an event loop that will quit when we get the finished signal
QObject::connect(netReply, SIGNAL(finished()), &loop, SLOT(quit()));
loop.exec(); // Nothing is going to happen on this whole run thread until we get this
static const int WAIT_TIMEOUT_MS = 500;
while (!aboutToQuit && qApp && !netReply->isReadable()) {
netReply->waitForReadyRead(WAIT_TIMEOUT_MS); // so we might as well block this thread waiting for the response, rather than
}
QObject::disconnect(connection);
return netReply; // trying to sync later on.
}
@ -624,15 +634,15 @@ FBXGeometry* OBJReader::readOBJ(QByteArray& model, const QVariantHash& mapping,
// Throw away any path part of libraryName, and merge against original url.
QUrl libraryUrl = _url.resolved(QUrl(libraryName).fileName());
qCDebug(modelformat) << "OBJ Reader material library" << libraryName << "used in" << _url;
QNetworkReply* netReply = request(libraryUrl, false);
if (replyOK(netReply, libraryUrl)) {
parseMaterialLibrary(netReply);
bool success;
QByteArray data;
std::tie<bool, QByteArray>(success, data) = requestData(libraryUrl);
if (success) {
QBuffer buffer { &data };
buffer.open(QIODevice::ReadOnly);
parseMaterialLibrary(&buffer);
} else {
qCDebug(modelformat) << "OBJ Reader WARNING:" << libraryName << "did not answer. Got"
<< (!netReply ? "aborted" : netReply->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toString());
}
if (netReply) {
netReply->deleteLater();
qCDebug(modelformat) << "OBJ Reader WARNING:" << libraryName << "did not answer";
}
}
}

View file

@ -72,7 +72,6 @@ public:
QString currentMaterialName;
QHash<QString, OBJMaterial> materials;
QNetworkReply* request(QUrl& url, bool isTest);
FBXGeometry* readOBJ(QByteArray& model, const QVariantHash& mapping, bool combineParts, const QUrl& url = QUrl());
private:

View file

@ -40,16 +40,16 @@ AssetResourceRequest::~AssetResourceRequest() {
}
}
bool AssetResourceRequest::urlIsAssetHash() const {
bool AssetResourceRequest::urlIsAssetHash(const QUrl& url) {
static const QString ATP_HASH_REGEX_STRING { "^atp:([A-Fa-f0-9]{64})(\\.[\\w]+)?$" };
QRegExp hashRegex { ATP_HASH_REGEX_STRING };
return hashRegex.exactMatch(_url.toString());
return hashRegex.exactMatch(url.toString());
}
void AssetResourceRequest::doSend() {
// We'll either have a hash or an ATP path to a file (that maps to a hash)
if (urlIsAssetHash()) {
if (urlIsAssetHash(_url)) {
// We've detected that this is a hash - simply use AssetClient to request that asset
auto parts = _url.path().split(".", QString::SkipEmptyParts);
auto hash = parts.length() > 0 ? parts[0] : "";

View file

@ -32,7 +32,7 @@ private slots:
void onDownloadProgress(qint64 bytesReceived, qint64 bytesTotal);
private:
bool urlIsAssetHash() const;
static bool urlIsAssetHash(const QUrl& url);
void requestMappingForPath(const AssetPath& path);
void requestHash(const AssetHash& hash);

View file

@ -14,10 +14,10 @@
#include <QNetworkDiskCache>
#include <QStandardPaths>
#include <QThread>
#include <QFileInfo>
#include <SharedUtil.h>
#include "AssetResourceRequest.h"
#include "FileResourceRequest.h"
#include "HTTPResourceRequest.h"