diff options
Diffstat (limited to 'src/render/io/gltfparser.cpp')
-rw-r--r-- | src/render/io/gltfparser.cpp | 1110 |
1 files changed, 0 insertions, 1110 deletions
diff --git a/src/render/io/gltfparser.cpp b/src/render/io/gltfparser.cpp deleted file mode 100644 index 65c800fb0..000000000 --- a/src/render/io/gltfparser.cpp +++ /dev/null @@ -1,1110 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB). -** Copyright (C) 2015 The Qt Company Ltd and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the Qt3D module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL3$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPLv3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or later as published by the Free -** Software Foundation and appearing in the file LICENSE.GPL included in -** the packaging of this file. Please review the following information to -** ensure the GNU General Public License version 2.0 requirements will be -** met: http://www.gnu.org/licenses/gpl-2.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "gltfparser_p.h" - -#include "texturedata.h" -#include <Qt3DRenderer/private/renderlogging_p.h> - -#include <Qt3DCore/qentity.h> -#include <qabstractmesh.h> -#include <qmaterial.h> -#include <qtechnique.h> -#include <qshaderprogram.h> -#include <qeffect.h> -#include <Qt3DCore/qcamera.h> -#include <Qt3DCore/qtransform.h> -#include <Qt3DCore/qmatrixtransform.h> -#include <Qt3DCore/qcameralens.h> -#include <Qt3DCore/private/qurlhelper_p.h> -#include <qtexture.h> -#include <qparameter.h> - -#include <QJsonDocument> -#include <QJsonObject> -#include <QJsonArray> -#include <QFile> -#include <QDir> -#include <QFileInfo> -#include <QQuaternion> -#include <QMatrix4x4> -#include <QColor> -#include <QVector2D> -#include <QVector3D> -#include <QUrl> - -// need to move these to somewhere common? -#include <Qt3DRenderer/private/renderstate_p.h> -#include <Qt3DRenderer/private/blendstate_p.h> -#include <private/qabstractmesh_p.h> - -QT_BEGIN_NAMESPACE - -namespace Qt3D { -namespace { - -const QString KEY_CAMERA = QStringLiteral("camera"); -const QString KEY_CAMERAS = QStringLiteral("cameras"); -const QString KEY_SCENES = QStringLiteral("scenes"); -const QString KEY_NODES = QStringLiteral("nodes"); -const QString KEY_MESHES = QStringLiteral("meshes"); -const QString KEY_CHILDREN = QStringLiteral("children"); -const QString KEY_MATRIX = QStringLiteral("matrix"); -const QString KEY_TYPE = QStringLiteral("type"); -const QString KEY_PERSPECTIVE =QStringLiteral("perspective"); -const QString KEY_NAME = QStringLiteral("name"); -const QString KEY_COUNT = QStringLiteral("count"); -const QString KEY_YFOV = QStringLiteral("yfov"); -const QString KEY_ZNEAR = QStringLiteral("znear"); -const QString KEY_ZFAR = QStringLiteral("zfar"); -const QString KEY_MATERIALS = QStringLiteral("materials"); -const QString KEY_TECHNIQUE = QStringLiteral("technique"); -const QString KEY_VALUES = QStringLiteral("values"); -const QString KEY_BUFFERS = QStringLiteral("buffers"); -const QString KEY_SHADERS = QStringLiteral("shaders"); -const QString KEY_PROGRAMS = QStringLiteral("programs"); -const QString KEY_PROGRAM = QStringLiteral("program"); -const QString KEY_TECHNIQUES = QStringLiteral("techniques"); -const QString KEY_ACCESSORS = QStringLiteral("accessors"); -const QString KEY_IMAGES = QStringLiteral("images"); -const QString KEY_TEXTURES = QStringLiteral("textures"); -const QString KEY_SCENE = QStringLiteral("scene"); -const QString KEY_BUFFER = QStringLiteral("buffer"); -const QString KEY_TARGET = QStringLiteral("target"); -const QString KEY_BYTE_OFFSET = QStringLiteral("byteOffset"); -const QString KEY_BYTE_LENGTH = QStringLiteral("byteLength"); -const QString KEY_BYTE_STRIDE = QStringLiteral("byteStride"); -const QString KEY_PRIMITIVES = QStringLiteral("primitives"); -const QString KEY_PRIMITIVE = QStringLiteral("primitive"); -const QString KEY_MATERIAL = QStringLiteral("material"); -const QString KEY_ATTRIBUTES = QStringLiteral("attributes"); -const QString KEY_INDICES = QStringLiteral("indices"); -const QString KEY_PATH = QStringLiteral("path"); -const QString KEY_FORMAT = QStringLiteral("format"); -const QString KEY_PASSES = QStringLiteral("passes"); -const QString KEY_SOURCE = QStringLiteral("source"); -const QString KEY_SAMPLER = QStringLiteral("sampler"); -const QString KEY_SAMPLERS = QStringLiteral("samplers"); -const QString KEY_LENGTH = QStringLiteral("length"); -const QString KEY_SEMANTIC = QStringLiteral("semantic"); -const QString KEY_STATES = QStringLiteral("states"); -const QString KEY_UNIFORMS = QStringLiteral("uniforms"); -const QString KEY_PARAMETERS = QStringLiteral("parameters"); -const QString KEY_WRAP_S = QStringLiteral("wrapS"); -const QString KEY_MIN_FILTER = QStringLiteral("minFilter"); -const QString KEY_MAG_FILTER = QStringLiteral("magFilter"); - -const QString KEY_INSTANCE_TECHNIQUE = QStringLiteral("instanceTechnique"); -const QString KEY_INSTANCE_PROGRAM = QStringLiteral("instanceProgram"); -const QString KEY_BUFFER_VIEWS = QStringLiteral("bufferViews"); -const QString KEY_BUFFER_VIEW = QStringLiteral("bufferView"); -const QString KEY_VERTEX_SHADER = QStringLiteral("vertexShader"); -const QString KEY_FRAGMENT_SHADER = QStringLiteral("fragmentShader"); -const QString KEY_INTERNAL_FORMAT = QStringLiteral("internalFormat"); - -//Parameter::StandardUniform parseSemanticName(const QByteArray& s) -//{ -// if (s == "MODEL") return Parameter::ModelMatrix; -// if (s == "VIEW") return Parameter::ViewMatrix; -// if (s == "PROJECTION") return Parameter::ProjectionMatrix; -// if (s == "MODELVIEW") return Parameter::ModelView; -// if (s == "MODELVIEWPROJECTION") -// return Parameter::ModelViewProjection; - -// if (s == "MODELINVERSE") return Parameter::ModelInverse; -// if (s == "VIEWINVERSE") return Parameter::ViewInverse; -// if (s == "PROJECTIONINVERSE") -// return Parameter::ProjectionInverse; -// if (s == "MODELVIEWINVERSE") -// return Parameter::ModelViewInverse; -// if (s == "MODELVIEWPROJECTIONINVERSE") -// return Parameter::ModelViewProjectionInverse; - -// if (s == "MODELINVERSETRANSPOSE") -// return Parameter::ModelNormal; -// if (s == "MODELVIEWINVERSETRANSPOSE") -// return Parameter::ModelViewNormal; - -// return Parameter::None; -//} - -//QParameter::OpenGLTypes parseType(const QByteArray &s) -//{ -// if (s == "BYTE") return QParameter::Undefined; -// if (s == "BYTE_VEC2") return QParameter::Undefined; -// if (s == "BYTE_VEC3") return QParameter::Undefined; -// if (s == "BYTE_VEC4") return QParameter::Undefined; -// if (s == "UNSIGNED_BYTE") return QParameter::Undefined; -// if (s == "UNSIGNED_BYTE_VEC2") return QParameter::Undefined; -// if (s == "UNSIGNED_BYTE_VEC3") return QParameter::Undefined; -// if (s == "UNSIGNED_BYTE_VEC4") return QParameter::Undefined; -// if (s == "SHORT") return QParameter::Undefined; -// if (s == "SHORT_VEC2") return QParameter::Undefined; -// if (s == "SHORT_VEC3") return QParameter::Undefined; -// if (s == "SHORT_VEC4") return QParameter::Undefined; -// if (s == "UNSIGNED_SHORT") return QParameter::Undefined; -// if (s == "UNSIGNED_SHORT_VEC2") return QParameter::Undefined; -// if (s == "UNSIGNED_SHORT_VEC3") return QParameter::Undefined; -// if (s == "UNSIGNED_SHORT_VEC4") return QParameter::Undefined; -// if (s == "FLOAT") return QParameter::Float; -// if (s == "FLOAT_VEC2") return QParameter::FloatVec2; -// if (s == "FLOAT_VEC3") return QParameter::FloatVec3; -// if (s == "FLOAT_VEC4") return QParameter::FloatVec4; -// if (s == "FLOAT_MAT2") return QParameter::FloatMat2; -// if (s == "FLOAT_MAT2") return QParameter::FloatMat3; -// if (s == "FLOAT_MAT2") return QParameter::FloatMat4; -// if (s == "INT") return QParameter::Int; -// if (s == "INT_VEC2") return QParameter::IntVec2; -// if (s == "INT_VEC3") return QParameter::IntVec3; -// if (s == "INT_VEC4") return QParameter::IntVec4; -// if (s == "BOOL") return QParameter::Bool; -// if (s == "BOOL_VEC2") return QParameter::BoolVec2; -// if (s == "BOOL_VEC3") return QParameter::BoolVec3; -// if (s == "BOOL_VEC4") return QParameter::BoolVec4; - -// return QParameter::Undefined; -//} - -QAbstractAttribute::DataType typeFromGLType(GLint dataType, uint &dataCount) -{ - switch (dataType) { - - case GL_UNSIGNED_SHORT: - dataCount = 1; - return QAbstractAttribute::UnsignedShort; - - case GL_UNSIGNED_BYTE: - dataCount = 1; - return QAbstractAttribute::UnsignedByte; - - case GL_UNSIGNED_INT: - dataCount = 1; - return QAbstractAttribute::UnsignedInt; - - case GL_SHORT: - dataCount = 1; - return QAbstractAttribute::Short; - - case GL_BYTE: - dataCount = 1; - return QAbstractAttribute::Byte; - - case GL_INT: - dataCount = 1; - return QAbstractAttribute::Int; - - case GL_FLOAT: - dataCount = 1; - break; - - case GL_FLOAT_VEC2: - dataCount = 2; - break; - - case GL_FLOAT_VEC3: - dataCount = 3; - break; - - case GL_FLOAT_VEC4: - dataCount = 4; - break; - -// TO DO: Handle doubles - - default: - Q_UNREACHABLE(); - } - - return QAbstractAttribute::Float; -} - -} // of anonymous namespace - -class GLTFParserMeshPrivate; - -class GLTFParserMeshFunctor : public QAbstractMeshFunctor -{ -public: - explicit GLTFParserMeshFunctor(QMeshDataPtr meshData = QMeshDataPtr()); - QMeshDataPtr operator ()() Q_DECL_OVERRIDE; - bool operator ==(const QAbstractMeshFunctor &other) const Q_DECL_OVERRIDE; - QT3D_FUNCTOR(GLTFParserMeshFunctor) -private: - QMeshDataPtr m_meshData; -}; - -class GLTFParserMesh : public QAbstractMesh -{ - Q_OBJECT -public: - explicit GLTFParserMesh(QNode *parent = 0); - - void setData(QMeshDataPtr data); - QAbstractMeshFunctorPtr meshFunctor() const Q_DECL_FINAL; - -protected: - void copy(const QNode *ref) Q_DECL_FINAL; - -private: - QT3D_CLONEABLE(GLTFParserMesh) - Q_DECLARE_PRIVATE(GLTFParserMesh) -}; - -class GLTFParserMeshPrivate : public QAbstractMeshPrivate -{ -public: - GLTFParserMeshPrivate() - : QAbstractMeshPrivate() - {} - - Q_DECLARE_PUBLIC(GLTFParserMesh) - QMeshDataPtr m_meshData; -}; - -GLTFParser::GLTFParser() : AbstractSceneParser(), - m_parseDone(false) -{ -} - -bool GLTFParser::isGLTFPath(const QString& path) -{ - QFileInfo finfo(path); - if (!finfo.exists()) - return false; - - // might need to detect other things in the future, but would - // prefer to avoid doing a full parse. - return (finfo.suffix().toLower() == QStringLiteral("json")); -} - -void GLTFParser::setBasePath(const QString& path) -{ - m_basePath = path; -} - -bool GLTFParser::setJSON( QJsonDocument json ) -{ - if ( !json.isObject() ) { - return false; - } - - m_json = json; - m_parseDone = false; - - m_meshDict.clear(); - m_attributeDict.clear(); - m_defaultScene.clear(); - - return true; -} - -/*! - * Sets the \a path used by the parser to load the scene file. - * If the file is valid, parsing is automatically triggered. - */ -void GLTFParser::setSource(const QUrl &source) -{ - const QString path = QUrlHelper::urlToLocalFileOrQrc(source); - QFileInfo finfo(path); - if (!finfo.exists()) { - qWarning() << "missing file:" << path; - return; - } - QFile f(path); - f.open(QIODevice::ReadOnly); - - if (!setJSON(QJsonDocument::fromJson(f.readAll()))) { - qWarning() << "not a JSON document"; - return; - } - - setBasePath(finfo.dir().absolutePath()); -} - -/*! - * Returns true if the extension of \a path is supported by the - * GLTF parser. - */ -bool GLTFParser::isExtensionSupported(const QUrl &source) const -{ - const QString path = QUrlHelper::urlToLocalFileOrQrc(source); - return GLTFParser::isGLTFPath(path); -} - -QMeshDataPtr GLTFParser::mesh(const QString &id) -{ - parse(); - if (m_meshDict.contains(id)) - return m_meshDict.value(id); - - qWarning() << "Unknown mesh" << id << "in GLTF file" << m_basePath; - return QMeshDataPtr(); -} - -QEntity* GLTFParser::defaultScene() -{ - parse(); - if (m_defaultScene.isEmpty()) { - qWarning() << Q_FUNC_INFO << "no default scene"; - return NULL; - } - - return scene(m_defaultScene); -} - -QEntity* GLTFParser::scene(const QString &id) -{ - parse(); - - QJsonObject scenes = m_json.object().value(KEY_SCENES).toObject(); - if (!scenes.contains(id)) { - qWarning() << "GLTF: no such scene" << id << "in file" << m_basePath; - return defaultScene(); - } - - QJsonObject sceneObj = scenes.value(id).toObject(); - QEntity* sceneEntity = new QEntity; - foreach (QJsonValue nnv, sceneObj.value(KEY_NODES).toArray()) { - QString nodeName = nnv.toString(); - QEntity* child = node(nodeName); - if (!child) - continue; - child->setParent(sceneEntity); - } - - return sceneEntity; -} - -QEntity* GLTFParser::node(const QString &id) -{ - QJsonObject nodes = m_json.object().value(KEY_NODES).toObject(); - if (!nodes.contains(id)) { - qWarning() << "unknown node" << id << "in GLTF file" << m_basePath; - return NULL; - } - - QJsonObject jsonObj = nodes.value(id).toObject(); - QEntity* result( new QEntity ); - parse(); - - if ( jsonObj.contains(KEY_CHILDREN) ) - { - foreach (QJsonValue c, jsonObj.value(KEY_CHILDREN).toArray()) { - QEntity* child = node(c.toString()); - if (!child) - continue; - child->setParent(result); - } - } - - if ( jsonObj.contains(KEY_MESHES) ) - { - typedef QList<GLTFParserMesh *> MeshList; - QMap<QString, MeshList> materialDict; - - foreach (QJsonValue m, jsonObj.value(KEY_MESHES).toArray()) - { - if (!m_meshDict.contains(m.toString())) { - qWarning() << "node" << id << "references unknown mesh" << m.toString(); - continue; - } - - foreach (QMeshDataPtr md, m_meshDict.values(m.toString())) { - QString matId = m_meshMaterialDict[md.data()]; - GLTFParserMesh* meshComp = new GLTFParserMesh; - meshComp->setData(md); - materialDict[matId].append(meshComp); - } - } - - if (materialDict.size() == 1) { - // common case - result->addComponent(material(materialDict.firstKey())); - foreach (GLTFParserMesh* m, materialDict.first()) - result->addComponent(m); - } else { - // need to make a child entity per material - foreach (QString matId, materialDict.keys()) { - QEntity* subEntity(new QEntity); - subEntity->setParent(result); - - subEntity->addComponent(material(matId)); - foreach (GLTFParserMesh* m, materialDict.value(matId)) - subEntity->addComponent(m); - } // of distinct material iteration - } // of multiple materials case - } - - processName(jsonObj, result); - - if ( jsonObj.contains(KEY_MATRIX) ) - { - QMatrix4x4 m(Qt::Uninitialized); - - QJsonArray matrixValues = jsonObj.value(KEY_MATRIX).toArray(); - for (int i=0; i<16; ++i) { - double v = matrixValues.at( i ).toDouble(); - m(i % 4, i >> 2) = v; - } - - // ADD MATRIX TRANSFORM COMPONENT TO ENTITY - QTransform *trans = new QTransform(); - trans->addTransform(new QMatrixTransform(m)); - result->addComponent(trans); - } - - if ( jsonObj.contains(KEY_CAMERA) ) - { - QCameraLens* cam = camera( jsonObj.value(KEY_CAMERA).toString() ); - if (!cam) { - qWarning() << "failed to build camera:" << jsonObj.value(KEY_CAMERA) - << "on node" << id; - } else { - result->addComponent(cam); - } - } // of have camera attribute - - return result; -} - -// Get rid of miniwindef.h clobbering legal variable names -#if defined(near) -#undef near -#endif - -#if defined(far) -#undef far -#endif - -QCameraLens* GLTFParser::camera(const QString &id) -{ - parse(); - QJsonObject cams = m_json.object().value(KEY_CAMERAS).toObject(); - if (!cams.contains(id)) { - qWarning() << "unknown camera" << id << "in GLTF file" << m_basePath; - return Q_NULLPTR; - } - - QJsonObject jsonObj = cams.value(id).toObject(); - QByteArray camTy = jsonObj.value(KEY_TYPE).toString().toUtf8(); - - if (camTy == "perspective") { - if (!jsonObj.contains(KEY_PERSPECTIVE)) { - qWarning() << "camera:" << id << "missing 'perspective' object"; - return Q_NULLPTR; - } - - QJsonObject pObj = jsonObj.value(KEY_PERSPECTIVE).toObject(); - double yfov = pObj.value(KEY_YFOV).toDouble(); - double near = pObj.value(KEY_ZNEAR).toDouble(); - double far = pObj.value(KEY_ZFAR).toDouble(); - - QCameraLens* result = new QCameraLens; - result->setPerspectiveProjection(yfov, 1.0, near, far); - return result; - } else if (camTy == "orthographic") { - qWarning() << Q_FUNC_INFO << "implement me"; - - return Q_NULLPTR; - } else { - qWarning() << "camera:" << id << "has unsupported type:" << camTy; - return Q_NULLPTR; - } -} - -QMaterial* GLTFParser::material(const QString &id) -{ - parse(); - - if (m_materialCache.contains(id)) - return m_materialCache.value(id); - - QJsonObject mats = m_json.object().value(KEY_MATERIALS).toObject(); - if (!mats.contains(id)) { - qWarning() << "unknown material" << id << "in GLTF file" << m_basePath; - return NULL; - } - - QJsonObject jsonObj = mats.value(id).toObject(); - - QJsonObject tech = jsonObj.value(KEY_INSTANCE_TECHNIQUE).toObject(); - QString tname = tech.value(KEY_TECHNIQUE).toString(); - if (!m_techniques.contains(tname)) { - qWarning() << "unknown technique" << tname << - "for material" << id << "in GLTF file" << m_basePath; - return NULL; - } - - QTechnique *technique = m_techniques.value(tname); - if (!m_effectProxies.contains(tname)) { - QEffect* eff = new QEffect; - eff->setObjectName(tname); - eff->addTechnique(technique); - m_effectProxies[tname] = eff; - } - - QMaterial* mat = new QMaterial; - mat->setEffect(m_effectProxies[tname]); - - processName(jsonObj, mat); - -// QJsonObject values = tech.value(KEY_VALUES).toObject(); -// foreach (QString vName, values.keys()) { -// QParameter* param = technique->parameterForName(vName); -// if (!param) { -// qWarning() << "unknown parameter:" << vName << "in technique" << tname -// << "processing material" << id; -// continue; -// } - -// if (param->isTextureType()) { -// QString textureId = values.value(vName).toString(); -// if (!m_textures.contains(textureId)) { -// qWarning() << "unknown texture" << textureId << "for parameter" << vName -// << "of material" << id; -// } else { -// mat->setTextureParameter(vName, m_textures.value(textureId)); -// } -// } else { -// // QVariant var = parameterValueFromJSON(param, values.value(vName)); -// mat->addParameter(param); -// } -// } // of material technique-instance values iteration - - m_materialCache[id] = mat; - return mat; -} - -void GLTFParser::parse() -{ - if (m_parseDone) - return; - - QJsonObject buffers = m_json.object().value(KEY_BUFFERS).toObject(); - foreach (QString nm, buffers.keys()) { - processJSONBuffer( nm, buffers.value(nm).toObject() ); - } - - QJsonObject views = m_json.object().value(KEY_BUFFER_VIEWS).toObject(); - foreach (QString nm, views.keys()) { - processJSONBufferView( nm, views.value(nm).toObject() ); - } - - QJsonObject shaders = m_json.object().value(KEY_SHADERS).toObject(); - foreach (QString nm, shaders.keys()) { - processJSONShader( nm, shaders.value(nm).toObject() ); - } - - QJsonObject programs = m_json.object().value(KEY_PROGRAMS).toObject(); - foreach (QString nm, programs.keys()) { - processJSONProgram( nm, programs.value(nm).toObject() ); - } - - QJsonObject techniques = m_json.object().value(KEY_TECHNIQUES).toObject(); - foreach (QString nm, techniques.keys()) { - processJSONTechnique( nm, techniques.value(nm).toObject() ); - } - - QJsonObject attrs = m_json.object().value(KEY_ACCESSORS).toObject(); - foreach (QString nm, attrs.keys()) { - processJSONAccessor( nm, attrs.value(nm).toObject() ); - } - - QJsonObject meshes = m_json.object().value(KEY_MESHES).toObject(); - foreach (QString nm, meshes.keys()) { - processJSONMesh( nm, meshes.value(nm).toObject() ); - } - - QJsonObject images = m_json.object().value(KEY_IMAGES).toObject(); - foreach (QString nm, images.keys()) { - processJSONImage( nm, images.value(nm).toObject() ); - } - - QJsonObject textures = m_json.object().value(KEY_TEXTURES).toObject(); - foreach (QString nm, textures.keys()) { - processJSONTexture(nm, textures.value(nm).toObject() ); - } - - m_defaultScene = m_json.object().value(KEY_SCENE).toString(); - m_parseDone = true; -} - -void GLTFParser::processJSONBuffer( QString id, const QJsonObject& json ) -{ - // simply cache buffers for lookup by buffer-views - m_bufferDatas[id] = BufferData(json); -} - -void GLTFParser::processJSONBufferView( QString id, const QJsonObject& json ) -{ - QString bufName = json.value(KEY_BUFFER).toString(); - if (!m_bufferDatas.contains(bufName)) { - qWarning() << "unknown buffer:" << bufName << "processing view:" << id; - return; - } - - int target = json.value(KEY_TARGET).toInt(); - QBuffer::BufferType ty(QBuffer::VertexBuffer); - - switch (target) { - case GL_ARRAY_BUFFER: ty = QBuffer::VertexBuffer; break; - case GL_ELEMENT_ARRAY_BUFFER: ty = QBuffer::IndexBuffer; break; - default: - qWarning() << Q_FUNC_INFO << "buffer" << id << "unsupported target:" << target; - return; - } - - quint64 offset = 0; - if (json.contains(KEY_BYTE_OFFSET)) { - offset = json.value(KEY_BYTE_OFFSET).toInt(); - qCDebug(Render::Io) << "bv:" << id << "has offset:" << offset; - } - - quint64 len = json.value(KEY_BYTE_LENGTH).toInt(); - QFile* f = resolveLocalData(m_bufferDatas[bufName].path); - if (!f->seek(offset)) { - qWarning() << "failed to seek to offset in file for bufferView:" << id << offset; - } - - QByteArray bytes = f->read(len); - if (bytes.count() != (int) len) { - qWarning() << "failed to read sufficient bytes from:" << m_bufferDatas[bufName].path - << "for view" << id; - } - delete f; - - QBuffer *b(new QBuffer(ty)); - b->setData(bytes); - m_buffers[id] = b; -} - -void GLTFParser::processJSONAccessor( QString id, const QJsonObject& json ) -{ - QString bvName = json.value(KEY_BUFFER_VIEW).toString(); - if (!m_buffers.contains(bvName)) { - qWarning() << "unknown buffer-view:" << bvName << "processing accessor:" << id; - return; - } - - QBuffer *buf = m_buffers.value(bvName); - int offset = 0, stride = 0; - int type = json.value(KEY_TYPE).toInt(); - int count = json.value(KEY_COUNT).toInt(); - - if ( json.contains(KEY_BYTE_OFFSET)) - offset = json.value(KEY_BYTE_OFFSET).toInt(); - if ( json.contains(KEY_BYTE_STRIDE)) - stride = json.value(KEY_BYTE_STRIDE).toInt(); - - uint dataSize = 0; - QAttribute::DataType dataType = typeFromGLType(type, dataSize); - - QAttribute *attr( new QAttribute( buf, dataType, dataSize, count, offset, stride ) ); - m_attributeDict[id] = attr; -} - -void GLTFParser::processJSONMesh( QString id, QJsonObject jsonObj ) -{ - QJsonArray primsArray = jsonObj.value(KEY_PRIMITIVES).toArray(); - Q_FOREACH (QJsonValue primVal, primsArray) { - QJsonObject primObj = primVal.toObject(); - int type = primObj.value(KEY_PRIMITIVE).toInt(); - QString material = primObj.value(KEY_MATERIAL).toString(); - - if ( material.isEmpty()) { - qCWarning(Render::Io) << "malformed primitive on " << id << ", missing material value" - << material; - continue; - } - - QMeshDataPtr md(new QMeshData(static_cast<QMeshData::PrimitiveType>(type))); - m_meshMaterialDict[md.data()] = material; - - QJsonObject attrs = primObj.value(KEY_ATTRIBUTES).toObject(); - Q_FOREACH (QString attrName, attrs.keys()) { - QString k = attrs.value(attrName).toString(); - if (!m_attributeDict.contains(k)) { - qCWarning(Render::Io) << "unknown attribute accessor:" << k << "on mesh" << id; - continue; - } - - md->addAttribute(attrName, m_attributeDict[k]); - - // qCDebug(Render::rIo) << "DUMP of:" << attrName; - // m_attributeDict[k]->dump(20); - } - - if ( primObj.contains(KEY_INDICES)) { - QString k = primObj.value(KEY_INDICES).toString(); - if (!m_attributeDict.contains(k)) { - qCWarning(Render::Io) << "unknown index accessor:" << k << "on mesh" << id; - } else { - md->setIndexAttribute(m_attributeDict[k]); - // m_attributeDict[k]->dump(100); - } - } // of has indices - - m_meshDict.insert( id, md ); - } // of primitives iteration -} - -void GLTFParser::processName(const QJsonObject &json, QObject *ins) -{ - if ( json.contains(KEY_NAME) ) - { - ins->setObjectName( json.value(KEY_NAME).toString() ); - } -} - -void GLTFParser::processJSONProgram( QString id, QJsonObject jsonObj) -{ - QShaderProgram* prog = new QShaderProgram; - prog->setObjectName(id); - - QString fragName = jsonObj.value(KEY_FRAGMENT_SHADER).toString(), - vertName = jsonObj.value(KEY_VERTEX_SHADER).toString(); - if (!m_shaderPaths.contains(fragName) || !m_shaderPaths.contains(vertName)) { - qCWarning(Render::Io) << Q_FUNC_INFO << "program:" << id << "missing shader:" << - fragName << vertName; - return; - } - - prog->setFragmentShaderCode(Qt3D::QShaderProgram::loadSource(QUrl(m_shaderPaths[fragName]))); - prog->setVertexShaderCode(Qt3D::QShaderProgram::loadSource(QUrl(m_shaderPaths[vertName]))); - m_programs[id] = prog; -} - -void GLTFParser::processJSONShader( QString id, QJsonObject jsonObj) -{ - // shaders are trivial for the moment, defer the real work - // to the program section - QString path = jsonObj.value(KEY_PATH).toString(); - - QFileInfo info(m_basePath, path); - if (!info.exists()) { - qCWarning(Render::Io) << "can't find shader" << id << "from path" << path; - return; - } - - m_shaderPaths[id] = info.absoluteFilePath(); -} - -void GLTFParser::processJSONImage( QString id, QJsonObject jsonObj) -{ - QString path = jsonObj.value(KEY_PATH).toString(); - QFileInfo info(m_basePath, path); - if (!info.exists()) { - qCWarning(Render::Io)<< "can't find image" << id << "from path" << path; - return; - } - - QImage img(info.absoluteFilePath()); - if (img.isNull()) { - qCWarning(Render::Io) << "failed to load image:" << info.absoluteFilePath(); - return; - } - - m_images[id] = img; -} - -void GLTFParser::processJSONTexture( QString id, QJsonObject jsonObj) -{ - Q_UNUSED(id); - Q_UNUSED(jsonObj); -// int target = jsonObj.value(KEY_TARGET).toInt(); -// QAbstractTextureProvider* tex = new QAbstractTextureProvider(static_cast<QAbstractTextureProvider::Target>(target)); - - -// // TODO: Choose suitable internal format - may vary on OpenGL context type -// //int pixelFormat = jsonObj.value(KEY_FORMAT).toInt(); -// //int internalFormat = jsonObj.value(KEY_INTERNAL_FORMAT).toInt(); - -// tex->setFormat(QAbstractTextureProvider::RGBA8_UNorm /* static_cast<QOpenGLTexture::TextureFormat>(internalFormat)*/); - -// QString samplerId = jsonObj.value(KEY_SAMPLER).toString(); -// QString source = jsonObj.value(KEY_SOURCE).toString(); -// if (!m_images.contains(source)) { -// qCWarning(Render::Io) << "texture" << id << "references missing image" << source; -// return; -// } - -// tex->setFromQImage(m_images[source]); - -// QJsonObject samplersDict(m_json.object().value(KEY_SAMPLERS).toObject()); -// if (!samplersDict.contains(samplerId)) { -// qCWarning(Render::Io) << "texture" << id << "references unknown sampler" << samplerId; -// return; -// } - -// QJsonObject sampler = samplersDict.value(samplerId).toObject(); - -// tex->setWrapMode(QTextureWrapMode(static_cast<QTextureWrapMode::WrapMode>(sampler.value(KEY_WRAP_S).toInt()))); -// tex->setMinificationFilter(static_cast<QAbstractTextureProvider::Filter>(sampler.value(KEY_MIN_FILTER).toInt())); -// tex->setMagnificationFilter(static_cast<QAbstractTextureProvider::Filter>(sampler.value(KEY_MAG_FILTER).toInt())); - -// m_textures[id] = tex; -} - -void GLTFParser::processJSONTechnique( QString id, QJsonObject jsonObj ) -{ - QTechnique *t = new QTechnique; - t->setObjectName(id); - - QHash<QString, QParameter*> paramDict; - QJsonObject params = jsonObj.value(KEY_PARAMETERS).toObject(); - Q_FOREACH (QString pname, params.keys()) { - QJsonObject po = params.value(pname).toObject(); - - // int dataType = po.value(KEY_TYPE).toInt(); - QString semantic = po.value(KEY_SEMANTIC).toString(); - // The Standard has changed, it doesn't return the raw int value for a type - // But a string -// QParameter* p = new QParameter(pname, parseType(po.value(KEY_TYPE).toString().toUtf8()), t); -// Parameter::StandardUniform su = parseSemanticName(semantic.toUtf8()); -// if (su != Parameter::None) { -// p->setStandardUniform(su); -// } else { -// // should really verify it's an attribute parameter? -// // but what would be the way to do that? -// // check the accessor dict? -// p->setMeshAttributeName(semantic); -// } - -// t->addParameter(p); - -// paramDict[pname] = p; - } // of parameters iteration - - QJsonObject passes = jsonObj.value(KEY_PASSES).toObject(); - Q_FOREACH (QString pname, passes.keys()) { - QJsonObject po = passes.value(pname).toObject(); - QJsonObject ip = po.value(KEY_INSTANCE_PROGRAM).toObject(); - - QString programName = ip.value(KEY_PROGRAM).toString(); - if (!m_programs.contains(programName)) { - qWarning() << Q_FUNC_INFO << "technique" << id << "pass" << pname - << ": missing program" << programName; - continue; - } - - QRenderPass* pass = new QRenderPass; - pass->setShaderProgram(m_programs[programName]); - - QJsonObject attrs = ip.value(KEY_ATTRIBUTES).toObject(); - Q_FOREACH ( QString attrName, attrs.keys() ) { - QString pname = attrs.value(attrName).toString(); - // TO DO : Correct that - // pass->addAttributeBinding(paramDict[pname], attrName); - } // of program-instance attributes - - QJsonObject uniforms = ip.value(KEY_UNIFORMS).toObject(); - Q_FOREACH (QString uniformName, uniforms.keys()) { - QString pname = uniforms.value(uniformName).toString(); - // TO DO : Correct that - // pass->addUniformBinding(paramDict[pname], uniformName); - } // of program-instance attributes - - // TODO: Use public state api only here -// QJsonObject states = po.value(KEY_STATES).toObject(); -// Render::RenderStateSet* ss = new Render::RenderStateSet; - -// Q_FOREACH (QString stateName, states.keys()) { -// Render::RenderState* s= buildState(stateName.toUtf8(), states.value(stateName)); -// if (!s) -// continue; - -// ss->addState(s); -// } // of program-instance attributes - -// pass->setStateSet(ss); - t->addPass(pass); - } // of passes iteration - - m_techniques[id] = t; -} - -//Render::RenderState* GLTFParser::buildState(const QByteArray& nm, QJsonValue v) -//{ -// if (nm == "blendEnable") { -// return NULL; // will see a blendEquation spec too -// } - -// if (nm == "blendFunc") { -// QJsonObject obj = v.toObject(); -// GLenum srcF = static_cast<GLenum>(obj.value(QStringLiteral("sfactor")).toInt()); -// GLenum dstF = static_cast<GLenum>(obj.value(QStringLiteral("dfactor")).toInt()); -// return Render::BlendState::getOrCreate(srcF, dstF); -// } - -// if (nm == "blendEquation") { -// return Render::BlendEquation::getOrCreate(static_cast<GLenum>(v.toInt())); -// } - -// if (nm == "cullFaceEnable" && v.toInt()) { -// return Render::CullFace::getOrCreate(GL_BACK); -// } - -// if (nm == "depthTestEnable" && v.toInt()) { -// return Render::DepthTest::getOrCreate(GL_LESS); -// } - -// if (nm == "depthMask") { -// return Render::DepthMask::getOrCreate(v.toInt() ? GL_TRUE : GL_FALSE); -// } - -// qCWarning(Render::Io) << Q_FUNC_INFO << "unsupported gltf state:" << nm; -// return NULL; -//} - -QFile *GLTFParser::resolveLocalData(QString path) -{ - QDir d(m_basePath); - Q_ASSERT(d.exists()); - - QString absPath = d.absoluteFilePath(path); - QFile* f = new QFile(absPath); - f->open(QIODevice::ReadOnly); - return f; -} - -GLTFParser::BufferData::BufferData() : - length(0) -{ -} - -GLTFParser::BufferData::BufferData(QJsonObject json) -{ - path = json.value(KEY_PATH).toString(); - length = json.value(KEY_LENGTH).toInt(); - // url -} - -QVariant GLTFParser::parameterValueFromJSON(QParameter* p, QJsonValue val) -{ - Q_UNUSED(p); - Q_UNUSED(val); -// switch (p->datatype()) { -// case QParameter::Bool: -// return val.toBool(); - -// case QParameter::Float: -// return val.toDouble(); - -// case QParameter::FloatVec2: { -// QJsonArray a = val.toArray(); -// return QVector2D(a[0].toDouble(), a[1].toDouble()); -// } - -// case QParameter::FloatVec3: { -// QJsonArray a = val.toArray(); -// return QVector3D(a[0].toDouble(), a[1].toDouble(), a[3].toDouble()); -// } - -// case QParameter::FloatVec4: { -// QJsonArray a = val.toArray(); -// return QVector4D(a[0].toDouble(), -// a[1].toDouble(), -// a[2].toDouble(), -// a[3].toDouble()); -// } - -// case QParameter::FloatMat4: { -// QJsonArray a = val.toArray(); - -// QMatrix4x4 m(Qt::Uninitialized); -// for (int i=0; i<16; ++i) { -// m(i % 4, i / 4) = a[i].toDouble(); -// } -// return m; -// } - -// default: -// qCWarning(Render::Io) << Q_FUNC_INFO << "unhandled type:" << QString::number(p->datatype(), 16); -// } - - return QVariant(); -} - -void GLTFParserMesh::copy(const QNode *ref) -{ - QAbstractMesh::copy(ref); - const GLTFParserMesh *gltfMesh = static_cast<const GLTFParserMesh*>(ref); - d_func()->m_meshData = gltfMesh->d_func()->m_meshData; -} - -GLTFParserMesh::GLTFParserMesh(QNode *parent) - : QAbstractMesh(*new GLTFParserMeshPrivate, parent) -{ -} - - -void GLTFParserMesh::setData(QMeshDataPtr data) -{ - Q_D(GLTFParserMesh); - d->m_meshData = data; - QAbstractMesh::update(); -} - -QAbstractMeshFunctorPtr GLTFParserMesh::meshFunctor() const -{ - Q_D(const GLTFParserMesh); - return QAbstractMeshFunctorPtr(new GLTFParserMeshFunctor(d->m_meshData)); -} - -GLTFParserMeshFunctor::GLTFParserMeshFunctor(QMeshDataPtr meshData) - : QAbstractMeshFunctor() - , m_meshData(meshData) -{ -} - -QMeshDataPtr GLTFParserMeshFunctor::operator ()() -{ - return m_meshData; -} - -bool GLTFParserMeshFunctor::operator ==(const QAbstractMeshFunctor &) const -{ - return false; -} - -} // namespace Qt3D - -QT_END_NAMESPACE - -Q_DECLARE_METATYPE(Qt3D::GLTFParserMeshFunctor) - -#include "gltfparser.moc" |