summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLaszlo Agocs <laszlo.agocs@theqtcompany.com>2016-01-06 15:24:03 +0100
committerLaszlo Agocs <laszlo.agocs@theqtcompany.com>2016-01-07 09:28:32 +0000
commit9a23776ed1cb077bf839c6aad4ff901ea4fcc8c2 (patch)
tree0f0ff5d17a606500757c24e3aeef8b15162543a5
parent251046782631ca13a2df1d23c73fc68691fc77bc (diff)
Support KHR_materials_common in the glTF parser
Map to the built-in materials as much as possible. Task-number: QTBUG-49384 Change-Id: I6c73c0cfcc327323c51ae2f3735cc7f3c53fbfee Reviewed-by: Andy Nichols <andy.nichols@theqtcompany.com>
-rw-r--r--src/plugins/sceneparsers/gltf/gltfparser.cpp133
-rw-r--r--src/plugins/sceneparsers/gltf/gltfparser.h3
2 files changed, 123 insertions, 13 deletions
diff --git a/src/plugins/sceneparsers/gltf/gltfparser.cpp b/src/plugins/sceneparsers/gltf/gltfparser.cpp
index ac942ef68..6bfca2b55 100644
--- a/src/plugins/sceneparsers/gltf/gltfparser.cpp
+++ b/src/plugins/sceneparsers/gltf/gltfparser.cpp
@@ -72,6 +72,12 @@
#include <Qt3DRender/QTechnique>
#include <Qt3DRender/QTexture>
+#include <Qt3DRender/QPhongMaterial>
+#include <Qt3DRender/QDiffuseMapMaterial>
+#include <Qt3DRender/QDiffuseSpecularMapMaterial>
+#include <Qt3DRender/QNormalDiffuseMapMaterial>
+#include <Qt3DRender/QNormalDiffuseSpecularMapMaterial>
+
QT_BEGIN_NAMESPACE
using namespace Qt3DCore;
@@ -100,6 +106,8 @@ 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_EXTENSIONS = QStringLiteral("extensions");
+const QString KEY_COMMON_MAT = QStringLiteral("KHR_materials_common");
const QString KEY_TECHNIQUE = QStringLiteral("technique");
const QString KEY_VALUES = QStringLiteral("values");
const QString KEY_BUFFERS = QStringLiteral("buffers");
@@ -245,7 +253,9 @@ Qt3DCore::QEntity* GLTFParser::node(const QString &id)
Q_FOREACH (QGeometryRenderer *geometryRenderer, m_meshDict.values(mesh.toString())) {
QEntity *entity = new QEntity;
entity->addComponent(geometryRenderer);
- entity->addComponent(material(m_meshMaterialDict[geometryRenderer]));
+ QMaterial *mat = material(m_meshMaterialDict[geometryRenderer]);
+ if (mat)
+ entity->addComponent(mat);
entities.append(entity);
}
@@ -513,19 +523,8 @@ Qt3DCore::QEntity* GLTFParser::defaultScene()
return scene(m_defaultScene);
}
-QMaterial* GLTFParser::material(const QString &id)
+QMaterial *GLTFParser::materialWithCustomShader(const QString &id, const QJsonObject &jsonObj)
{
- if (m_materialCache.contains(id))
- return m_materialCache.value(id);
-
- QJsonObject mats = m_json.object().value(KEY_MATERIALS).toObject();
- if (!mats.contains(id)) {
- qCWarning(GLTFParserLog) << "unknown material" << id << "in GLTF file" << m_basePath;
- return NULL;
- }
-
- QJsonObject jsonObj = mats.value(id).toObject();
-
//Default ES2 Technique
QString techniqueName = jsonObj.value(KEY_TECHNIQUE).toString();
if (!m_techniques.contains(techniqueName)) {
@@ -614,6 +613,114 @@ QMaterial* GLTFParser::material(const QString &id)
mat->addParameter(new QParameter(param->name(), var));
} // of material technique-instance values iteration
+ return mat;
+}
+
+static inline QVariant vec4ToRgb(const QVariant &vec4Var)
+{
+ const QVector4D v = vec4Var.value<QVector4D>();
+ return QVariant(QColor::fromRgbF(v.x(), v.y(), v.z()));
+}
+
+QMaterial *GLTFParser::commonMaterial(const QJsonObject &jsonObj)
+{
+ QVariantHash params;
+ bool hasDiffuseMap = false;
+ bool hasSpecularMap = false;
+ bool hasNormalMap = false;
+
+ QJsonObject values = jsonObj.value(KEY_VALUES).toObject();
+ Q_FOREACH (const QString &vName, values.keys()) {
+ const QJsonValue val = values.value(vName);
+ QVariant var;
+ QString propertyName = vName;
+ if (vName == QStringLiteral("ambient") && val.isArray()) {
+ var = vec4ToRgb(parameterValueFromJSON(GL_FLOAT_VEC4, val));
+ } else if (vName == QStringLiteral("diffuse")) {
+ if (val.isString()) {
+ var = parameterValueFromJSON(GL_SAMPLER_2D, val);
+ hasDiffuseMap = true;
+ } else if (val.isArray()) {
+ var = vec4ToRgb(parameterValueFromJSON(GL_FLOAT_VEC4, val));
+ }
+ } else if (vName == QStringLiteral("specular")) {
+ if (val.isString()) {
+ var = parameterValueFromJSON(GL_SAMPLER_2D, val);
+ hasSpecularMap = true;
+ } else if (val.isArray()) {
+ var = vec4ToRgb(parameterValueFromJSON(GL_FLOAT_VEC4, val));
+ }
+ } else if (vName == QStringLiteral("shininess") && val.isDouble()) {
+ var = parameterValueFromJSON(GL_FLOAT, val);
+ } else if (vName == QStringLiteral("normalmap") && val.isString()) {
+ var = parameterValueFromJSON(GL_SAMPLER_2D, val);
+ propertyName = QStringLiteral("normal");
+ hasNormalMap = true;
+ } else if (vName == QStringLiteral("transparency")) {
+ qCWarning(GLTFParserLog) << "Semi-transparent common materials are not currently supported, ignoring alpha";
+ }
+ if (var.isValid())
+ params[propertyName] = var;
+ }
+
+ QMaterial *mat = Q_NULLPTR;
+ if (hasNormalMap) {
+ if (hasSpecularMap) {
+ mat = new QNormalDiffuseSpecularMapMaterial;
+ } else {
+ if (hasDiffuseMap)
+ mat = new QNormalDiffuseMapMaterial;
+ else
+ qCWarning(GLTFParserLog) << "Common material with normal and specular maps needs a diffuse map as well";
+ }
+ } else {
+ if (hasSpecularMap) {
+ if (hasDiffuseMap)
+ mat = new QDiffuseSpecularMapMaterial;
+ else
+ qCWarning(GLTFParserLog) << "Common material with specular map needs a diffuse map as well";
+ } else if (hasDiffuseMap) {
+ mat = new QDiffuseMapMaterial;
+ } else {
+ mat = new QPhongMaterial;
+ }
+ }
+
+ if (mat) {
+ for (QVariantHash::const_iterator it = params.constBegin(), itEnd = params.constEnd(); it != itEnd; ++it)
+ mat->setProperty(it.key().toUtf8(), it.value());
+ } else {
+ qCWarning(GLTFParserLog) << "Could not find a suitable built-in material for KHR_materials_common";
+ }
+
+ return mat;
+}
+
+QMaterial* GLTFParser::material(const QString &id)
+{
+ if (m_materialCache.contains(id))
+ return m_materialCache.value(id);
+
+ QJsonObject mats = m_json.object().value(KEY_MATERIALS).toObject();
+ if (!mats.contains(id)) {
+ qCWarning(GLTFParserLog) << "unknown material" << id << "in GLTF file" << m_basePath;
+ return NULL;
+ }
+
+ QJsonObject jsonObj = mats.value(id).toObject();
+
+ QMaterial *mat = Q_NULLPTR;
+
+ // Prefer common materials over custom shaders.
+ if (jsonObj.contains(KEY_EXTENSIONS)) {
+ QJsonObject extensions = jsonObj.value(KEY_EXTENSIONS).toObject();
+ if (extensions.contains(KEY_COMMON_MAT))
+ mat = commonMaterial(extensions.value(KEY_COMMON_MAT).toObject());
+ }
+
+ if (!mat)
+ mat = materialWithCustomShader(id, jsonObj);
+
m_materialCache[id] = mat;
return mat;
}
diff --git a/src/plugins/sceneparsers/gltf/gltfparser.h b/src/plugins/sceneparsers/gltf/gltfparser.h
index 0a4bbcfe9..be8bcaa50 100644
--- a/src/plugins/sceneparsers/gltf/gltfparser.h
+++ b/src/plugins/sceneparsers/gltf/gltfparser.h
@@ -169,6 +169,9 @@ private:
static QRenderState *buildStateEnable(int state);
static QRenderState *buildState(const QString& functionName, const QJsonValue &value, int &type);
+ QMaterial *materialWithCustomShader(const QString &id, const QJsonObject &jsonObj);
+ QMaterial *commonMaterial(const QJsonObject &jsonObj);
+
QJsonDocument m_json;
QString m_basePath;
bool m_parseDone;