From b7009b46318404484e6b8479a8167ee84f90eadf Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Fri, 21 Aug 2015 16:09:06 -0700 Subject: [PATCH 1/3] Fix for animation resources The problem was that the invokeMethod between the AnimationReader thread and the main thread was failing, because FBXGeometry* wasn't a registered meta type. So, I ended up normalizing the AnimationReader class to be more like GeometryReader, in that it uses singles and slots to communicate success and failure, rather then invokeMethod. --- examples/libraries/progressDialog.js | 4 +- libraries/animation/src/AnimationCache.cpp | 71 +++++++++++++-------- libraries/animation/src/AnimationCache.h | 24 ++++++- libraries/animation/src/AnimationHandle.cpp | 1 + libraries/fbx/src/FBXReader.cpp | 8 ++- libraries/render-utils/src/GeometryCache.h | 9 --- 6 files changed, 77 insertions(+), 40 deletions(-) diff --git a/examples/libraries/progressDialog.js b/examples/libraries/progressDialog.js index 7d3b1f88e2..4cb2644004 100644 --- a/examples/libraries/progressDialog.js +++ b/examples/libraries/progressDialog.js @@ -8,6 +8,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +var HIFI_PUBLIC_BUCKET = "http://s3.amazonaws.com/hifi-public/"; +var toolIconUrl = HIFI_PUBLIC_BUCKET + "images/tools/"; progressDialog = (function () { var that = {}, @@ -142,4 +144,4 @@ progressDialog = (function () { that.cleanup = cleanup; return that; -}()); \ No newline at end of file +}()); diff --git a/libraries/animation/src/AnimationCache.cpp b/libraries/animation/src/AnimationCache.cpp index 7f3f393a8b..c9514782ee 100644 --- a/libraries/animation/src/AnimationCache.cpp +++ b/libraries/animation/src/AnimationCache.cpp @@ -39,35 +39,44 @@ QSharedPointer AnimationCache::createResource(const QUrl& url, const Q return QSharedPointer(new Animation(url), &Resource::allReferencesCleared); } -Animation::Animation(const QUrl& url) : Resource(url) {} - -class AnimationReader : public QRunnable { -public: - - AnimationReader(const QWeakPointer& animation, QNetworkReply* reply); - - virtual void run(); - -private: - - QWeakPointer _animation; - QNetworkReply* _reply; -}; - -AnimationReader::AnimationReader(const QWeakPointer& animation, QNetworkReply* reply) : - _animation(animation), +AnimationReader::AnimationReader(const QUrl& url, QNetworkReply* reply) : + _url(url), _reply(reply) { } void AnimationReader::run() { - QSharedPointer animation = _animation.toStrongRef(); - if (!animation.isNull()) { - QMetaObject::invokeMethod(animation.data(), "setGeometry", - Q_ARG(FBXGeometry*, readFBX(_reply->readAll(), QVariantHash(), _reply->property("url").toString()))); + try { + if (!_reply) { + throw QString("Reply is NULL ?!"); + } + QString urlname = _url.path().toLower(); + bool urlValid = true; + urlValid &= !urlname.isEmpty(); + urlValid &= !_url.path().isEmpty(); + urlValid &= _url.path().toLower().endsWith(".fbx"); + + if (urlValid) { + // Let's read the binaries from the network + FBXGeometry* fbxgeo = nullptr; + if (_url.path().toLower().endsWith(".fbx")) { + fbxgeo = readFBX(_reply, QVariantHash(), _url.path()); + } else { + QString errorStr("usupported format"); + emit onError(299, errorStr); + } + emit onSuccess(fbxgeo); + } else { + throw QString("url is invalid"); + } + + } catch (const QString& error) { + emit onError(299, error); } _reply->deleteLater(); } +Animation::Animation(const QUrl& url) : Resource(url) {} + bool Animation::isLoaded() const { return _loaded && _geometry; } @@ -100,17 +109,27 @@ const QVector& Animation::getFramesReference() const { return _geometry->animationFrames; } -void Animation::setGeometry(FBXGeometry* geometry) { +void Animation::downloadFinished(QNetworkReply* reply) { + // parse the animation/fbx file on a background thread. + AnimationReader* animationReader = new AnimationReader(reply->url(), reply); + connect(animationReader, SIGNAL(onSuccess(FBXGeometry*)), SLOT(animationParseSuccess(FBXGeometry*))); + connect(animationReader, SIGNAL(onError(int, QString)), SLOT(animationParseError(int, QString))); + QThreadPool::globalInstance()->start(animationReader); +} + +void Animation::animationParseSuccess(FBXGeometry* geometry) { + + qCDebug(animation) << "Animation parse success" << _url.toDisplayString(); + _geometry.reset(geometry); finishedLoading(true); } -void Animation::downloadFinished(QNetworkReply* reply) { - // send the reader off to the thread pool - QThreadPool::globalInstance()->start(new AnimationReader(_self, reply)); +void Animation::animationParseError(int error, QString str) { + qCCritical(animation) << "Animation failure parsing " << _url.toDisplayString() << "code =" << error << str; + emit failed(QNetworkReply::UnknownContentError); } - AnimationDetails::AnimationDetails() : role(), url(), fps(0.0f), priority(0.0f), loop(false), hold(false), startAutomatically(false), firstFrame(0.0f), lastFrame(0.0f), running(false), frameIndex(0.0f) diff --git a/libraries/animation/src/AnimationCache.h b/libraries/animation/src/AnimationCache.h index 3ff5957fa2..af07eda9a4 100644 --- a/libraries/animation/src/AnimationCache.h +++ b/libraries/animation/src/AnimationCache.h @@ -12,6 +12,7 @@ #ifndef hifi_AnimationCache_h #define hifi_AnimationCache_h +#include #include #include @@ -64,16 +65,33 @@ public: const QVector& getFramesReference() const; protected: - - Q_INVOKABLE void setGeometry(FBXGeometry* geometry); - virtual void downloadFinished(QNetworkReply* reply); +protected slots: + void animationParseSuccess(FBXGeometry* geometry); + void animationParseError(int error, QString str); + private: std::unique_ptr _geometry; }; +/// Reads geometry in a worker thread. +class AnimationReader : public QObject, public QRunnable { + Q_OBJECT + +public: + AnimationReader(const QUrl& url, QNetworkReply* reply); + virtual void run(); + +signals: + void onSuccess(FBXGeometry* geometry); + void onError(int error, QString str); + +private: + QUrl _url; + QNetworkReply* _reply; +}; class AnimationDetails { public: diff --git a/libraries/animation/src/AnimationHandle.cpp b/libraries/animation/src/AnimationHandle.cpp index ebf0e29b97..1f4c886a06 100644 --- a/libraries/animation/src/AnimationHandle.cpp +++ b/libraries/animation/src/AnimationHandle.cpp @@ -15,6 +15,7 @@ void AnimationHandle::setURL(const QUrl& url) { if (_url != url) { _animation = DependencyManager::get()->getAnimation(_url = url); + _animation->ensureLoading(); QObject::connect(_animation.data(), &Resource::onRefresh, this, &AnimationHandle::clearJoints); _jointMappings.clear(); } diff --git a/libraries/fbx/src/FBXReader.cpp b/libraries/fbx/src/FBXReader.cpp index f0d13f8792..320b93ff06 100644 --- a/libraries/fbx/src/FBXReader.cpp +++ b/libraries/fbx/src/FBXReader.cpp @@ -182,7 +182,7 @@ QString FBXGeometry::getModelNameOfMesh(int meshIndex) const { static int fbxGeometryMetaTypeId = qRegisterMetaType(); static int fbxAnimationFrameMetaTypeId = qRegisterMetaType(); -static int fbxAnimationFrameVectorMetaTypeId = qRegisterMetaType >(); +static int fbxAnimationFrameVectorMetaTypeId = qRegisterMetaType>(); template int streamSize() { return sizeof(T); @@ -1858,12 +1858,18 @@ FBXGeometry* extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping foreach (const FBXNode& subobject, object.children) { if (subobject.name == "RelativeFilename") { QByteArray filename = subobject.properties.at(0).toByteArray(); + qCDebug(modelformat) << "AJT: RelativeFilename, filename =" << filename; filename = fileOnUrl(filename, url); + qCDebug(modelformat) << "AJT: url = " << url; + qCDebug(modelformat) << "AJT: filename2 = " << filename; + textureFilenames.insert(getID(object.properties), filename); } else if (subobject.name == "TextureName") { // trim the name from the timestamp QString name = QString(subobject.properties.at(0).toByteArray()); + qCDebug(modelformat) << "AJT: TextureName, name =" << name; name = name.left(name.indexOf('[')); + qCDebug(modelformat) << "AJT: name2 =" << name; textureNames.insert(getID(object.properties), name); } else if (subobject.name == "Texture_Alpha_Source") { tex.assign(tex.alphaSource, subobject.properties.at(0).value()); diff --git a/libraries/render-utils/src/GeometryCache.h b/libraries/render-utils/src/GeometryCache.h index 774df1561c..0b692d81f7 100644 --- a/libraries/render-utils/src/GeometryCache.h +++ b/libraries/render-utils/src/GeometryCache.h @@ -21,8 +21,6 @@ #include "FBXReader.h" #include "OBJReader.h" -#include - #include #include @@ -383,20 +381,13 @@ protected: /// Reads geometry in a worker thread. class GeometryReader : public QObject, public QRunnable { Q_OBJECT - public: - GeometryReader(const QUrl& url, QNetworkReply* reply, const QVariantHash& mapping); - virtual void run(); - signals: void onSuccess(FBXGeometry* geometry); void onError(int error, QString str); - private: - - QWeakPointer _geometry; QUrl _url; QNetworkReply* _reply; QVariantHash _mapping; From 5e31d423b9a563c559c32c15423f7165ae83c4e9 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Fri, 21 Aug 2015 16:55:08 -0700 Subject: [PATCH 2/3] Removed some debugging statements --- libraries/fbx/src/FBXReader.cpp | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/libraries/fbx/src/FBXReader.cpp b/libraries/fbx/src/FBXReader.cpp index 320b93ff06..f0d13f8792 100644 --- a/libraries/fbx/src/FBXReader.cpp +++ b/libraries/fbx/src/FBXReader.cpp @@ -182,7 +182,7 @@ QString FBXGeometry::getModelNameOfMesh(int meshIndex) const { static int fbxGeometryMetaTypeId = qRegisterMetaType(); static int fbxAnimationFrameMetaTypeId = qRegisterMetaType(); -static int fbxAnimationFrameVectorMetaTypeId = qRegisterMetaType>(); +static int fbxAnimationFrameVectorMetaTypeId = qRegisterMetaType >(); template int streamSize() { return sizeof(T); @@ -1858,18 +1858,12 @@ FBXGeometry* extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping foreach (const FBXNode& subobject, object.children) { if (subobject.name == "RelativeFilename") { QByteArray filename = subobject.properties.at(0).toByteArray(); - qCDebug(modelformat) << "AJT: RelativeFilename, filename =" << filename; filename = fileOnUrl(filename, url); - qCDebug(modelformat) << "AJT: url = " << url; - qCDebug(modelformat) << "AJT: filename2 = " << filename; - textureFilenames.insert(getID(object.properties), filename); } else if (subobject.name == "TextureName") { // trim the name from the timestamp QString name = QString(subobject.properties.at(0).toByteArray()); - qCDebug(modelformat) << "AJT: TextureName, name =" << name; name = name.left(name.indexOf('[')); - qCDebug(modelformat) << "AJT: name2 =" << name; textureNames.insert(getID(object.properties), name); } else if (subobject.name == "Texture_Alpha_Source") { tex.assign(tex.alphaSource, subobject.properties.at(0).value()); From 80d3ae68c23c99fbd6b1922a8463343716040a93 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Fri, 21 Aug 2015 22:11:53 -0700 Subject: [PATCH 3/3] =?UTF-8?q?Removed=20redundant=20ends=20with=20?= =?UTF-8?q?=E2=80=98fbx=E2=80=99=20check.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- libraries/animation/src/AnimationCache.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libraries/animation/src/AnimationCache.cpp b/libraries/animation/src/AnimationCache.cpp index c9514782ee..e7a4fb50a3 100644 --- a/libraries/animation/src/AnimationCache.cpp +++ b/libraries/animation/src/AnimationCache.cpp @@ -53,10 +53,9 @@ void AnimationReader::run() { bool urlValid = true; urlValid &= !urlname.isEmpty(); urlValid &= !_url.path().isEmpty(); - urlValid &= _url.path().toLower().endsWith(".fbx"); if (urlValid) { - // Let's read the binaries from the network + // Parse the FBX directly from the QNetworkReply FBXGeometry* fbxgeo = nullptr; if (_url.path().toLower().endsWith(".fbx")) { fbxgeo = readFBX(_reply, QVariantHash(), _url.path());