diff options
Diffstat (limited to 'src/plugins/sceneformats/assimp/qaiscenehandler.cpp')
-rw-r--r-- | src/plugins/sceneformats/assimp/qaiscenehandler.cpp | 286 |
1 files changed, 286 insertions, 0 deletions
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 |