diff options
author | Andy Nichols <andy.nichols@theqtcompany.com> | 2015-11-11 15:21:11 +0100 |
---|---|---|
committer | Laszlo Agocs <laszlo.agocs@theqtcompany.com> | 2015-11-13 09:59:45 +0000 |
commit | 70581c93743ea60188192107d5f78ede274f247e (patch) | |
tree | b398d4f724e9c8aafb6b06bbfe3a51177e869e75 | |
parent | c40cdff485f24fba57a7e5f671699ab386f0351b (diff) |
gltfparser: Update to support glTF 1.0draft spec
Change-Id: I00e830e05c393e2e137db26b5443de5ec26870c5
Reviewed-by: Laszlo Agocs <laszlo.agocs@theqtcompany.com>
-rw-r--r-- | src/plugins/sceneparsers/gltf/gltfparser.cpp | 232 |
1 files changed, 145 insertions, 87 deletions
diff --git a/src/plugins/sceneparsers/gltf/gltfparser.cpp b/src/plugins/sceneparsers/gltf/gltfparser.cpp index 5c21604bc..c35a08fb6 100644 --- a/src/plugins/sceneparsers/gltf/gltfparser.cpp +++ b/src/plugins/sceneparsers/gltf/gltfparser.cpp @@ -47,7 +47,10 @@ #include <Qt3DCore/QCameraLens> #include <Qt3DCore/QEntity> #include <Qt3DCore/QMatrixTransform> +#include <Qt3DCore/QRotateTransform> +#include <Qt3DCore/QScaleTransform> #include <Qt3DCore/QTransform> +#include <Qt3DCore/QTranslateTransform> #include <Qt3DCore/private/qurlhelper_p.h> @@ -90,6 +93,9 @@ 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_ROTATION = QStringLiteral("rotation"); +const QString KEY_SCALE = QStringLiteral("scale"); +const QString KEY_TRANSLATION = QStringLiteral("translation"); const QString KEY_TYPE = QStringLiteral("type"); const QString KEY_PERSPECTIVE =QStringLiteral("perspective"); const QString KEY_NAME = QStringLiteral("name"); @@ -115,7 +121,7 @@ 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_MODE = QStringLiteral("mode"); const QString KEY_MATERIAL = QStringLiteral("material"); const QString KEY_ATTRIBUTES = QStringLiteral("attributes"); const QString KEY_INDICES = QStringLiteral("indices"); @@ -274,6 +280,9 @@ Qt3DCore::QEntity* GLTFParser::node(const QString &id) renameFromJson(jsonObj, result); + + // Node Transforms + Qt3DCore::QTransform *trans = Q_NULLPTR; if ( jsonObj.contains(KEY_MATRIX) ) { QMatrix4x4 m(Qt::Uninitialized); @@ -284,11 +293,63 @@ Qt3DCore::QEntity* GLTFParser::node(const QString &id) } // ADD MATRIX TRANSFORM COMPONENT TO ENTITY - Qt3DCore::QTransform *trans = new Qt3DCore::QTransform(); + if ( trans == Q_NULLPTR) + trans = new Qt3DCore::QTransform; trans->addTransform(new QMatrixTransform(m)); - result->addComponent(trans); + + } + + // Rotation quaternion + if (jsonObj.contains(KEY_ROTATION)) { + if ( trans == Q_NULLPTR) + trans = new Qt3DCore::QTransform; + + QJsonArray quaternionValues = jsonObj.value(KEY_ROTATION).toArray(); + QQuaternion quaternion(quaternionValues[0].toDouble(), + quaternionValues[1].toDouble(), + quaternionValues[2].toDouble(), + quaternionValues[3].toDouble()); + + QVector3D axis; + float angle; + quaternion.getAxisAndAngle(&axis, &angle); + + Qt3DCore::QRotateTransform *rotateTransform = new Qt3DCore::QRotateTransform; + rotateTransform->setAxis(axis); + rotateTransform->setAngleDeg(angle); + trans->addTransform(rotateTransform); + } + + // Translation + if (jsonObj.contains(KEY_TRANSLATION)) { + if ( trans == Q_NULLPTR) + trans = new Qt3DCore::QTransform; + + QJsonArray translationValues = jsonObj.value(KEY_TRANSLATION).toArray(); + Qt3DCore::QTranslateTransform *translateTransform = new Qt3DCore::QTranslateTransform; + translateTransform->setDx(translationValues[0].toDouble()); + translateTransform->setDy(translationValues[1].toDouble()); + translateTransform->setDz(translationValues[2].toDouble()); + trans->addTransform(translateTransform); + } + + // Scale + if (jsonObj.contains(KEY_SCALE)) { + if ( trans == Q_NULLPTR) + trans = new Qt3DCore::QTransform; + + QJsonArray scaleValues = jsonObj.value(KEY_SCALE).toArray(); + Qt3DCore::QScaleTransform *scaleTransform = new Qt3DCore::QScaleTransform; + scaleTransform->setScale3D(QVector3D(scaleValues[0].toDouble(), + scaleValues[1].toDouble(), + scaleValues[2].toDouble())); + trans->addTransform(scaleTransform); } + // Add the Transform component + if (trans != Q_NULLPTR) + result->addComponent(trans); + if ( jsonObj.contains(KEY_CAMERA) ) { QCameraLens* cam = camera( jsonObj.value(KEY_CAMERA).toString() ); if (!cam) { @@ -482,10 +543,8 @@ QMaterial* GLTFParser::material(const QString &id) QJsonObject jsonObj = mats.value(id).toObject(); - QJsonObject tech = jsonObj.value(KEY_INSTANCE_TECHNIQUE).toObject(); - //Default ES2 Technique - QString techniqueName = tech.value(KEY_TECHNIQUE).toString(); + QString techniqueName = jsonObj.value(KEY_TECHNIQUE).toString(); if (!m_techniques.contains(techniqueName)) { qCWarning(GLTFParserLog) << "unknown technique" << techniqueName << "for material" << id << "in GLTF file" << m_basePath; @@ -501,7 +560,7 @@ QMaterial* GLTFParser::material(const QString &id) //Optional Core technique QTechnique *coreTechnique = Q_NULLPTR; QTechnique *gl2Technique = Q_NULLPTR; - QString coreTechniqueName = tech.value(KEY_TECHNIQUE_CORE).toString(); + QString coreTechniqueName = jsonObj.value(KEY_TECHNIQUE_CORE).toString(); if (!coreTechniqueName.isNull()) { if (!m_techniques.contains(coreTechniqueName)) { qCWarning(GLTFParserLog) << "unknown technique" << coreTechniqueName @@ -515,7 +574,7 @@ QMaterial* GLTFParser::material(const QString &id) } } //Optional GL2 technique - QString gl2TechniqueName = tech.value(KEY_TECHNIQUE_GL2).toString(); + QString gl2TechniqueName = jsonObj.value(KEY_TECHNIQUE_GL2).toString(); if (!gl2TechniqueName.isNull()) { if (!m_techniques.contains(gl2TechniqueName)) { qCWarning(GLTFParserLog) << "unknown technique" << gl2TechniqueName @@ -548,7 +607,7 @@ QMaterial* GLTFParser::material(const QString &id) renameFromJson(jsonObj, mat); - QJsonObject values = tech.value(KEY_VALUES).toObject(); + QJsonObject values = jsonObj.value(KEY_VALUES).toObject(); Q_FOREACH (QString vName, values.keys()) { QParameter *param = parameterFromTechnique(technique, vName); @@ -788,6 +847,7 @@ void GLTFParser::processJSONTechnique(const QString &id, const QJsonObject &json QTechnique *t = new QTechnique; t->setObjectName(id); + // Parameters QHash<QString, QParameter*> paramDict; QJsonObject params = jsonObject.value(KEY_PARAMETERS).toObject(); Q_FOREACH (QString pname, params.keys()) { @@ -810,95 +870,93 @@ void GLTFParser::processJSONTechnique(const QString &id, const QJsonObject &json paramDict[pname] = p; } // of parameters iteration - QJsonObject passes = jsonObject.value(KEY_PASSES).toObject(); - Q_FOREACH (QString pname, passes.keys()) { - QJsonObject po = passes.value(pname).toObject(); - QJsonObject ip = po.value(KEY_INSTANCE_PROGRAM).toObject(); + // Program + QString programName = jsonObject.value(KEY_PROGRAM).toString(); + if (!m_programs.contains(programName)) { + qCWarning(GLTFParserLog) << Q_FUNC_INFO << "technique" << id + << ": missing program" << programName; + } - QString programName = ip.value(KEY_PROGRAM).toString(); - if (!m_programs.contains(programName)) { - qCWarning(GLTFParserLog) << Q_FUNC_INFO << "technique" << id << "pass" << pname - << ": missing program" << programName; + QRenderPass* pass = new QRenderPass; + pass->setShaderProgram(m_programs[programName]); + + // Attributes + QJsonObject attrs = jsonObject.value(KEY_ATTRIBUTES).toObject(); + Q_FOREACH ( QString shaderAttributeName, attrs.keys() ) { + QString pname = attrs.value(shaderAttributeName).toString(); + QParameter *parameter = paramDict.value(pname, Q_NULLPTR); + QString attributeName = pname; + if (parameter == Q_NULLPTR) { + qCWarning(GLTFParserLog) << Q_FUNC_INFO << "attribute " << pname + << "defined in instanceProgram but not as parameter"; continue; } + //Check if the parameter has a standard attribute semantic + QString standardAttributeName = standardAttributeNameFromSemantic(m_parameterDataDict[parameter].semantic); + if (!standardAttributeName.isNull()) { + attributeName = standardAttributeName; + t->removeParameter(parameter); + m_parameterDataDict.remove(parameter); + delete parameter; + } - QRenderPass* pass = new QRenderPass; - pass->setShaderProgram(m_programs[programName]); - - QJsonObject attrs = ip.value(KEY_ATTRIBUTES).toObject(); - Q_FOREACH ( QString shaderAttributeName, attrs.keys() ) { - QString pname = attrs.value(shaderAttributeName).toString(); - QParameter *parameter = paramDict.value(pname, Q_NULLPTR); - QString attributeName = pname; - if (parameter == Q_NULLPTR) { - qCWarning(GLTFParserLog) << Q_FUNC_INFO << "attribute " << pname - << "defined in instanceProgram but not as parameter"; - continue; - } - //Check if the parameter has a standard attribute semantic - QString standardAttributeName = standardAttributeNameFromSemantic(m_parameterDataDict[parameter].semantic); - if (!standardAttributeName.isNull()) { - attributeName = standardAttributeName; - t->removeParameter(parameter); - m_parameterDataDict.remove(parameter); - delete parameter; - } - - pass->addBinding(new QParameterMapping(attributeName, shaderAttributeName, QParameterMapping::Attribute)); - } // of program-instance attributes + pass->addBinding(new QParameterMapping(attributeName, shaderAttributeName, QParameterMapping::Attribute)); + } // of program-instance attributes + + // Uniforms + QJsonObject uniforms = jsonObject.value(KEY_UNIFORMS).toObject(); + Q_FOREACH (QString shaderUniformName, uniforms.keys()) { + QString pname = uniforms.value(shaderUniformName).toString(); + QParameter *parameter = paramDict.value(pname, Q_NULLPTR); + if (parameter == Q_NULLPTR) { + qCWarning(GLTFParserLog) << Q_FUNC_INFO << "uniform " << pname + << "defined in instanceProgram but not as parameter"; + continue; + } + //Check if the parameter has a standard uniform semantic + QString standardUniformName = standardUniformNamefromSemantic(m_parameterDataDict[parameter].semantic); + if (standardUniformName.isNull()) { + pass->addBinding(new QParameterMapping(pname, shaderUniformName, QParameterMapping::Uniform)); + } else { + pass->addBinding(new QParameterMapping(standardUniformName, shaderUniformName, QParameterMapping::StandardUniform)); + t->removeParameter(parameter); + m_parameterDataDict.remove(parameter); + delete parameter; + } + } // of program-instance uniforms - QJsonObject uniforms = ip.value(KEY_UNIFORMS).toObject(); - Q_FOREACH (QString shaderUniformName, uniforms.keys()) { - QString pname = uniforms.value(shaderUniformName).toString(); - QParameter *parameter = paramDict.value(pname, Q_NULLPTR); - if (parameter == Q_NULLPTR) { - qCWarning(GLTFParserLog) << Q_FUNC_INFO << "uniform " << pname - << "defined in instanceProgram but not as parameter"; - continue; - } - //Check if the parameter has a standard uniform semantic - QString standardUniformName = standardUniformNamefromSemantic(m_parameterDataDict[parameter].semantic); - if (standardUniformName.isNull()) { - pass->addBinding(new QParameterMapping(pname, shaderUniformName, QParameterMapping::Uniform)); - } else { - pass->addBinding(new QParameterMapping(standardUniformName, shaderUniformName, QParameterMapping::StandardUniform)); - t->removeParameter(parameter); - m_parameterDataDict.remove(parameter); - delete parameter; - } - } // of program-instance uniforms - QJsonObject states = po.value(KEY_STATES).toObject(); + // States + QJsonObject states = jsonObject.value(KEY_STATES).toObject(); - //Process states to enable - QJsonArray enableStatesArray = states.value(KEY_ENABLE).toArray(); - QVector<int> enableStates; - Q_FOREACH (QJsonValue enableValue, enableStatesArray) { - enableStates.append(enableValue.toInt()); - } + //Process states to enable + QJsonArray enableStatesArray = states.value(KEY_ENABLE).toArray(); + QVector<int> enableStates; + Q_FOREACH (QJsonValue enableValue, enableStatesArray) { + enableStates.append(enableValue.toInt()); + } - //Process the list of state functions - QJsonObject functions = states.value(KEY_FUNCTIONS).toObject(); - Q_FOREACH (QString functionName, functions.keys()) { - int enableStateType = 0; - QRenderState *renderState = buildState(functionName, functions.value(functionName), enableStateType); - if (renderState != Q_NULLPTR) { - //Remove the need to set a default state values for enableStateType - enableStates.removeOne(enableStateType); - pass->addRenderState(renderState); - } + //Process the list of state functions + QJsonObject functions = states.value(KEY_FUNCTIONS).toObject(); + Q_FOREACH (QString functionName, functions.keys()) { + int enableStateType = 0; + QRenderState *renderState = buildState(functionName, functions.value(functionName), enableStateType); + if (renderState != Q_NULLPTR) { + //Remove the need to set a default state values for enableStateType + enableStates.removeOne(enableStateType); + pass->addRenderState(renderState); } + } - //Create render states with default values for any remaining enable states - Q_FOREACH (int enableState, enableStates) { - QRenderState *renderState = buildStateEnable(enableState); - if (renderState != Q_NULLPTR) - pass->addRenderState(renderState); - } + //Create render states with default values for any remaining enable states + Q_FOREACH (int enableState, enableStates) { + QRenderState *renderState = buildStateEnable(enableState); + if (renderState != Q_NULLPTR) + pass->addRenderState(renderState); + } - t->addPass(pass); - } // of passes iteration + t->addPass(pass); m_techniques[id] = t; } @@ -913,7 +971,7 @@ void GLTFParser::processJSONMesh(const QString &id, const QJsonObject &json) QJsonArray primitivesArray = json.value(KEY_PRIMITIVES).toArray(); Q_FOREACH (QJsonValue primitiveValue, primitivesArray) { QJsonObject primitiveObject = primitiveValue.toObject(); - int type = primitiveObject.value(KEY_PRIMITIVE).toInt(); + int type = primitiveObject.value(KEY_MODE).toInt(); QString material = primitiveObject.value(KEY_MATERIAL).toString(); if ( material.isEmpty()) { |