summaryrefslogtreecommitdiffstats
path: root/src/plugins
diff options
context:
space:
mode:
authordpope <daniel.pope@nokia.com>2012-03-30 19:26:27 +1000
committerQt by Nokia <qt-info@nokia.com>2012-04-04 10:56:35 +0200
commitd3768a83cd473bb407f8b1c8e87ed36d1875e704 (patch)
treea573078c9e02ad82fdd02c0977c0e2c1830c7775 /src/plugins
parent749f3d9491b928a3ecd51a48565332c930b974ae (diff)
Network loading of textures and models.
Task-number: QTBUG-20054 Change-Id: I0624a815ad182bae7d812125e835426fb76f6b44 Reviewed-by: Sarah Jane Smith <sarah.j.smith@nokia.com>
Diffstat (limited to 'src/plugins')
-rw-r--r--src/plugins/sceneformats/assimp/ailoaderiosystem.cpp7
-rw-r--r--src/plugins/sceneformats/assimp/qailoader.h3
-rw-r--r--src/plugins/sceneformats/assimp/qaiscene.cpp75
-rw-r--r--src/plugins/sceneformats/assimp/qaiscene.h12
-rw-r--r--src/plugins/sceneformats/assimp/qaiscenehandler.cpp100
-rw-r--r--src/plugins/sceneformats/assimp/qaiscenehandler.h6
-rw-r--r--src/plugins/sceneformats/bezier/qglbezierscenehandler.cpp6
-rw-r--r--src/plugins/sceneformats/bezier/qglbezierscenehandler.h1
-rw-r--r--src/plugins/sceneformats/obj/qglobjscenehandler.cpp6
-rw-r--r--src/plugins/sceneformats/obj/qglobjscenehandler.h1
10 files changed, 208 insertions, 9 deletions
diff --git a/src/plugins/sceneformats/assimp/ailoaderiosystem.cpp b/src/plugins/sceneformats/assimp/ailoaderiosystem.cpp
index 661ccd8c1..50b00dcf6 100644
--- a/src/plugins/sceneformats/assimp/ailoaderiosystem.cpp
+++ b/src/plugins/sceneformats/assimp/ailoaderiosystem.cpp
@@ -60,7 +60,7 @@ AiLoaderIOSystem::~AiLoaderIOSystem()
bool AiLoaderIOSystem::Exists(const char* path) const
{
- return QFile::exists(QLatin1String(path));
+ return m_device->isReadable();
}
char AiLoaderIOSystem::getOsSeparator() const
@@ -87,7 +87,10 @@ Assimp::IOStream* AiLoaderIOSystem::Open(const char* pFile, const char* pMode)
// TODO: handle network case
if (url.scheme() != QLatin1String("file"))
{
- qWarning("Opening %s url not supported", qPrintable(url.scheme()));
+ //network cases should already be opened by this stage - they
+ //depend entirely on the download manager returning a QBuffer, so
+ //cannot be handled as the simple "open file" case shown below.
+ qWarning("Directly opening a network URL is not supported. Use scene handler code. (URL: %s).", qPrintable(url.scheme()));
return 0;
}
diff --git a/src/plugins/sceneformats/assimp/qailoader.h b/src/plugins/sceneformats/assimp/qailoader.h
index ad620d2a1..988ba224e 100644
--- a/src/plugins/sceneformats/assimp/qailoader.h
+++ b/src/plugins/sceneformats/assimp/qailoader.h
@@ -55,6 +55,7 @@ struct aiMaterial;
QT_BEGIN_NAMESPACE
class QAiMesh;
+class QAiScene;
class QGLSceneNode;
class QAiSceneHandler;
class QGLSceneAnimation;
@@ -69,6 +70,8 @@ public:
QList<QGLSceneAnimation *> loadAnimations();
private:
+ friend class QAiScene;
+
void loadMesh(aiMesh *);
void loadNodes(aiNode *, QGLSceneNode *);
void loadMaterial(aiMaterial *);
diff --git a/src/plugins/sceneformats/assimp/qaiscene.cpp b/src/plugins/sceneformats/assimp/qaiscene.cpp
index ada229b73..5634855f9 100644
--- a/src/plugins/sceneformats/assimp/qaiscene.cpp
+++ b/src/plugins/sceneformats/assimp/qaiscene.cpp
@@ -71,6 +71,26 @@ QAiScene::QAiScene(const aiScene *scene, QAiSceneHandler *handler)
m_root = loader.loadMeshes();
m_root->setParent(this);
m_animations = loader.loadAnimations();
+ m_aiLoader = 0;
+}
+
+/*!
+ \internal
+ Construct a new QAiScene object and setting the given \a handler.
+
+ Note that the scene which will be used to generate the QAiScene has
+ not been added yet - this is used in the network case and requires
+ a later call to the loadScene function to work correctly
+
+ \sa loadScene()
+*/
+QAiScene::QAiScene(QAiSceneHandler *handler)
+ : QGLAbstractScene(0)
+{
+ Q_ASSERT(handler);
+ //create a temporary loader and get a temporary root node for the scene.
+ m_aiLoader = new QAiLoader(0, handler);
+ m_root=m_aiLoader->m_builder.sceneNode();
}
/*!
@@ -80,7 +100,7 @@ QAiScene::QAiScene(const aiScene *scene, QAiSceneHandler *handler)
*/
QAiScene::~QAiScene()
{
- // nothing to do here
+ delete m_aiLoader;
}
/*!
@@ -109,6 +129,59 @@ QGLSceneNode *QAiScene::mainNode() const
return m_root;
}
+/*!
+ \internal
+ Returns the aiLoader associated with the scene (if any).
+*/
+QAiLoader * QAiScene::aiLoader() const
+{
+ return m_aiLoader;
+}
+
+/*!
+ \internal
+ Load the new \a scene and swap the extant palette from the temporary roote
+ node into the current root node.
+
+ The QAiScene object takes ownership of the \a file.
+*/
+void QAiScene::loadScene(const aiScene *scene)
+{
+ Q_ASSERT(scene);
+
+ //Get the old material information
+ QSharedPointer<QGLMaterialCollection>oldPalette= m_aiLoader->m_builder.palette();
+ int oldIndex = m_root->materialIndex();
+
+ //Reset the palette for the root node.
+ QSharedPointer<QGLMaterialCollection>newPalette = QSharedPointer<QGLMaterialCollection>(new QGLMaterialCollection());
+ m_aiLoader->m_builder.sceneNode()->setPalette(newPalette);
+ m_aiLoader->m_scene = scene;
+
+ //Commence loading of the mesh.
+ m_root = m_aiLoader->loadMeshes(); //this won't actually change the root unless we've messed up.
+ delete m_aiLoader;
+ m_aiLoader = 0;
+
+ //Swap out the materials palette
+ int indexCount=0;
+ int materialCount=0;
+ QGLMaterial * currentMaterial = NULL;
+ do {
+ currentMaterial = oldPalette->removeMaterial(indexCount);
+ if (currentMaterial) {
+ materialCount = m_root->palette()->addMaterial(currentMaterial);
+ indexCount++;
+ }
+ } while (currentMaterial);
+ m_root->setMaterialIndex(materialCount-(indexCount-1)+oldIndex);
+
+ //update picking nodes for the whole scene if needed
+ if (pickable()) generatePickNodes();
+
+ emit sceneUpdated();
+}
+
QList<QGLSceneAnimation *> QAiScene::animations() const
{
return m_animations;
diff --git a/src/plugins/sceneformats/assimp/qaiscene.h b/src/plugins/sceneformats/assimp/qaiscene.h
index 5eb096e29..e1543a595 100644
--- a/src/plugins/sceneformats/assimp/qaiscene.h
+++ b/src/plugins/sceneformats/assimp/qaiscene.h
@@ -52,24 +52,30 @@ QT_BEGIN_NAMESPACE
QT_MODULE(Qt3D)
-#include <QtCore/qurl.h>
-
class QGLSceneNode;
class QAiSceneHandler;
+class QAiLoader;
class QAiScene : public QGLAbstractScene
{
Q_OBJECT
public:
explicit QAiScene(const aiScene *scene, QAiSceneHandler *handler);
+ explicit QAiScene(QAiSceneHandler *handler);
virtual ~QAiScene();
+ //load a scene with the current handler
+ void loadScene(const aiScene*scene);
+
QList<QObject *> objects() const;
QGLSceneNode *mainNode() const;
QList<QGLSceneAnimation *> animations() const;
private:
- QGLSceneNode *m_root;
+ QAiLoader * aiLoader() const;
QList<QGLSceneAnimation *> m_animations;
+protected:
+ QGLSceneNode *m_root;
+ QAiLoader *m_aiLoader;
};
QT_END_NAMESPACE
diff --git a/src/plugins/sceneformats/assimp/qaiscenehandler.cpp b/src/plugins/sceneformats/assimp/qaiscenehandler.cpp
index 1f86fe869..27add9b28 100644
--- a/src/plugins/sceneformats/assimp/qaiscenehandler.cpp
+++ b/src/plugins/sceneformats/assimp/qaiscenehandler.cpp
@@ -41,6 +41,7 @@
#include "qaiscenehandler.h"
#include "qaiscene.h"
+#include "qdownloadmanager.h"
#include "ailoaderiosystem.h"
#include "aiScene.h"
@@ -49,6 +50,8 @@
#include <QtCore/qdir.h>
#include <QtCore/qdebug.h>
+#include <QObject>
+#include <QBuffer>
#define qAiPostProcessPreset ( \
@@ -235,10 +238,10 @@ QGLAbstractScene *QAiSceneHandler::read()
QUrl u = url();
if (u.scheme() != QLatin1String("file"))
{
- qWarning("Non-file URL's not yet supported");
- return 0;
+ path = u.toEncoded();
+ } else {
+ path = u.toLocalFile();
}
- path = u.toLocalFile();
if (m_removeComponentFlags)
m_options |= aiProcess_RemoveComponent;
@@ -285,6 +288,7 @@ QGLAbstractScene *QAiSceneHandler::read()
Assimp::DefaultLogger::kill();
+ finalize();
return qscene;
}
@@ -352,4 +356,94 @@ void DumpScene(const aiScene* pScene)
}
}
+QGLAbstractScene * QAiSceneHandler::download()
+{
+ QUrl u = url();
+
+ if (u.scheme() == QLatin1String("file")) {
+ qWarning() << "Cannot download urls with FILE scheme. Use the read() method.";
+ } else {
+ if (m_removeComponentFlags)
+ m_options |= aiProcess_RemoveComponent;
+ else
+ m_options &= ~aiProcess_RemoveComponent;
+
+ m_importer.SetPropertyInteger(AI_CONFIG_PP_RVC_FLAGS, m_removeComponentFlags);
+ m_importer.SetPropertyInteger(AI_CONFIG_PP_SBP_REMOVE, m_removeSortFlags);
+ m_importer.SetPropertyInteger(AI_CONFIG_PP_SLM_VERTEX_LIMIT, m_meshSplitVertexLimit);
+ m_importer.SetPropertyInteger(AI_CONFIG_PP_SLM_TRIANGLE_LIMIT, m_meshSplitTriangleLimit);
+
+ // force this on, and provide no way to turn it off. Its set by the
+ // aiProcessPreset_TargetRealtime_Quality option in the constructor.
+ // Guarantees that all meshes only have one primitive type
+ Q_ASSERT(m_options & aiProcess_SortByPType);
+
+ setScene(new QAiScene(this));
+ //m_scene = new QAiScene(this);
+
+ //m_scene->begindownLoad(url());
+
+ downloadScene();
+ }
+ return getScene();
+}
+
+void QAiSceneHandler::downloadComplete(QByteArray *sceneData)
+{
+ //Create i/o device to use for file reading.
+ QBuffer sceneBuffer(sceneData);
+ sceneBuffer.open(QIODevice::ReadOnly);
+ setDevice(&sceneBuffer);
+
+ //Set i/o system to use non-file based device.
+ AiLoaderIOSystem *ios = new AiLoaderIOSystem(device(), url());
+ m_importer.SetIOHandler(ios);
+
+ QString path;
+ path = url().toEncoded();
+
+ Assimp::Logger *log = 0;
+ Assimp::Logger::LogSeverity severity = Assimp::Logger::NORMAL;
+ if (m_showWarnings)
+ {
+ severity = Assimp::Logger::VERBOSE;
+ int streams = aiDefaultLogStream_FILE |
+#ifdef Q_CC_MSVC
+ aiDefaultLogStream_DEBUGGER
+#else
+ aiDefaultLogStream_STDERR
+#endif
+ ;
+ log = Assimp::DefaultLogger::create("AssimpLog.txt", severity, streams);
+ }
+
+ const aiScene* scene = m_importer.ReadFile(path.toStdString(), m_options);
+ if (!scene)
+ {
+ // Notes on import success flags - according to assimp doco if validation
+ // is requested the flags AI_SCENE_FLAGS_VALIDATION_WARNING will be set
+ // if there's a warning, and AI_SCENE_FLAGS_VALIDATED is set on success.
+ // This does not happen. Also AI_SCENE_FLAGS_INCOMPLETE can be set on a
+ // valid model, so checking for that is no use either. Best way to proceed
+ // is that if ShowWarnings is turned on above, then any pertinent warnings
+ // will be shown; and if a NULL result is returned here, then its a fatal
+ // error and a message is shown here. If a non-NULL result is returned
+ // just go ahead and try to load it.
+ QString c = QDir::current().absolutePath();
+ qWarning("Asset importer error: %s\n", m_importer.GetErrorString());
+ if (log)
+ qWarning("For details check log: %s/AssimpLog.txt\n", qPrintable(c));
+ } else {
+ //If we have reached this point everything has proceeded correctly,
+ //load the scene.
+ QAiScene *theScene = qobject_cast<QAiScene*>(getScene());
+ theScene->loadScene(scene);
+ }
+
+ Assimp::DefaultLogger::kill();
+
+ delete sceneData;
+ finalize();
+}
+
QT_END_NAMESPACE
diff --git a/src/plugins/sceneformats/assimp/qaiscenehandler.h b/src/plugins/sceneformats/assimp/qaiscenehandler.h
index 94e4eac1d..45c7a2c66 100644
--- a/src/plugins/sceneformats/assimp/qaiscenehandler.h
+++ b/src/plugins/sceneformats/assimp/qaiscenehandler.h
@@ -48,6 +48,7 @@
#include "assimp.hpp"
#include <QtCore/qurl.h>
+#include <QObject>
Q_DECLARE_FLAGS(aiPostProcessFlags, aiPostProcessSteps);
Q_DECLARE_OPERATORS_FOR_FLAGS(aiPostProcessFlags);
@@ -59,6 +60,7 @@ class QIODevice;
class QAiSceneHandler : public QGLSceneFormatHandler
{
+ Q_OBJECT
public:
enum Options {
NoOptions,
@@ -82,6 +84,7 @@ public:
~QAiSceneHandler();
QGLAbstractScene *read();
+ QGLAbstractScene *download();
void decodeOptions(const QString &options);
@@ -92,6 +95,9 @@ public:
quint32 removeComponentFlags() const { return m_removeComponentFlags; }
quint32 removeSortFlags() const { return m_removeSortFlags; }
+public slots:
+ void downloadComplete(QByteArray *sceneData);
+
private:
aiPostProcessFlags m_options;
bool m_showWarnings;
diff --git a/src/plugins/sceneformats/bezier/qglbezierscenehandler.cpp b/src/plugins/sceneformats/bezier/qglbezierscenehandler.cpp
index f79b332aa..58ea68c60 100644
--- a/src/plugins/sceneformats/bezier/qglbezierscenehandler.cpp
+++ b/src/plugins/sceneformats/bezier/qglbezierscenehandler.cpp
@@ -188,4 +188,10 @@ QGLAbstractScene *QGLBezierSceneHandler::read()
return new QGLBezierScene(geometry.finalizedSceneNode());
}
+QGLAbstractScene *QGLBezierSceneHandler::download()
+{
+ qWarning() << "Network loading is not supported for .bez files.";
+ return NULL;
+}
+
QT_END_NAMESPACE
diff --git a/src/plugins/sceneformats/bezier/qglbezierscenehandler.h b/src/plugins/sceneformats/bezier/qglbezierscenehandler.h
index d07fc47d6..59f8945f9 100644
--- a/src/plugins/sceneformats/bezier/qglbezierscenehandler.h
+++ b/src/plugins/sceneformats/bezier/qglbezierscenehandler.h
@@ -50,6 +50,7 @@ class QGLBezierSceneHandler : public QGLSceneFormatHandler
{
public:
QGLAbstractScene *read();
+ QGLAbstractScene *download();
};
QT_END_NAMESPACE
diff --git a/src/plugins/sceneformats/obj/qglobjscenehandler.cpp b/src/plugins/sceneformats/obj/qglobjscenehandler.cpp
index 6ae0b7872..aea28126c 100644
--- a/src/plugins/sceneformats/obj/qglobjscenehandler.cpp
+++ b/src/plugins/sceneformats/obj/qglobjscenehandler.cpp
@@ -326,6 +326,12 @@ QGLAbstractScene *QGLObjSceneHandler::read()
return new QGLObjScene(builder.finalizedSceneNode());
}
+QGLAbstractScene *QGLObjSceneHandler::download()
+{
+ qWarning() << "Network loading of obj files using this plugin is not implemented.";
+ return NULL;
+}
+
void QGLObjSceneHandler::loadMaterialLibrary(const QString& name)
{
QUrl materialUrl = url().resolved(name);
diff --git a/src/plugins/sceneformats/obj/qglobjscenehandler.h b/src/plugins/sceneformats/obj/qglobjscenehandler.h
index 1cfd5551f..0f62bc370 100644
--- a/src/plugins/sceneformats/obj/qglobjscenehandler.h
+++ b/src/plugins/sceneformats/obj/qglobjscenehandler.h
@@ -55,6 +55,7 @@ class QGLObjSceneHandler : public QGLSceneFormatHandler
public:
QGLObjSceneHandler();
QGLAbstractScene *read();
+ QGLAbstractScene *download();
//! [1]
void decodeOptions(const QString &options);