summaryrefslogtreecommitdiffstats
path: root/src/plugins/sceneformats/assimp
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/sceneformats/assimp')
-rw-r--r--src/plugins/sceneformats/assimp/README.txt12
-rw-r--r--src/plugins/sceneformats/assimp/ailoaderiostream.cpp121
-rw-r--r--src/plugins/sceneformats/assimp/ailoaderiostream.h67
-rw-r--r--src/plugins/sceneformats/assimp/ailoaderiosystem.cpp156
-rw-r--r--src/plugins/sceneformats/assimp/ailoaderiosystem.h67
-rw-r--r--src/plugins/sceneformats/assimp/assimp.pro32
-rw-r--r--src/plugins/sceneformats/assimp/main.cpp100
-rw-r--r--src/plugins/sceneformats/assimp/qailoader.cpp540
-rw-r--r--src/plugins/sceneformats/assimp/qailoader.h89
-rw-r--r--src/plugins/sceneformats/assimp/qaimesh.cpp143
-rw-r--r--src/plugins/sceneformats/assimp/qaimesh.h67
-rw-r--r--src/plugins/sceneformats/assimp/qaiscene.cpp112
-rw-r--r--src/plugins/sceneformats/assimp/qaiscene.h77
-rw-r--r--src/plugins/sceneformats/assimp/qaiscenehandler.cpp286
-rw-r--r--src/plugins/sceneformats/assimp/qaiscenehandler.h108
15 files changed, 1977 insertions, 0 deletions
diff --git a/src/plugins/sceneformats/assimp/README.txt b/src/plugins/sceneformats/assimp/README.txt
new file mode 100644
index 000000000..cabf1bdd8
--- /dev/null
+++ b/src/plugins/sceneformats/assimp/README.txt
@@ -0,0 +1,12 @@
+This importer uses the Asset Importer library available from:
+
+http://assimp.sourceforge.net/
+
+Copyright (c) 2008-2010 ASSIMP Development Team
+All rights reserved.
+
+For convenience a stripped down source tree is included in this distribution. See the license
+included at $QT3D_SOURCE/3rdparty/assimp/LICENCE, or at http://assimp.sourceforge.net/main_license.html
+
+To use your own build of AssImp, modify the assimp.pro file and/or export the environment variables
+specified there.
diff --git a/src/plugins/sceneformats/assimp/ailoaderiostream.cpp b/src/plugins/sceneformats/assimp/ailoaderiostream.cpp
new file mode 100644
index 000000000..0ee44863f
--- /dev/null
+++ b/src/plugins/sceneformats/assimp/ailoaderiostream.cpp
@@ -0,0 +1,121 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtQuick3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "ailoaderiostream.h"
+
+#include <QtCore/qiodevice.h>
+
+#include <QtCore/qdebug.h>
+
+AiLoaderIOStream::AiLoaderIOStream(QIODevice *device)
+ : m_device(device)
+ , m_errorState(false)
+{
+ Q_ASSERT(device);
+}
+
+AiLoaderIOStream::~AiLoaderIOStream()
+{
+ // Nothing to do here
+}
+
+size_t AiLoaderIOStream::Read( void* pvBuffer, size_t pSize, size_t pCount)
+{
+ qint64 result = m_device->read((char*)pvBuffer, pSize * pCount);
+ size_t res = result;
+ m_errorState = (result == -1);
+ if (m_errorState)
+ fprintf(stderr, "AI read error: %s\n", qPrintable(m_device->errorString()));
+ if ((pSize * pCount) != res) // AI will treat as error
+ {
+ fprintf(stderr, "read mismatch requested size: %lu x count: %lu = %lu != %lu actuall read\n",
+ pSize, pCount, (pSize * pCount), res);
+ }
+ return res;
+}
+
+size_t AiLoaderIOStream::Write( const void* pvBuffer, size_t pSize, size_t pCount)
+{
+ qint64 result = m_device->write((char*)pvBuffer, pSize * pCount);
+ m_errorState = (result == -1);
+ if (m_errorState)
+ fprintf(stderr, "AI write error: %s\n", qPrintable(m_device->errorString()));
+ return result;
+}
+
+aiReturn AiLoaderIOStream::Seek(size_t pOffset, aiOrigin pOrigin)
+{
+ // cannot deal with sockets right now
+ Q_ASSERT(!m_device->isSequential());
+ switch (pOrigin)
+ {
+ case aiOrigin_SET:
+ m_errorState = m_device->seek(pOffset);
+ break;
+ case aiOrigin_CUR:
+ m_errorState = m_device->seek(m_device->pos() + pOffset);
+ break;
+ case aiOrigin_END:
+ m_errorState = m_device->seek(m_device->size() + pOffset);
+ break;
+ default:
+ Q_ASSERT(0);
+ return(aiReturn_FAILURE);
+ }
+ if (m_errorState)
+ return aiReturn_FAILURE;
+ return aiReturn_SUCCESS;
+}
+
+size_t AiLoaderIOStream::Tell() const
+{
+ return m_device->pos();
+}
+
+size_t AiLoaderIOStream::FileSize() const
+{
+ return m_device->size();
+}
+
+void AiLoaderIOStream::Flush()
+{
+ // do nothing
+}
diff --git a/src/plugins/sceneformats/assimp/ailoaderiostream.h b/src/plugins/sceneformats/assimp/ailoaderiostream.h
new file mode 100644
index 000000000..be3172bb2
--- /dev/null
+++ b/src/plugins/sceneformats/assimp/ailoaderiostream.h
@@ -0,0 +1,67 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtQuick3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef AILOADERIOSTREAM_H
+#define AILOADERIOSTREAM_H
+
+#include "IOStream.h"
+#include "IOSystem.h"
+
+class QIODevice;
+
+class AiLoaderIOStream : public Assimp::IOStream
+{
+public:
+ AiLoaderIOStream(QIODevice *device);
+ ~AiLoaderIOStream();
+ size_t Read( void* pvBuffer, size_t pSize, size_t pCount);
+ size_t Write( const void* pvBuffer, size_t pSize, size_t pCount);
+ aiReturn Seek( size_t pOffset, aiOrigin pOrigin);
+ size_t Tell() const;
+ size_t FileSize() const;
+ void Flush();
+ QIODevice *device() const { return m_device; }
+private:
+ QIODevice *m_device;
+ bool m_errorState;
+};
+
+#endif // AILOADERIOSTREAM_H
diff --git a/src/plugins/sceneformats/assimp/ailoaderiosystem.cpp b/src/plugins/sceneformats/assimp/ailoaderiosystem.cpp
new file mode 100644
index 000000000..b31f275d0
--- /dev/null
+++ b/src/plugins/sceneformats/assimp/ailoaderiosystem.cpp
@@ -0,0 +1,156 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtQuick3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "ailoaderiosystem.h"
+#include "ailoaderiostream.h"
+#include "DefaultLogger.h"
+
+#include <QtCore/qfile.h>
+#include <QtCore/qdir.h>
+
+AiLoaderIOSystem::AiLoaderIOSystem(QIODevice *device, QUrl url)
+ : m_device(device)
+ , m_url(url)
+{
+}
+
+AiLoaderIOSystem::~AiLoaderIOSystem()
+{
+ // we don't own m_device
+ qDeleteAll(m_sub);
+}
+
+bool AiLoaderIOSystem::Exists(const char* path) const
+{
+ return QFile::exists(QLatin1String(path));
+}
+
+char AiLoaderIOSystem::getOsSeparator() const
+{
+ return QDir::separator().toLatin1();
+}
+
+/*!
+ \internal
+ Open the pFile with the pMode, where mode is given by "man fopen"
+*/
+Assimp::IOStream* AiLoaderIOSystem::Open(const char* pFile, const char* pMode)
+{
+ // This is just the file already opened on the device
+ if (m_url.toEncoded().endsWith(pFile))
+ return new AiLoaderIOStream(m_device);
+
+ // New relative file
+ QUrl rel;
+ rel.setScheme(m_url.scheme());
+ rel.setPath(QLatin1String(pFile));
+ QUrl url = m_url.resolved(rel);
+
+ // TODO: handle network case
+ if (url.scheme() != QLatin1String("file"))
+ {
+ qWarning("Opening %s url not supported", qPrintable(url.scheme()));
+ return 0;
+ }
+
+ char mode_str[4];
+ qMemSet(mode_str, '\0', 4);
+ int i = 0;
+ for (const char *ptr = pMode; i < 4 && *ptr; ++ptr)
+ {
+ if (*ptr != 'b') // ignore the binary attribute
+ mode_str[i++] = *ptr;
+ }
+ QIODevice::OpenMode mode = QIODevice::NotOpen;
+ if (::strncmp("r", mode_str, 1) == 0)
+ {
+ mode = QIODevice::ReadOnly;
+ }
+ else if (::strncmp("r+", mode_str, 2) == 0)
+ {
+ mode = QIODevice::ReadWrite;
+ }
+ else if (::strncmp("w", mode_str, 1) == 0)
+ {
+ mode = QIODevice::WriteOnly | QIODevice::Truncate;
+ }
+ else if (::strncmp("w+", mode_str, 2) == 0)
+ {
+ mode = QIODevice::ReadWrite | QIODevice::Truncate;
+ }
+ else if (::strncmp("a", mode_str, 1) == 0)
+ {
+ mode = QIODevice::WriteOnly | QIODevice::Append;
+ }
+ else if (::strncmp("a+", mode_str, 2) == 0)
+ {
+ mode = QIODevice::ReadWrite | QIODevice::Append;
+ }
+ else
+ {
+ std::string err("Error: invalid mode flag:");
+ err.append(mode_str).append(" when opening ").append(pFile);
+ Assimp::DefaultLogger::get()->warn(err);
+ return 0;
+ }
+
+ QFile *f = new QFile(url.toLocalFile());
+ bool res = f->open(mode);
+ if (!res)
+ {
+ std::string err("Error: could not open subsequent file:");
+ err.append(pFile).append("--").append(f->errorString().toStdString());
+ Assimp::DefaultLogger::get()->warn(err);
+ delete f;
+ return 0;
+ }
+ m_sub.append(f);
+ AiLoaderIOStream *s = new AiLoaderIOStream(f);
+ return s;
+}
+
+void AiLoaderIOSystem::Close(Assimp::IOStream* stream)
+{
+ AiLoaderIOStream *s = static_cast<AiLoaderIOStream*>(stream);
+ Q_ASSERT(s);
+ s->device()->close();
+ delete stream;
+}
diff --git a/src/plugins/sceneformats/assimp/ailoaderiosystem.h b/src/plugins/sceneformats/assimp/ailoaderiosystem.h
new file mode 100644
index 000000000..8df0a3c75
--- /dev/null
+++ b/src/plugins/sceneformats/assimp/ailoaderiosystem.h
@@ -0,0 +1,67 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtQuick3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef AILOADERIOSYSTEM_H
+#define AILOADERIOSYSTEM_H
+
+#include "IOSystem.h"
+
+#include <QtCore/qurl.h>
+
+class QIODevice;
+class IOStream;
+
+class AiLoaderIOSystem : public Assimp::IOSystem
+{
+public:
+ AiLoaderIOSystem(QIODevice *device, QUrl url);
+ ~AiLoaderIOSystem();
+ virtual bool Exists( const char* path) const;
+ virtual char getOsSeparator() const;
+ virtual Assimp::IOStream* Open(const char* pFile, const char* pMode = "rb");
+ virtual void Close(Assimp::IOStream* pFile);
+private:
+ QIODevice *m_device;
+ QList<QIODevice*> m_sub;
+ QUrl m_url;
+};
+
+#endif // AILOADERIOSYSTEM_H
diff --git a/src/plugins/sceneformats/assimp/assimp.pro b/src/plugins/sceneformats/assimp/assimp.pro
new file mode 100644
index 000000000..43b74363e
--- /dev/null
+++ b/src/plugins/sceneformats/assimp/assimp.pro
@@ -0,0 +1,32 @@
+TARGET = qsceneai
+include(../../qpluginbase.pri)
+HEADERS += qailoader.h \
+ qaiscene.h \
+ qaiscenehandler.h \
+ qaimesh.h \
+ ailoaderiostream.h \
+ ailoaderiosystem.h
+SOURCES += main.cpp \
+ qailoader.cpp \
+ qaiscene.cpp \
+ qaiscenehandler.cpp \
+ qaimesh.cpp \
+ ailoaderiostream.cpp \
+ ailoaderiosystem.cpp
+CONFIG += qt3d
+system_ai {
+ !isEmpty(QMAKE_INCDIR_AI):INCLUDEPATH += $$QMAKE_INCDIR_AI
+ !isEmpty(QMAKE_LIBDIR_AI):LIBS += -L$$QMAKE_LIBDIR_AI
+
+ !isEmpty(QMAKE_LIBS_AI):LIBS += -l$$QMAKE_LIBS_AI
+ else {
+ win32:LIBS += -llibai-1_3
+ else:LIBS += -lai
+ }
+} else {
+ include(../../../../3rdparty/assimp/assimp.pri)
+}
+
+QTDIR_build:DESTDIR = $$QT_BUILD_TREE/plugins/sceneformats
+target.path += $$[QT_INSTALL_PLUGINS]/sceneformats
+INSTALLS += target
diff --git a/src/plugins/sceneformats/assimp/main.cpp b/src/plugins/sceneformats/assimp/main.cpp
new file mode 100644
index 000000000..7251e4627
--- /dev/null
+++ b/src/plugins/sceneformats/assimp/main.cpp
@@ -0,0 +1,100 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtQuick3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qglsceneformatplugin.h"
+#include "qaiscenehandler.h"
+
+#include "assimp.hpp"
+
+#include <QtCore/qmap.h>
+#include <QtCore/qdebug.h>
+
+QT_BEGIN_NAMESPACE
+
+class QAiScenePlugin : public QGLSceneFormatPlugin
+{
+public:
+ QStringList keys() const;
+ virtual QGLSceneFormatHandler *create(QIODevice *device, const QUrl& url, const QString &format) const;
+};
+
+QStringList QAiScenePlugin::keys() const
+{
+ static QMultiMap<QString, QString> mimetypes;
+ if (mimetypes.size() == 0)
+ {
+ mimetypes.insertMulti("3ds", "application/x-3ds");
+ mimetypes.insertMulti("3ds", "image/x-3ds");
+ mimetypes.insertMulti("dae", "model/x3d+binary");
+ mimetypes.insertMulti("dxf", "application/x-dxf");
+ }
+ QStringList result;
+ Assimp::Importer importer;
+ aiString extns;
+ importer.GetExtensionList(extns);
+ QString qextns = QString::fromUtf8(extns.data, extns.length);
+ QStringList extnList = qextns.split(';');
+ for (int i = 0; i < extnList.size(); ++i)
+ {
+ QString xt = extnList.at(i);
+ xt = xt.simplified();
+ if (xt.startsWith(QLatin1String("*.")))
+ xt = xt.mid(2);
+ result << xt;
+ QMap<QString, QString>::const_iterator it = mimetypes.constFind(xt);
+ for ( ; it != mimetypes.constEnd(); ++it)
+ result << it.value();
+ }
+ return result;
+}
+
+QGLSceneFormatHandler *QAiScenePlugin::create(QIODevice *device, const QUrl& url, const QString &format) const
+{
+ Q_UNUSED(device);
+ Q_UNUSED(url);
+ Q_UNUSED(format);
+ return new QAiSceneHandler;
+}
+
+Q_EXPORT_STATIC_PLUGIN(QAiScenePlugin)
+Q_EXPORT_PLUGIN2(qsceneai, QAiScenePlugin)
+
+QT_END_NAMESPACE
diff --git a/src/plugins/sceneformats/assimp/qailoader.cpp b/src/plugins/sceneformats/assimp/qailoader.cpp
new file mode 100644
index 000000000..18ba1e172
--- /dev/null
+++ b/src/plugins/sceneformats/assimp/qailoader.cpp
@@ -0,0 +1,540 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtQuick3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qailoader.h"
+#include "qaiscenehandler.h"
+#include "qaiscene.h"
+#include "qaimesh.h"
+
+#include "qgeometrydata.h"
+#include "qgltwosidedmaterial.h"
+#include "qglmaterial.h"
+#include "qglmaterialcollection.h"
+#include "qglpainter.h"
+#include "qgltexture2d.h"
+#include "qglscenenode.h"
+#include "qlogicalvertex.h"
+
+#include "aiScene.h"
+#include "aiMaterial.h"
+#include "aiMesh.h"
+#include "DefaultLogger.h"
+
+#include <QtCore/qdir.h>
+#include <QtCore/qobject.h>
+#include <QtCore/qfileinfo.h>
+
+QAiLoader::QAiLoader(const aiScene *scene, QAiSceneHandler* handler)
+ : m_scene(scene)
+ , m_root(0)
+ , m_handler(handler)
+ , m_hasTextures(false)
+ , m_hasLitMaterials(false)
+ , m_builder(new QGLMaterialCollection(m_root))
+{
+}
+
+QAiLoader::~QAiLoader()
+{
+ // nothing to do here - m_rootNode is taken ownership of by caller of
+ // rootNode() method
+}
+
+static inline void assertOnePrimitiveType(aiMesh *mesh)
+{
+#ifndef QT_NO_DEBUG
+ int k = 0; // count the number of bits set in the primitives
+ unsigned int msk = 0x01;
+ for (unsigned int p = mesh->mPrimitiveTypes; p; p >>= 1)
+ if (p & msk)
+ ++k;
+ Q_ASSERT(k == 1); // Assimp SortByPType promises this
+#else
+ Q_UNUSED(mesh);
+#endif
+}
+
+static inline bool qHasTextures(const QGLSceneNode *node)
+{
+ QGLMaterial *mat = node->material();
+ for (int i = 0; i < mat->textureLayerCount(); ++i)
+ if (node->material()->texture(i))
+ return true;
+ return false;
+}
+
+void QAiLoader::loadMesh(aiMesh *mesh)
+{
+ QString name = QString::fromUtf8(mesh->mName.data, mesh->mName.length);
+ // qDebug() << "loadMesh" << name << "with" << mesh->mNumVertices << "vertices"
+ // << "and" << mesh->mNumFaces << "faces";
+
+ assertOnePrimitiveType(mesh);
+
+ if (mesh->mPrimitiveTypes & aiPrimitiveType_TRIANGLE)
+ {
+ m_builder.newSection();
+ QGLSceneNode *node = m_builder.currentNode();
+ node->setObjectName(name);
+ QAiMesh m(mesh);
+ m.build(m_builder, m_handler->showWarnings());
+ m_meshes.append(node);
+ if (qHasTextures(node))
+ m_hasTextures = true;
+ else
+ m_hasLitMaterials = true;
+ }
+ else
+ {
+ // TODO: Implement other types in qaimesh.cpp
+ if (m_handler->showWarnings())
+ {
+ QString error = QLatin1String("Bad primitive type in mesh %1 : %2");
+ error = error.arg(name).arg(mesh->mPrimitiveTypes);
+ Assimp::DefaultLogger::get()->warn(error.toStdString());
+ }
+ }
+
+ if (m_handler->showWarnings())
+ {
+ if (!(m_handler->removeComponentFlags() & aiComponent_COLORS))
+ {
+ // TODO: Implement models with per vertex colors. Ok, the
+ // vertex colors were wanted but are not supported yet.
+ for (int i = 0; i < AI_MAX_NUMBER_OF_COLOR_SETS; ++i)
+ {
+ if (mesh->HasVertexColors(i))
+ {
+ QString error = QLatin1String(
+ "Found color information in mesh %1, channel %2"
+ "- per vertex color not yet supported");
+ error = error.arg(name).arg(i);
+ Assimp::DefaultLogger::get()->warn(error.toStdString());
+ break;
+ }
+ }
+ }
+ if (mesh->HasBones())
+ {
+ // TODO: Implement skeletal animation
+ QString error = QLatin1String("Bones in mesh %1 not yet supported");
+ error.arg(name);
+ Assimp::DefaultLogger::get()->warn(error.toStdString());
+ }
+ if (mesh->HasTangentsAndBitangents())
+ {
+ // TODO: Implement normal maps - here and in the texture import
+ QString error = QLatin1String("Tangents for normal map in mesh %1 not yet supported");
+ error.arg(name);
+ Assimp::DefaultLogger::get()->warn(error.toStdString());
+ }
+ }
+}
+
+inline static QMatrix4x4 getNodeMatrix(aiNode *node)
+{
+ QMatrix4x4 nodeMatrix;
+ if (node->mTransformation.IsIdentity())
+ return nodeMatrix;
+ aiQuaternion rotation;
+ aiVector3D position;
+ aiVector3D scale;
+ node->mTransformation.Decompose(scale, rotation, position);
+ QVector3D qscale(scale.x,scale.y, scale.z);
+ QVector3D qposition(position.x, position.y, position.z);
+ QQuaternion qrotation(rotation.w, rotation.x, rotation.y, rotation.z);
+ if (!qscale.isNull())
+ nodeMatrix.scale(qscale);
+ if (!qposition.isNull())
+ nodeMatrix.translate(qposition);
+ if (!qrotation.isNull())
+ nodeMatrix.rotate(qrotation);
+ return nodeMatrix;
+}
+
+void QAiLoader::loadNodes(aiNode *nodeList, QGLSceneNode *parentNode)
+{
+ QMap<aiNode *, QGLSceneNode *>::const_iterator it = m_nodeMap.constFind(nodeList);
+ QGLSceneNode *node = 0;
+ if (it == m_nodeMap.constEnd()) // not found
+ {
+ node = new QGLSceneNode(parentNode);
+ m_nodes.append(node);
+ QString name = QString::fromUtf8(nodeList->mName.data, nodeList->mName.length);
+ if (name.isEmpty())
+ name = QString(QLatin1String("aiNode %1")).arg(m_nodes.size());
+ node->setObjectName(name);
+ QMatrix4x4 mat = getNodeMatrix(nodeList);
+ if (!mat.isIdentity())
+ node->setLocalTransform(mat);
+ for (unsigned int i = 0; i < nodeList->mNumChildren; ++i)
+ loadNodes(nodeList->mChildren[i], node);
+ for (unsigned int i = 0; i < nodeList->mNumMeshes; ++i)
+ {
+ int n = nodeList->mMeshes[i];
+ if (n < m_meshes.size())
+ node->addNode(m_meshes.at(n));
+ }
+ }
+ else
+ {
+ node = it.value();
+ parentNode->addNode(node);
+ }
+}
+
+/*!
+ \internal
+ Loads all the geometry, materials, and texture associations from the assigned
+ file, and returns the root node of the resulting scene graph.
+
+ The caller must take ownership of the root node returned, and delete it
+ when its no longer required.
+*/
+QGLSceneNode *QAiLoader::loadMeshes()
+{
+ Q_ASSERT(m_scene);
+ for (unsigned int i = 0; i < m_scene->mNumMaterials; ++i)
+ loadMaterial(m_scene->mMaterials[i]);
+
+ // builds a naive scene heierarchy with all meshes under the root node
+ for (unsigned int i = 0; i < m_scene->mNumMeshes; ++i)
+ loadMesh(m_scene->mMeshes[i]);
+
+ // fetch the naive scene heierarchy from the builder
+ m_root = m_builder.finalizedSceneNode();
+
+ QString name = m_handler->url().path();
+ int pos = name.lastIndexOf("/");
+ if (pos == -1)
+ pos = name.lastIndexOf("\\");
+ if (pos != -1)
+ name = name.mid(pos+1);
+ m_root->setObjectName(name);
+
+ // if scene has a node heierarchy replace the naive heierarchy with that
+ if (m_scene->mRootNode->mNumChildren > 0 && m_scene->mRootNode->mChildren)
+ {
+ m_root->removeNodes(m_root->children());
+ loadNodes(m_scene->mRootNode, m_root);
+ }
+
+ if (m_hasTextures) // make textures the default
+ {
+ m_root->setEffect(QGL::LitModulateTexture2D);
+ if (m_hasLitMaterials)
+ {
+ for (int i = 0; i < m_meshes.size(); ++i)
+ if (!qHasTextures(m_meshes.at(i)))
+ m_meshes.at(i)->setEffect(QGL::LitMaterial);
+ }
+ }
+ else
+ {
+ m_root->setEffect(QGL::LitMaterial);
+ }
+
+ if (m_handler->showWarnings())
+ {
+ QString message = QLatin1String("AssetImporter loader %1 -- "
+ "Mesh count: %2 -- Node count: %3 -- "
+ "Material count: %4");
+ QUrl url = m_handler->url();
+ message = message.arg(url.toString()).arg(m_meshes.size())
+ .arg(m_nodes.size()).arg(m_root->palette()->size());
+ Assimp::DefaultLogger::get()->warn(message.toStdString());
+ }
+
+//#define DEBUG_ME
+#ifdef DEBUG_ME
+ qDumpScene(m_root);
+
+ QList<QGLSceneNode*> c = m_root->allChildren();
+ QSet<quint64> debugged;
+ for (int i = 0; i < c.size(); ++i)
+ {
+ if (c.at(i)->geometry().count() > 0)
+ {
+ QGeometryData g = c.at(i)->geometry();
+ qDebug() << "geometry for:" << c.at(i) << "is:" << g.id();
+ if (!debugged.contains(g.id()))
+ {
+ qDebug() << g;
+ debugged.insert(g.id());
+ }
+ }
+ }
+#endif
+
+ return m_root;
+}
+
+/*!
+ \internal
+ Search for a resource based on the given \a path.
+
+ If the URL for the currently loading mesh has a scheme other than
+ "file" then a URL with the path relative to that URL is returned.
+
+ If the URL for the currently loading mesh has a "file" scheme, then
+ first a case-sensitive search is done of all of the current directory,
+ and the :/ resource directory, and the directory of the current mesh
+ file.
+
+ If the file is not found in any of those locations then they are
+ searched again case-insensitively. If the file is found, then a
+ URL based on the absolute file path of the matching file is returned.
+
+ Otherwise an empty string is returned.
+*/
+QUrl QAiLoader::ensureResource(const QString &path)
+{
+ QUrl res;
+ QUrl base = m_handler->url();
+ if (base.scheme() == QLatin1String("file"))
+ {
+ res = base.resolved(path);
+ //qDebug() << "ensureResource - base:" << base
+ // << " -- path:" << path << "-- resolved:" << res;
+ if (QFile::exists(res.path())) // shortcut common case
+ return res;
+ QStringList paths;
+ paths << QLatin1String(".") << QLatin1String(":/"); // current directory and aliased/root resource file
+ if (!base.isEmpty())
+ {
+ QFileInfo fi(base.path());
+ paths.prepend(fi.absoluteDir().absolutePath());
+ }
+ bool caseInsensitive = false;
+ do {
+ QStringList::const_iterator it(paths.begin());
+ for ( ; it != paths.end(); ++it)
+ {
+ QDir resDir(*it);
+ QStringList fileList = resDir.entryList(QDir::Files);
+ if (caseInsensitive)
+ {
+ QStringList::const_iterator fit(fileList.begin());
+ for ( ; fit != fileList.end(); ++fit)
+ {
+ if (fit->toLower() == path.toLower())
+ {
+ res.setScheme(QLatin1String("file"));
+ res.setPath(resDir.absoluteFilePath(*fit));
+ break;
+ }
+ }
+ }
+ else
+ {
+ if (fileList.contains(path))
+ {
+ //return resDir.absoluteFilePath(path);
+ res.setScheme(QLatin1String("file"));
+ res.setPath(resDir.absoluteFilePath(path));
+ break;
+ }
+ }
+ }
+ if (caseInsensitive)
+ break;
+ caseInsensitive = true;
+ } while (true);
+ }
+ else
+ {
+ // non-file url
+ res = base.resolved(path);
+ }
+ return res;
+}
+
+void QAiLoader::loadTextures(aiMaterial *ma, QGLMaterial *mq)
+{
+ int texCount;
+ aiTextureType texType;
+ if (m_handler->showWarnings())
+ {
+ // TODO: AssImp has a very rich set of texture related functionality
+ // but until things in this list get implemented, all are just going
+ // to get ignored, tho' they will generate a warning in verbose mode.
+ // So for now, its just inside this conditional - move it out once
+ // implementation of these items begins.
+ static const char * typeNames[] = {
+ "None",
+ "Diffuse",
+ "Specular",
+ "Ambient",
+ "Emissive",
+ "Height",
+ "Normals",
+ "Shininess",
+ "Opacity",
+ "Displacement",
+ "Lightmap",
+ "Reflection",
+ "Unknown",
+ 0
+ };
+
+ for (unsigned int i = 0; i <= aiTextureType_UNKNOWN; ++i)
+ {
+ texType = static_cast<aiTextureType>(i);
+ texCount = ma->GetTextureCount(texType);
+ if (texCount && texType != aiTextureType_DIFFUSE)
+ {
+ QString error = QLatin1String("Unsupported texture type \"%1\" in material \"%2\".");
+ error.arg(typeNames[i]).arg(mq->objectName());
+ Assimp::DefaultLogger::get()->warn(error.toStdString());
+ }
+ }
+ }
+ // TODO: For now assume the only texture we care about is the diffuse one
+ //
+ texCount = ma->GetTextureCount(aiTextureType_DIFFUSE);
+ if (texCount > 0)
+ {
+ if (texCount > 1 && m_handler->showWarnings())
+ {
+ QString error = QLatin1String("Multi-textures not supported: \"%1\" has %2");
+ error.arg(mq->objectName()).arg(texCount);
+ Assimp::DefaultLogger::get()->warn(error.toStdString());
+ }
+ else
+ {
+ aiString path;
+ ma->Get(AI_MATKEY_TEXTURE_DIFFUSE(0), path);
+ QString qpath = QString::fromUtf8(path.data, path.length);
+ QUrl url = ensureResource(qpath);
+ if (url.isEmpty())
+ {
+ if (m_handler->showWarnings())
+ {
+ QString error = QLatin1String("Could not load texture: %1 for material %2");
+ error.arg(url.toString()).arg(mq->objectName());
+ Assimp::DefaultLogger::get()->warn(error.toStdString());
+ }
+ }
+ else
+ {
+ mq->setTextureUrl(url);
+ }
+ }
+ }
+}
+
+/*!
+ Load a material
+*/
+void QAiLoader::loadMaterial(aiMaterial *ma)
+{
+ QGLMaterialCollection *palette = m_builder.palette();
+ QGLMaterial *mq = new QGLMaterial;
+ mq->setObjectName("___DEFAULT_NAME___");
+
+ bool isTwoSided = false;
+ bool isWireframe = false;
+ struct aiColor4D clr;
+ float shininess;
+ float amplitude;
+
+ aiReturn r;
+
+ // In AssImp if the material is two sided then it means cull face
+ // should be turned off: http://assimp.sourceforge.net/lib_html/materials.html
+ r = ma->Get(AI_MATKEY_TWOSIDED, isTwoSided);
+ if (r == aiReturn_SUCCESS && isTwoSided)
+ mq->setProperty("isTwoSided", isTwoSided);
+
+ aiString aName;
+ r = ma->Get(AI_MATKEY_NAME, aName);
+ if (r == aiReturn_SUCCESS && aName.length > 0)
+ mq->setObjectName(QLatin1String(aName.data));
+
+ r = ma->Get(AI_MATKEY_COLOR_AMBIENT, clr);
+ if (r == aiReturn_SUCCESS)
+ mq->setAmbientColor(QColor::fromRgbF(clr.r, clr.g, clr.b, clr.a));
+
+ r = ma->Get(AI_MATKEY_COLOR_DIFFUSE, clr);
+ if (r == aiReturn_SUCCESS)
+ mq->setDiffuseColor(QColor::fromRgbF(clr.r, clr.g, clr.b, clr.a));
+
+ r = ma->Get(AI_MATKEY_COLOR_SPECULAR, clr);
+ if (r == aiReturn_SUCCESS)
+ {
+ QColor spec = QColor::fromRgbF(clr.r, clr.g, clr.b, clr.a);
+ mq->setSpecularColor(spec);
+
+ // By default the specular color is black - very dark.
+ // If the specular color is bright be careful with shininess -
+ // a shininess of 0 will blow everything out to full white. So in
+ // the case of bad materials with this problem, set shiness low.
+ mq->setShininess(64.0);
+ }
+
+ r = ma->Get(AI_MATKEY_SHININESS, shininess);
+ if (r == aiReturn_SUCCESS)
+ mq->setShininess(shininess);
+
+ r = ma->Get(AI_MATKEY_SHININESS_STRENGTH, amplitude);
+ if (r == aiReturn_SUCCESS)
+ mq->setShininess(shininess * amplitude);
+
+ r = ma->Get(AI_MATKEY_ENABLE_WIREFRAME, isWireframe);
+ if (r == aiReturn_SUCCESS && isWireframe)
+ mq->setProperty("isWireFrame", isWireframe);
+
+ loadTextures(ma, mq);
+
+ // INVARIANT: since we create the palette newly in this class, and this
+ // function is the only place we add materials to this palette, the index
+ // values (the positions in the palette generated by this call to addMaterial)
+ // will exactly match the index values of the materials traversed in the
+ // for loop in loadMeshes() - so therefore AI's index values and the ones in
+ // the palette will be the same.
+ //
+ // executive summary: don't muck around with the palettte outside of this call
+
+ int k = palette->addMaterial(mq);
+
+ Q_UNUSED(k);
+ //qDebug() << "loaded material" << k << mq;
+}
diff --git a/src/plugins/sceneformats/assimp/qailoader.h b/src/plugins/sceneformats/assimp/qailoader.h
new file mode 100644
index 000000000..cb646295a
--- /dev/null
+++ b/src/plugins/sceneformats/assimp/qailoader.h
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtQuick3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QGL3DSLOADER_H
+#define QGL3DSLOADER_H
+
+#include <QtCore/qurl.h>
+#include <QtCore/qstring.h>
+#include <QtCore/qmap.h>
+
+#include "aiScene.h"
+
+#include "qglbuilder.h"
+
+class QAiMesh;
+class QGLSceneNode;
+class QAiSceneHandler;
+class QGLMaterial;
+class aiMaterial;
+
+class QAiLoader
+{
+public:
+ QAiLoader(const aiScene *scene, QAiSceneHandler* handler);
+ ~QAiLoader();
+ QGLSceneNode *loadMeshes();
+
+private:
+ void loadMesh(aiMesh *);
+ void loadNodes(aiNode *, QGLSceneNode *);
+ void loadMaterial(aiMaterial *);
+ void loadTextures(aiMaterial *, QGLMaterial *);
+ QUrl ensureResource(const QString &);
+ void optimizeData();
+ void optimizeNodes(QGLSceneNode *node = 0, QGLSceneNode *parent = 0);
+ void countChildNodeReferences();
+
+ const aiScene *m_scene;
+ QGLSceneNode *m_root;
+ QAiSceneHandler *m_handler;
+ QList<QGLSceneNode *> m_nodes;
+ QList<QGLMaterial *> m_materials;
+ QList<QGLSceneNode *> m_meshes;
+ QMap<aiNode *, QGLSceneNode *> m_nodeMap;
+ QMap<QGLSceneNode *, int> m_refCounts;
+ bool m_hasTextures;
+ bool m_hasLitMaterials;
+ QGLBuilder m_builder;
+};
+
+#endif // QGL3DSLOADER_H
diff --git a/src/plugins/sceneformats/assimp/qaimesh.cpp b/src/plugins/sceneformats/assimp/qaimesh.cpp
new file mode 100644
index 000000000..e7d801dc3
--- /dev/null
+++ b/src/plugins/sceneformats/assimp/qaimesh.cpp
@@ -0,0 +1,143 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtQuick3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qaimesh.h"
+#include "qglscenenode.h"
+#include "qglmaterialcollection.h"
+#include "qglbuilder.h"
+
+#include <QtGui/qmatrix4x4.h>
+#include <QtCore/qmath.h>
+
+#include "aiMesh.h"
+#include "DefaultLogger.h"
+
+QAiMesh::QAiMesh(aiMesh *mesh)
+ : m_mesh(mesh)
+{
+}
+
+QAiMesh::~QAiMesh()
+{
+}
+
+static inline QVector2D qv2d(const aiVector3D &v)
+{
+ return QVector2D(v.x, v.y);
+}
+
+static inline QVector2D qv2d_inv(const aiVector3D &v)
+{
+ // invert the v coord because Qt is upside-down
+ return QVector2D(v.x, (1.0 - v.y));
+}
+
+static inline QVector3D qv3d(const aiVector3D &v)
+{
+ return QVector3D(v.x, v.y, v.z);
+}
+
+void QAiMesh::loadTriangles(QGLBuilder &builder)
+{
+ QGeometryData data;
+ for (unsigned int i = 0; i < m_mesh->mNumVertices; ++i)
+ data.appendVertex(qv3d(m_mesh->mVertices[i]));
+ if (m_mesh->HasNormals())
+ for (unsigned int i = 0; i < m_mesh->mNumVertices; ++i)
+ data.appendNormal(qv3d(m_mesh->mNormals[i]));
+ int k = m_mesh->GetNumUVChannels();
+ for (int t = 0; t < k; ++t)
+ {
+ if (m_mesh->mNumUVComponents[t] != 2)
+ Assimp::DefaultLogger::get()->warn("Tex co-ords only supports U & V");
+ QGLMaterial *m = builder.currentNode()->material();
+ if (m && m->textureUrl().path().endsWith(".dds", Qt::CaseInsensitive))
+ {
+ for (unsigned int i = 0; i < m_mesh->mNumVertices; ++i)
+ data.appendTexCoord(qv2d_inv(m_mesh->mTextureCoords[t][i]), static_cast<QGL::VertexAttribute>(QGL::TextureCoord0 + t));
+ }
+ else
+ {
+ for (unsigned int i = 0; i < m_mesh->mNumVertices; ++i)
+ data.appendTexCoord(qv2d(m_mesh->mTextureCoords[t][i]), static_cast<QGL::VertexAttribute>(QGL::TextureCoord0 + t));
+ }
+ }
+
+ for (unsigned int i = 0; i < m_mesh->mNumFaces; ++i)
+ {
+ aiFace *face = &m_mesh->mFaces[i];
+ data.appendIndices(face->mIndices[0], face->mIndices[1], face->mIndices[2]);
+ }
+
+ // raw triangle mode
+ builder.addTriangles(data);
+}
+
+void QAiMesh::build(QGLBuilder &builder, bool showWarnings)
+{
+ QGLSceneNode *node = builder.currentNode();
+ QString name = node->objectName();
+
+ if (!m_mesh->HasFaces() || !m_mesh->HasPositions())
+ {
+ if (showWarnings)
+ {
+ QString error = QLatin1String("Mesh %1 has zero vertex/face count");
+ error.arg(name.isEmpty() ? QString(QLatin1String("<unnamed mesh>")) : name);
+ Assimp::DefaultLogger::get()->warn(error.toStdString());
+ }
+ return;
+ }
+
+ node->setMaterialIndex(m_mesh->mMaterialIndex);
+ node->palette()->markMaterialAsUsed(m_mesh->mMaterialIndex);
+
+ if (m_mesh->mPrimitiveTypes & aiPrimitiveType_TRIANGLE)
+ loadTriangles(builder);
+ else
+ return; // TODO - lines, points, quads, polygons
+
+ QGLMaterial * mat = node->palette()->material(m_mesh->mMaterialIndex);
+ if (mat->property("isTwoSided").isValid() && mat->property("isTwoSided").toBool())
+ node->setBackMaterialIndex(m_mesh->mMaterialIndex);
+ if (mat->property("isWireFrame").isValid() && mat->property("isWireFrame").toBool())
+ node->setDrawingMode(QGL::Lines);
+}
diff --git a/src/plugins/sceneformats/assimp/qaimesh.h b/src/plugins/sceneformats/assimp/qaimesh.h
new file mode 100644
index 000000000..2a1efc2ed
--- /dev/null
+++ b/src/plugins/sceneformats/assimp/qaimesh.h
@@ -0,0 +1,67 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtQuick3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QGL3DSMESH_H
+#define QGL3DSMESH_H
+
+#include "qaiscenehandler.h"
+#include "qgeometrydata.h"
+
+class QGLMaterialCollection;
+class QGLSceneNode;
+class QGLBuilder;
+class QAiLoader;
+class aiMesh;
+
+class QAiMesh
+{
+public:
+ QAiMesh(aiMesh *mesh);
+ virtual ~QAiMesh();
+
+ void build(QGLBuilder &builder, bool showWarnings = false);
+private:
+ void loadTriangles(QGLBuilder &builder);
+
+ aiMesh *m_mesh;
+};
+
+#endif // QGL3DSMESH_H
diff --git a/src/plugins/sceneformats/assimp/qaiscene.cpp b/src/plugins/sceneformats/assimp/qaiscene.cpp
new file mode 100644
index 000000000..cb67fe99d
--- /dev/null
+++ b/src/plugins/sceneformats/assimp/qaiscene.cpp
@@ -0,0 +1,112 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtQuick3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qaiscene.h"
+#include "qaimesh.h"
+#include "qailoader.h"
+
+#include "qglscenenode.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \internal
+ \class QAiScene
+ \brief The QAiScene class manages and contains an asset importer scene.
+ The scene consists of a QGLSceneNode object which is the top-level node
+ and references the geometry imported from a file.
+*/
+
+/*!
+ \internal
+ Construct a new QAiScene object using the data in the \a scene,
+ and setting the given \a parent.
+
+ The QAiScene object takes ownership of the \a file.
+*/
+QAiScene::QAiScene(const aiScene *scene, QAiSceneHandler *handler)
+ : QGLAbstractScene(0)
+{
+ Q_ASSERT(handler);
+ Q_ASSERT(scene);
+ QAiLoader loader(scene, handler);
+ m_root = loader.loadMeshes();
+}
+
+/*!
+ \reimp
+ Destroy this QAiScene, recovering all resources.
+
+ This method destroys the Lib3dsFile object the scene is based
+ on by calling the appropriate lib3ds function.
+*/
+QAiScene::~QAiScene()
+{
+ // nothing to do here
+}
+
+/*!
+ \internal
+ \reimp
+*/
+QList<QObject *> QAiScene::objects() const
+{
+ QList<QObject *> objs;
+ if (!m_root)
+ return objs;
+ objs.append(m_root);
+ QList<QGLSceneNode*> children = m_root->allChildren();
+ QList<QGLSceneNode*>::const_iterator it = children.constBegin();
+ for ( ; it != children.constEnd(); ++it)
+ objs.append(*it);
+ return objs;
+}
+
+/*!
+ \internal
+ \reimp
+*/
+QGLSceneNode *QAiScene::mainNode() const
+{
+ return m_root;
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/sceneformats/assimp/qaiscene.h b/src/plugins/sceneformats/assimp/qaiscene.h
new file mode 100644
index 000000000..5b9aac58c
--- /dev/null
+++ b/src/plugins/sceneformats/assimp/qaiscene.h
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtQuick3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QGL3DSSCENE_H
+#define QGL3DSSCENE_H
+
+#include "qglabstractscene.h"
+
+#include "aiScene.h"
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Qt3D)
+
+#include <QtCore/qurl.h>
+
+class QGLSceneNode;
+class QAiSceneHandler;
+
+class QAiScene : public QGLAbstractScene
+{
+ Q_OBJECT
+public:
+ explicit QAiScene(const aiScene *scene, QAiSceneHandler *handler);
+ virtual ~QAiScene();
+
+ QList<QObject *> objects() const;
+ QGLSceneNode *mainNode() const;
+private:
+ QGLSceneNode *m_root;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/plugins/sceneformats/assimp/qaiscenehandler.cpp b/src/plugins/sceneformats/assimp/qaiscenehandler.cpp
new file mode 100644
index 000000000..259bf9021
--- /dev/null
+++ b/src/plugins/sceneformats/assimp/qaiscenehandler.cpp
@@ -0,0 +1,286 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtQuick3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qaiscenehandler.h"
+#include "qaiscene.h"
+#include "ailoaderiosystem.h"
+
+#include "aiScene.h"
+#include "aiPostProcess.h"
+#include "DefaultLogger.h"
+
+#include <QtCore/qdir.h>
+#include <QtCore/qdebug.h>
+
+
+#define qAiPostProcessPreset ( \
+ aiProcess_CalcTangentSpace | \
+ aiProcess_GenSmoothNormals | \
+ aiProcess_JoinIdenticalVertices | \
+ aiProcess_ImproveCacheLocality | \
+ aiProcess_LimitBoneWeights | \
+ aiProcess_RemoveRedundantMaterials | \
+ aiProcess_SplitLargeMeshes | \
+ aiProcess_Triangulate | \
+ aiProcess_GenUVCoords | \
+ aiProcess_SortByPType | \
+ aiProcess_FindDegenerates | \
+ aiProcess_FindInvalidData )
+
+QT_BEGIN_NAMESPACE
+
+QAiSceneHandler::QAiSceneHandler()
+ : m_options(qAiPostProcessPreset)
+ , m_showWarnings(false)
+ , m_mayHaveLinesPoints(false)
+ , m_meshSplitVertexLimit(2000)
+ , m_meshSplitTriangleLimit(2000)
+ , m_removeComponentFlags(0)
+ , m_removeSortFlags(0)
+{
+ // by default remove per vertex colors from the data - no-one uses that in
+ // models - if they need it it can be turned on with UseVertexColors
+ m_removeComponentFlags |= aiComponent_COLORS;
+
+ // by default remove points and lines from the model, since these are usually
+ // degenerate structures from bad modelling or bad import/export. if they
+ // are needed it can be turned on with IncludeLinesPoints
+ m_removeSortFlags |= aiPrimitiveType_POINT | aiPrimitiveType_LINE;
+}
+
+QAiSceneHandler::~QAiSceneHandler()
+{
+ // nothing to do
+}
+
+void QAiSceneHandler::decodeOptions(const QString &options)
+{
+ if (options.isEmpty())
+ return;
+
+ // See aiPostProcess.h for aiProcessPreset_TargetRealtime_Quality
+ // - a useful default set of values - its exactly what we want but
+ // wont compile with flags, so redefined with the above macro.
+ // Also, allow the user to override some settings
+ m_options = qAiPostProcessPreset;
+
+ // Has to match the enum
+ static const char *validOptions[] = {
+ "NoOptions",
+ "ShowWarnings",
+ "CalculateNormals",
+ "ForceFaceted",
+ "ForceSmooth",
+ "IncludeAllMaterials",
+ "IncludeLinesPoints",
+ "FixNormals",
+ "DeDupMeshes",
+ "Optimize",
+ "FlipUVs",
+ "FlipWinding",
+ "UseVertexColors",
+ "VertexSplitLimitx2",
+ "TriangleSplitLimitx2",
+ 0
+ };
+
+ QStringList opList = options.simplified().split(QLatin1Char(' '), QString::SkipEmptyParts);
+
+ for (int i = 0; i < opList.count(); ++i)
+ {
+ QString op = opList.at(i);
+ op = op.trimmed();
+ int k = 0;
+ for ( ; validOptions[k]; ++k)
+ if (op == QString::fromLatin1(validOptions[k]))
+ break;
+ if (validOptions[k]) // found
+ {
+ Options o = static_cast<Options>(k);
+ switch (o)
+ {
+ case NoOptions:
+ break;
+ case ShowWarnings:
+ if (m_showWarnings)
+ {
+ m_importer.SetExtraVerbose(true);
+ }
+ else
+ {
+ m_showWarnings = true;
+ m_options |= aiProcess_ValidateDataStructure;
+ }
+ break;
+ case CalculateNormals:
+ m_removeComponentFlags |= aiComponent_NORMALS;
+ m_options |= aiProcess_GenSmoothNormals;
+ m_options &= ~aiProcess_GenNormals;
+ break;
+ case ForceFaceted:
+ m_removeComponentFlags |= aiComponent_NORMALS;
+ m_options |= aiProcess_GenNormals;
+ m_options &= ~aiProcess_GenSmoothNormals;
+ m_options &= ~aiProcess_JoinIdenticalVertices;
+ break;
+ case ForceSmooth:
+ Assimp::DefaultLogger::get()->warn("ForceSmooth is deprecated - ignoring (meshes now smooth by default)");
+ break;
+ case IncludeAllMaterials:
+ m_options &= ~aiProcess_RemoveRedundantMaterials;
+ break;
+ case IncludeLinesPoints:
+ m_removeSortFlags &= ~(aiPrimitiveType_LINE | aiPrimitiveType_POINT);
+ m_mayHaveLinesPoints = true;
+ // leave it with the FindDegenerates option turned on - we want zero
+ // area triangles to display as proper GL lines or points
+ break;
+ case FixNormals:
+ m_options |= aiProcess_FixInfacingNormals;
+ break;
+ case DeDupMeshes:
+ m_options |= aiProcess_FindInstances;
+ break;
+ case Optimize:
+ m_options |= aiProcess_OptimizeGraph | aiProcess_OptimizeMeshes;
+ break;
+ case FlipUVs:
+ m_options |= aiProcess_FlipUVs;
+ break;
+ case FlipWinding:
+ m_options |= aiProcess_FlipWindingOrder;
+ break;
+ case UseVertexColors:
+ m_removeComponentFlags &= ~aiComponent_COLORS;
+ break;
+ case VertexSplitLimitx2:
+ m_meshSplitVertexLimit <<= 1;
+ // repeating this in the option string more than once works...
+ break;
+ case TriangleSplitLimitx2:
+ // ....and we're OK with that, just don't overdo it
+ m_meshSplitTriangleLimit <<= 1;
+ break;
+ }
+ }
+ else
+ {
+ qWarning("Bad option: \"%s\" in %s", qPrintable(op),
+ qPrintable(options));
+ }
+ }
+}
+
+QGLAbstractScene *QAiSceneHandler::read()
+{
+ AiLoaderIOSystem *ios = new AiLoaderIOSystem(device(), url());
+ m_importer.SetIOHandler(ios);
+
+ 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);
+ }
+
+ QString path;
+ QUrl u = url();
+ if (u.scheme() != QLatin1String("file"))
+ {
+ qWarning("Non-file URL's not yet supported");
+ return 0;
+ }
+ path = u.toLocalFile();
+
+ 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);
+
+ // the importer owns the scene, so when the it goes out of scope on exiting
+ // this function the scene will get destroyed
+ 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));
+ return 0;
+ }
+
+
+ QAiScene *qscene = new QAiScene(scene, this);
+
+ Assimp::DefaultLogger::kill();
+
+ return qscene;
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/sceneformats/assimp/qaiscenehandler.h b/src/plugins/sceneformats/assimp/qaiscenehandler.h
new file mode 100644
index 000000000..95b800025
--- /dev/null
+++ b/src/plugins/sceneformats/assimp/qaiscenehandler.h
@@ -0,0 +1,108 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtQuick3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QGL3DSSCENEHANDLER_H
+#define QGL3DSSCENEHANDLER_H
+
+#include "qglsceneformatplugin.h"
+
+#include "aiPostProcess.h"
+#include "assimp.hpp"
+
+#include <QtCore/qurl.h>
+
+Q_DECLARE_FLAGS(aiPostProcessFlags, aiPostProcessSteps);
+Q_DECLARE_OPERATORS_FOR_FLAGS(aiPostProcessFlags);
+
+
+QT_BEGIN_NAMESPACE
+
+class QIODevice;
+
+class QAiSceneHandler : public QGLSceneFormatHandler
+{
+public:
+ enum Options {
+ NoOptions,
+ ShowWarnings, // show any warnings while loading the file
+ CalculateNormals, // replace normals from the file with smooth generated ones
+ ForceFaceted, // generate non-smooth normals (implies CalculateNormals)
+ ForceSmooth, // deprecated - retained only for backward compatibility
+ IncludeAllMaterials, // include even redundant (unused) materials
+ IncludeLinesPoints, // include even collapsed triangles (lines or points)
+ FixNormals, // try to fix incorrect (in facing) normals
+ DeDupMeshes, // replace copied meshes with refs to a single instance
+ Optimize, // collapse meshes, nodes & scene heierarchies
+ FlipUVs, // flips UV's on the y-axis (for upside-down textures)
+ FlipWinding, // makes faces CW instead of CCW
+ UseVertexColors, // use vertex colors that are in a model
+ VertexSplitLimitx2, // double the vertex count which will split a large mesh
+ TriangleSplitLimitx2 // double the triangle count which will split a large mesh
+ };
+
+ QAiSceneHandler();
+ ~QAiSceneHandler();
+
+ QGLAbstractScene *read();
+
+ void decodeOptions(const QString &options);
+
+ bool showWarnings() const { return m_showWarnings; }
+ bool mayHaveLinesPoints() const { return m_mayHaveLinesPoints; }
+
+ aiPostProcessFlags options() const { return m_options; }
+ quint32 removeComponentFlags() const { return m_removeComponentFlags; }
+ quint32 removeSortFlags() const { return m_removeSortFlags; }
+
+private:
+ aiPostProcessFlags m_options;
+ bool m_showWarnings;
+ bool m_mayHaveLinesPoints;
+ int m_meshSplitVertexLimit;
+ int m_meshSplitTriangleLimit;
+ Assimp::Importer m_importer;
+ quint32 m_removeComponentFlags;
+ quint32 m_removeSortFlags;
+};
+
+QT_END_NAMESPACE
+
+#endif