mirror of
https://github.com/overte-org/overte.git
synced 2025-07-23 19:04:27 +02:00
commit
a85a6f6795
3 changed files with 2181 additions and 5 deletions
1380
libraries/fbx/src/GLTFReader.cpp
Normal file
1380
libraries/fbx/src/GLTFReader.cpp
Normal file
File diff suppressed because it is too large
Load diff
786
libraries/fbx/src/GLTFReader.h
Normal file
786
libraries/fbx/src/GLTFReader.h
Normal file
|
@ -0,0 +1,786 @@
|
||||||
|
//
|
||||||
|
// GLTFReader.h
|
||||||
|
// libraries/fbx/src
|
||||||
|
//
|
||||||
|
// Created by Luis Cuenca on 8/30/17.
|
||||||
|
// Copyright 2017 High Fidelity, Inc.
|
||||||
|
//
|
||||||
|
// Distributed under the Apache License, Version 2.0.
|
||||||
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef hifi_GLTFReader_h
|
||||||
|
#define hifi_GLTFReader_h
|
||||||
|
|
||||||
|
#include <memory.h>
|
||||||
|
#include <QtNetwork/QNetworkReply>
|
||||||
|
#include "ModelFormatLogging.h"
|
||||||
|
#include "FBXReader.h"
|
||||||
|
|
||||||
|
|
||||||
|
struct GLTFAsset {
|
||||||
|
QString generator;
|
||||||
|
QString version; //required
|
||||||
|
QString copyright;
|
||||||
|
QMap<QString, bool> defined;
|
||||||
|
void dump() {
|
||||||
|
if (defined["generator"]) {
|
||||||
|
qCDebug(modelformat) << "generator: " << generator;
|
||||||
|
}
|
||||||
|
if (defined["version"]) {
|
||||||
|
qCDebug(modelformat) << "version: " << version;
|
||||||
|
}
|
||||||
|
if (defined["copyright"]) {
|
||||||
|
qCDebug(modelformat) << "copyright: " << copyright;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct GLTFNode {
|
||||||
|
QString name;
|
||||||
|
int camera;
|
||||||
|
int mesh;
|
||||||
|
QVector<int> children;
|
||||||
|
QVector<double> translation;
|
||||||
|
QVector<double> rotation;
|
||||||
|
QVector<double> scale;
|
||||||
|
QVector<double> matrix;
|
||||||
|
QVector<glm::mat4> transforms;
|
||||||
|
int skin;
|
||||||
|
QVector<int> skeletons;
|
||||||
|
QString jointName;
|
||||||
|
QMap<QString, bool> defined;
|
||||||
|
void dump() {
|
||||||
|
if (defined["name"]) {
|
||||||
|
qCDebug(modelformat) << "name: " << name;
|
||||||
|
}
|
||||||
|
if (defined["camera"]) {
|
||||||
|
qCDebug(modelformat) << "camera: " << camera;
|
||||||
|
}
|
||||||
|
if (defined["mesh"]) {
|
||||||
|
qCDebug(modelformat) << "mesh: " << mesh;
|
||||||
|
}
|
||||||
|
if (defined["skin"]) {
|
||||||
|
qCDebug(modelformat) << "skin: " << skin;
|
||||||
|
}
|
||||||
|
if (defined["jointName"]) {
|
||||||
|
qCDebug(modelformat) << "jointName: " << jointName;
|
||||||
|
}
|
||||||
|
if (defined["children"]) {
|
||||||
|
qCDebug(modelformat) << "children: " << children;
|
||||||
|
}
|
||||||
|
if (defined["translation"]) {
|
||||||
|
qCDebug(modelformat) << "translation: " << translation;
|
||||||
|
}
|
||||||
|
if (defined["rotation"]) {
|
||||||
|
qCDebug(modelformat) << "rotation: " << rotation;
|
||||||
|
}
|
||||||
|
if (defined["scale"]) {
|
||||||
|
qCDebug(modelformat) << "scale: " << scale;
|
||||||
|
}
|
||||||
|
if (defined["matrix"]) {
|
||||||
|
qCDebug(modelformat) << "matrix: " << matrix;
|
||||||
|
}
|
||||||
|
if (defined["skeletons"]) {
|
||||||
|
qCDebug(modelformat) << "skeletons: " << skeletons;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Meshes
|
||||||
|
|
||||||
|
struct GLTFMeshPrimitivesTarget {
|
||||||
|
int normal;
|
||||||
|
int position;
|
||||||
|
int tangent;
|
||||||
|
QMap<QString, bool> defined;
|
||||||
|
void dump() {
|
||||||
|
if (defined["normal"]) {
|
||||||
|
qCDebug(modelformat) << "normal: " << normal;
|
||||||
|
}
|
||||||
|
if (defined["position"]) {
|
||||||
|
qCDebug(modelformat) << "position: " << position;
|
||||||
|
}
|
||||||
|
if (defined["tangent"]) {
|
||||||
|
qCDebug(modelformat) << "tangent: " << tangent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace GLTFMeshPrimitivesRenderingMode {
|
||||||
|
enum Values {
|
||||||
|
POINTS = 0,
|
||||||
|
LINES,
|
||||||
|
LINE_LOOP,
|
||||||
|
LINE_STRIP,
|
||||||
|
TRIANGLES,
|
||||||
|
TRIANGLE_STRIP,
|
||||||
|
TRIANGLE_FAN
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
struct GLTFMeshPrimitiveAttr {
|
||||||
|
QMap<QString, int> values;
|
||||||
|
QMap<QString, bool> defined;
|
||||||
|
void dump() {
|
||||||
|
QList<QString> keys = values.keys();
|
||||||
|
qCDebug(modelformat) << "values: ";
|
||||||
|
foreach(auto k, keys) {
|
||||||
|
qCDebug(modelformat) << k << ": " << values[k];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct GLTFMeshPrimitive {
|
||||||
|
GLTFMeshPrimitiveAttr attributes;
|
||||||
|
int indices;
|
||||||
|
int material;
|
||||||
|
int mode{ GLTFMeshPrimitivesRenderingMode::TRIANGLES };
|
||||||
|
QVector<GLTFMeshPrimitiveAttr> targets;
|
||||||
|
QMap<QString, bool> defined;
|
||||||
|
void dump() {
|
||||||
|
if (defined["attributes"]) {
|
||||||
|
qCDebug(modelformat) << "attributes: ";
|
||||||
|
attributes.dump();
|
||||||
|
}
|
||||||
|
if (defined["indices"]) {
|
||||||
|
qCDebug(modelformat) << "indices: " << indices;
|
||||||
|
}
|
||||||
|
if (defined["material"]) {
|
||||||
|
qCDebug(modelformat) << "material: " << material;
|
||||||
|
}
|
||||||
|
if (defined["mode"]) {
|
||||||
|
qCDebug(modelformat) << "mode: " << mode;
|
||||||
|
}
|
||||||
|
if (defined["targets"]) {
|
||||||
|
qCDebug(modelformat) << "targets: ";
|
||||||
|
foreach(auto t, targets) t.dump();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct GLTFMesh {
|
||||||
|
QString name;
|
||||||
|
QVector<GLTFMeshPrimitive> primitives;
|
||||||
|
QVector<double> weights;
|
||||||
|
QMap<QString, bool> defined;
|
||||||
|
void dump() {
|
||||||
|
if (defined["name"]) {
|
||||||
|
qCDebug(modelformat) << "name: " << name;
|
||||||
|
}
|
||||||
|
if (defined["primitives"]) {
|
||||||
|
qCDebug(modelformat) << "primitives: ";
|
||||||
|
foreach(auto prim, primitives) prim.dump();
|
||||||
|
}
|
||||||
|
if (defined["weights"]) {
|
||||||
|
qCDebug(modelformat) << "weights: " << weights;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// BufferViews
|
||||||
|
|
||||||
|
namespace GLTFBufferViewTarget {
|
||||||
|
enum Values {
|
||||||
|
ARRAY_BUFFER = 34962,
|
||||||
|
ELEMENT_ARRAY_BUFFER = 34963
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
struct GLTFBufferView {
|
||||||
|
int buffer; //required
|
||||||
|
int byteLength; //required
|
||||||
|
int byteOffset;
|
||||||
|
int target;
|
||||||
|
QMap<QString, bool> defined;
|
||||||
|
void dump() {
|
||||||
|
if (defined["buffer"]) {
|
||||||
|
qCDebug(modelformat) << "buffer: " << buffer;
|
||||||
|
}
|
||||||
|
if (defined["byteLength"]) {
|
||||||
|
qCDebug(modelformat) << "byteLength: " << byteLength;
|
||||||
|
}
|
||||||
|
if (defined["byteOffset"]) {
|
||||||
|
qCDebug(modelformat) << "byteOffset: " << byteOffset;
|
||||||
|
}
|
||||||
|
if (defined["target"]) {
|
||||||
|
qCDebug(modelformat) << "target: " << target;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Buffers
|
||||||
|
|
||||||
|
struct GLTFBuffer {
|
||||||
|
int byteLength; //required
|
||||||
|
QString uri;
|
||||||
|
QByteArray blob;
|
||||||
|
QMap<QString, bool> defined;
|
||||||
|
void dump() {
|
||||||
|
if (defined["byteLength"]) {
|
||||||
|
qCDebug(modelformat) << "byteLength: " << byteLength;
|
||||||
|
}
|
||||||
|
if (defined["uri"]) {
|
||||||
|
qCDebug(modelformat) << "uri: " << uri;
|
||||||
|
}
|
||||||
|
if (defined["blob"]) {
|
||||||
|
qCDebug(modelformat) << "blob: " << "DEFINED";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Samplers
|
||||||
|
namespace GLTFSamplerFilterType {
|
||||||
|
enum Values {
|
||||||
|
NEAREST = 9728,
|
||||||
|
LINEAR = 9729,
|
||||||
|
NEAREST_MIPMAP_NEAREST = 9984,
|
||||||
|
LINEAR_MIPMAP_NEAREST = 9985,
|
||||||
|
NEAREST_MIPMAP_LINEAR = 9986,
|
||||||
|
LINEAR_MIPMAP_LINEAR = 9987
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace GLTFSamplerWrapType {
|
||||||
|
enum Values {
|
||||||
|
CLAMP_TO_EDGE = 33071,
|
||||||
|
MIRRORED_REPEAT = 33648,
|
||||||
|
REPEAT = 10497
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
struct GLTFSampler {
|
||||||
|
int magFilter;
|
||||||
|
int minFilter;
|
||||||
|
int wrapS;
|
||||||
|
int wrapT;
|
||||||
|
QMap<QString, bool> defined;
|
||||||
|
void dump() {
|
||||||
|
if (defined["magFilter"]) {
|
||||||
|
qCDebug(modelformat) << "magFilter: " << magFilter;
|
||||||
|
}
|
||||||
|
if (defined["minFilter"]) {
|
||||||
|
qCDebug(modelformat) << "minFilter: " << minFilter;
|
||||||
|
}
|
||||||
|
if (defined["wrapS"]) {
|
||||||
|
qCDebug(modelformat) << "wrapS: " << wrapS;
|
||||||
|
}
|
||||||
|
if (defined["wrapT"]) {
|
||||||
|
qCDebug(modelformat) << "wrapT: " << wrapT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Cameras
|
||||||
|
|
||||||
|
struct GLTFCameraPerspective {
|
||||||
|
double aspectRatio;
|
||||||
|
double yfov; //required
|
||||||
|
double zfar;
|
||||||
|
double znear; //required
|
||||||
|
QMap<QString, bool> defined;
|
||||||
|
void dump() {
|
||||||
|
if (defined["zfar"]) {
|
||||||
|
qCDebug(modelformat) << "zfar: " << zfar;
|
||||||
|
}
|
||||||
|
if (defined["znear"]) {
|
||||||
|
qCDebug(modelformat) << "znear: " << znear;
|
||||||
|
}
|
||||||
|
if (defined["aspectRatio"]) {
|
||||||
|
qCDebug(modelformat) << "aspectRatio: " << aspectRatio;
|
||||||
|
}
|
||||||
|
if (defined["yfov"]) {
|
||||||
|
qCDebug(modelformat) << "yfov: " << yfov;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct GLTFCameraOrthographic {
|
||||||
|
double zfar; //required
|
||||||
|
double znear; //required
|
||||||
|
double xmag; //required
|
||||||
|
double ymag; //required
|
||||||
|
QMap<QString, bool> defined;
|
||||||
|
void dump() {
|
||||||
|
if (defined["zfar"]) {
|
||||||
|
qCDebug(modelformat) << "zfar: " << zfar;
|
||||||
|
}
|
||||||
|
if (defined["znear"]) {
|
||||||
|
qCDebug(modelformat) << "znear: " << znear;
|
||||||
|
}
|
||||||
|
if (defined["xmag"]) {
|
||||||
|
qCDebug(modelformat) << "xmag: " << xmag;
|
||||||
|
}
|
||||||
|
if (defined["ymag"]) {
|
||||||
|
qCDebug(modelformat) << "ymag: " << ymag;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace GLTFCameraTypes {
|
||||||
|
enum Values {
|
||||||
|
ORTHOGRAPHIC = 0,
|
||||||
|
PERSPECTIVE
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
struct GLTFCamera {
|
||||||
|
QString name;
|
||||||
|
GLTFCameraPerspective perspective; //required (or)
|
||||||
|
GLTFCameraOrthographic orthographic; //required (or)
|
||||||
|
int type;
|
||||||
|
QMap<QString, bool> defined;
|
||||||
|
void dump() {
|
||||||
|
if (defined["name"]) {
|
||||||
|
qCDebug(modelformat) << "name: " << name;
|
||||||
|
}
|
||||||
|
if (defined["type"]) {
|
||||||
|
qCDebug(modelformat) << "type: " << type;
|
||||||
|
}
|
||||||
|
if (defined["perspective"]) {
|
||||||
|
perspective.dump();
|
||||||
|
}
|
||||||
|
if (defined["orthographic"]) {
|
||||||
|
orthographic.dump();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Images
|
||||||
|
|
||||||
|
namespace GLTFImageMimetype {
|
||||||
|
enum Values {
|
||||||
|
JPEG = 0,
|
||||||
|
PNG
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
struct GLTFImage {
|
||||||
|
QString uri; //required (or)
|
||||||
|
int mimeType;
|
||||||
|
int bufferView; //required (or)
|
||||||
|
QMap<QString, bool> defined;
|
||||||
|
void dump() {
|
||||||
|
if (defined["uri"]) {
|
||||||
|
qCDebug(modelformat) << "uri: " << uri;
|
||||||
|
}
|
||||||
|
if (defined["mimeType"]) {
|
||||||
|
qCDebug(modelformat) << "mimeType: " << mimeType;
|
||||||
|
}
|
||||||
|
if (defined["bufferView"]) {
|
||||||
|
qCDebug(modelformat) << "bufferView: " << bufferView;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Materials
|
||||||
|
|
||||||
|
struct GLTFpbrMetallicRoughness {
|
||||||
|
QVector<double> baseColorFactor;
|
||||||
|
int baseColorTexture;
|
||||||
|
int metallicRoughnessTexture;
|
||||||
|
double metallicFactor;
|
||||||
|
double roughnessFactor;
|
||||||
|
QMap<QString, bool> defined;
|
||||||
|
void dump() {
|
||||||
|
if (defined["baseColorFactor"]) {
|
||||||
|
qCDebug(modelformat) << "baseColorFactor: " << baseColorFactor;
|
||||||
|
}
|
||||||
|
if (defined["baseColorTexture"]) {
|
||||||
|
qCDebug(modelformat) << "baseColorTexture: " << baseColorTexture;
|
||||||
|
}
|
||||||
|
if (defined["metallicRoughnessTexture"]) {
|
||||||
|
qCDebug(modelformat) << "metallicRoughnessTexture: " << metallicRoughnessTexture;
|
||||||
|
}
|
||||||
|
if (defined["metallicFactor"]) {
|
||||||
|
qCDebug(modelformat) << "metallicFactor: " << metallicFactor;
|
||||||
|
}
|
||||||
|
if (defined["roughnessFactor"]) {
|
||||||
|
qCDebug(modelformat) << "roughnessFactor: " << roughnessFactor;
|
||||||
|
}
|
||||||
|
if (defined["baseColorFactor"]) {
|
||||||
|
qCDebug(modelformat) << "baseColorFactor: " << baseColorFactor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace GLTFMaterialAlphaMode {
|
||||||
|
enum Values {
|
||||||
|
OPAQUE = 0,
|
||||||
|
MASK,
|
||||||
|
BLEND
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
struct GLTFMaterial {
|
||||||
|
QString name;
|
||||||
|
QVector<double> emissiveFactor;
|
||||||
|
int emissiveTexture;
|
||||||
|
int normalTexture;
|
||||||
|
int occlusionTexture;
|
||||||
|
int alphaMode;
|
||||||
|
double alphaCutoff;
|
||||||
|
bool doubleSided;
|
||||||
|
GLTFpbrMetallicRoughness pbrMetallicRoughness;
|
||||||
|
QMap<QString, bool> defined;
|
||||||
|
void dump() {
|
||||||
|
if (defined["name"]) {
|
||||||
|
qCDebug(modelformat) << "name: " << name;
|
||||||
|
}
|
||||||
|
if (defined["emissiveTexture"]) {
|
||||||
|
qCDebug(modelformat) << "emissiveTexture: " << emissiveTexture;
|
||||||
|
}
|
||||||
|
if (defined["normalTexture"]) {
|
||||||
|
qCDebug(modelformat) << "normalTexture: " << normalTexture;
|
||||||
|
}
|
||||||
|
if (defined["occlusionTexture"]) {
|
||||||
|
qCDebug(modelformat) << "occlusionTexture: " << occlusionTexture;
|
||||||
|
}
|
||||||
|
if (defined["emissiveFactor"]) {
|
||||||
|
qCDebug(modelformat) << "emissiveFactor: " << emissiveFactor;
|
||||||
|
}
|
||||||
|
if (defined["pbrMetallicRoughness"]) {
|
||||||
|
pbrMetallicRoughness.dump();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Accesors
|
||||||
|
|
||||||
|
namespace GLTFAccessorType {
|
||||||
|
enum Values {
|
||||||
|
SCALAR = 0,
|
||||||
|
VEC2,
|
||||||
|
VEC3,
|
||||||
|
VEC4,
|
||||||
|
MAT2,
|
||||||
|
MAT3,
|
||||||
|
MAT4
|
||||||
|
};
|
||||||
|
}
|
||||||
|
namespace GLTFAccessorComponentType {
|
||||||
|
enum Values {
|
||||||
|
BYTE = 5120,
|
||||||
|
UNSIGNED_BYTE = 5121,
|
||||||
|
SHORT = 5122,
|
||||||
|
UNSIGNED_SHORT = 5123,
|
||||||
|
UNSIGNED_INT = 5125,
|
||||||
|
FLOAT = 5126
|
||||||
|
};
|
||||||
|
}
|
||||||
|
struct GLTFAccessor {
|
||||||
|
int bufferView;
|
||||||
|
int byteOffset;
|
||||||
|
int componentType; //required
|
||||||
|
int count; //required
|
||||||
|
int type; //required
|
||||||
|
bool normalized{ false };
|
||||||
|
QVector<double> max;
|
||||||
|
QVector<double> min;
|
||||||
|
QMap<QString, bool> defined;
|
||||||
|
void dump() {
|
||||||
|
if (defined["bufferView"]) {
|
||||||
|
qCDebug(modelformat) << "bufferView: " << bufferView;
|
||||||
|
}
|
||||||
|
if (defined["byteOffset"]) {
|
||||||
|
qCDebug(modelformat) << "byteOffset: " << byteOffset;
|
||||||
|
}
|
||||||
|
if (defined["componentType"]) {
|
||||||
|
qCDebug(modelformat) << "componentType: " << componentType;
|
||||||
|
}
|
||||||
|
if (defined["count"]) {
|
||||||
|
qCDebug(modelformat) << "count: " << count;
|
||||||
|
}
|
||||||
|
if (defined["type"]) {
|
||||||
|
qCDebug(modelformat) << "type: " << type;
|
||||||
|
}
|
||||||
|
if (defined["normalized"]) {
|
||||||
|
qCDebug(modelformat) << "normalized: " << (normalized ? "TRUE" : "FALSE");
|
||||||
|
}
|
||||||
|
if (defined["max"]) {
|
||||||
|
qCDebug(modelformat) << "max: ";
|
||||||
|
foreach(float m, max) {
|
||||||
|
qCDebug(modelformat) << m;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (defined["min"]) {
|
||||||
|
qCDebug(modelformat) << "min: ";
|
||||||
|
foreach(float m, min) {
|
||||||
|
qCDebug(modelformat) << m;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Animation
|
||||||
|
|
||||||
|
namespace GLTFChannelTargetPath {
|
||||||
|
enum Values {
|
||||||
|
TRANSLATION = 0,
|
||||||
|
ROTATION,
|
||||||
|
SCALE
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
struct GLTFChannelTarget {
|
||||||
|
int node;
|
||||||
|
int path;
|
||||||
|
QMap<QString, bool> defined;
|
||||||
|
void dump() {
|
||||||
|
if (defined["node"]) {
|
||||||
|
qCDebug(modelformat) << "node: " << node;
|
||||||
|
}
|
||||||
|
if (defined["path"]) {
|
||||||
|
qCDebug(modelformat) << "path: " << path;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct GLTFChannel {
|
||||||
|
int sampler;
|
||||||
|
GLTFChannelTarget target;
|
||||||
|
QMap<QString, bool> defined;
|
||||||
|
void dump() {
|
||||||
|
if (defined["sampler"]) {
|
||||||
|
qCDebug(modelformat) << "sampler: " << sampler;
|
||||||
|
}
|
||||||
|
if (defined["target"]) {
|
||||||
|
target.dump();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace GLTFAnimationSamplerInterpolation {
|
||||||
|
enum Values{
|
||||||
|
LINEAR = 0
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
struct GLTFAnimationSampler {
|
||||||
|
int input;
|
||||||
|
int output;
|
||||||
|
int interpolation;
|
||||||
|
QMap<QString, bool> defined;
|
||||||
|
void dump() {
|
||||||
|
if (defined["input"]) {
|
||||||
|
qCDebug(modelformat) << "input: " << input;
|
||||||
|
}
|
||||||
|
if (defined["output"]) {
|
||||||
|
qCDebug(modelformat) << "output: " << output;
|
||||||
|
}
|
||||||
|
if (defined["interpolation"]) {
|
||||||
|
qCDebug(modelformat) << "interpolation: " << interpolation;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct GLTFAnimation {
|
||||||
|
QVector<GLTFChannel> channels;
|
||||||
|
QVector<GLTFAnimationSampler> samplers;
|
||||||
|
QMap<QString, bool> defined;
|
||||||
|
void dump() {
|
||||||
|
if (defined["channels"]) {
|
||||||
|
foreach(auto channel, channels) channel.dump();
|
||||||
|
}
|
||||||
|
if (defined["samplers"]) {
|
||||||
|
foreach(auto sampler, samplers) sampler.dump();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct GLTFScene {
|
||||||
|
QString name;
|
||||||
|
QVector<int> nodes;
|
||||||
|
QMap<QString, bool> defined;
|
||||||
|
void dump() {
|
||||||
|
if (defined["name"]) {
|
||||||
|
qCDebug(modelformat) << "name: " << name;
|
||||||
|
}
|
||||||
|
if (defined["nodes"]) {
|
||||||
|
qCDebug(modelformat) << "nodes: ";
|
||||||
|
foreach(int node, nodes) qCDebug(modelformat) << node;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct GLTFSkin {
|
||||||
|
int inverseBindMatrices;
|
||||||
|
QVector<int> joints;
|
||||||
|
int skeleton;
|
||||||
|
QMap<QString, bool> defined;
|
||||||
|
void dump() {
|
||||||
|
if (defined["inverseBindMatrices"]) {
|
||||||
|
qCDebug(modelformat) << "inverseBindMatrices: " << inverseBindMatrices;
|
||||||
|
}
|
||||||
|
if (defined["skeleton"]) {
|
||||||
|
qCDebug(modelformat) << "skeleton: " << skeleton;
|
||||||
|
}
|
||||||
|
if (defined["joints"]) {
|
||||||
|
qCDebug(modelformat) << "joints: ";
|
||||||
|
foreach(int joint, joints) qCDebug(modelformat) << joint;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct GLTFTexture {
|
||||||
|
int sampler;
|
||||||
|
int source;
|
||||||
|
QMap<QString, bool> defined;
|
||||||
|
void dump() {
|
||||||
|
if (defined["sampler"]) {
|
||||||
|
qCDebug(modelformat) << "sampler: " << sampler;
|
||||||
|
}
|
||||||
|
if (defined["source"]) {
|
||||||
|
qCDebug(modelformat) << "source: " << sampler;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct GLTFFile {
|
||||||
|
GLTFAsset asset;
|
||||||
|
int scene = 0;
|
||||||
|
QVector<GLTFAccessor> accessors;
|
||||||
|
QVector<GLTFAnimation> animations;
|
||||||
|
QVector<GLTFBufferView> bufferviews;
|
||||||
|
QVector<GLTFBuffer> buffers;
|
||||||
|
QVector<GLTFCamera> cameras;
|
||||||
|
QVector<GLTFImage> images;
|
||||||
|
QVector<GLTFMaterial> materials;
|
||||||
|
QVector<GLTFMesh> meshes;
|
||||||
|
QVector<GLTFNode> nodes;
|
||||||
|
QVector<GLTFSampler> samplers;
|
||||||
|
QVector<GLTFScene> scenes;
|
||||||
|
QVector<GLTFSkin> skins;
|
||||||
|
QVector<GLTFTexture> textures;
|
||||||
|
QMap<QString, bool> defined;
|
||||||
|
void dump() {
|
||||||
|
if (defined["asset"]) {
|
||||||
|
asset.dump();
|
||||||
|
}
|
||||||
|
if (defined["scene"]) {
|
||||||
|
qCDebug(modelformat) << "scene: " << scene;
|
||||||
|
}
|
||||||
|
if (defined["accessors"]) {
|
||||||
|
foreach(auto acc, accessors) acc.dump();
|
||||||
|
}
|
||||||
|
if (defined["animations"]) {
|
||||||
|
foreach(auto ani, animations) ani.dump();
|
||||||
|
}
|
||||||
|
if (defined["bufferviews"]) {
|
||||||
|
foreach(auto bv, bufferviews) bv.dump();
|
||||||
|
}
|
||||||
|
if (defined["buffers"]) {
|
||||||
|
foreach(auto b, buffers) b.dump();
|
||||||
|
}
|
||||||
|
if (defined["cameras"]) {
|
||||||
|
foreach(auto c, cameras) c.dump();
|
||||||
|
}
|
||||||
|
if (defined["images"]) {
|
||||||
|
foreach(auto i, images) i.dump();
|
||||||
|
}
|
||||||
|
if (defined["materials"]) {
|
||||||
|
foreach(auto mat, materials) mat.dump();
|
||||||
|
}
|
||||||
|
if (defined["meshes"]) {
|
||||||
|
foreach(auto mes, meshes) mes.dump();
|
||||||
|
}
|
||||||
|
if (defined["nodes"]) {
|
||||||
|
foreach(auto nod, nodes) nod.dump();
|
||||||
|
}
|
||||||
|
if (defined["samplers"]) {
|
||||||
|
foreach(auto sa, samplers) sa.dump();
|
||||||
|
}
|
||||||
|
if (defined["scenes"]) {
|
||||||
|
foreach(auto sc, scenes) sc.dump();
|
||||||
|
}
|
||||||
|
if (defined["skins"]) {
|
||||||
|
foreach(auto sk, nodes) sk.dump();
|
||||||
|
}
|
||||||
|
if (defined["textures"]) {
|
||||||
|
foreach(auto tex, textures) tex.dump();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class GLTFReader : public QObject {
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
GLTFReader();
|
||||||
|
FBXGeometry* readGLTF(QByteArray& model, const QVariantHash& mapping,
|
||||||
|
const QUrl& url, bool loadLightmaps = true, float lightmapLevel = 1.0f);
|
||||||
|
private:
|
||||||
|
GLTFFile _file;
|
||||||
|
QUrl _url;
|
||||||
|
|
||||||
|
glm::mat4 getModelTransform(const GLTFNode& node);
|
||||||
|
|
||||||
|
bool buildGeometry(FBXGeometry& geometry, const QUrl& url);
|
||||||
|
bool parseGLTF(const QByteArray& model);
|
||||||
|
|
||||||
|
bool getStringVal(const QJsonObject& object, const QString& fieldname,
|
||||||
|
QString& value, QMap<QString, bool>& defined);
|
||||||
|
bool getBoolVal(const QJsonObject& object, const QString& fieldname,
|
||||||
|
bool& value, QMap<QString, bool>& defined);
|
||||||
|
bool getIntVal(const QJsonObject& object, const QString& fieldname,
|
||||||
|
int& value, QMap<QString, bool>& defined);
|
||||||
|
bool getDoubleVal(const QJsonObject& object, const QString& fieldname,
|
||||||
|
double& value, QMap<QString, bool>& defined);
|
||||||
|
bool getObjectVal(const QJsonObject& object, const QString& fieldname,
|
||||||
|
QJsonObject& value, QMap<QString, bool>& defined);
|
||||||
|
bool getIntArrayVal(const QJsonObject& object, const QString& fieldname,
|
||||||
|
QVector<int>& values, QMap<QString, bool>& defined);
|
||||||
|
bool getDoubleArrayVal(const QJsonObject& object, const QString& fieldname,
|
||||||
|
QVector<double>& values, QMap<QString, bool>& defined);
|
||||||
|
bool getObjectArrayVal(const QJsonObject& object, const QString& fieldname,
|
||||||
|
QJsonArray& objects, QMap<QString, bool>& defined);
|
||||||
|
|
||||||
|
int getMaterialAlphaMode(const QString& type);
|
||||||
|
int getAccessorType(const QString& type);
|
||||||
|
int getAnimationSamplerInterpolation(const QString& interpolation);
|
||||||
|
int getCameraType(const QString& type);
|
||||||
|
int getImageMimeType(const QString& mime);
|
||||||
|
int getMeshPrimitiveRenderingMode(const QString& type);
|
||||||
|
|
||||||
|
bool getIndexFromObject(const QJsonObject& object, const QString& field,
|
||||||
|
int& outidx, QMap<QString, bool>& defined);
|
||||||
|
|
||||||
|
bool setAsset(const QJsonObject& object);
|
||||||
|
bool addAccessor(const QJsonObject& object);
|
||||||
|
bool addAnimation(const QJsonObject& object);
|
||||||
|
bool addBufferView(const QJsonObject& object);
|
||||||
|
bool addBuffer(const QJsonObject& object);
|
||||||
|
bool addCamera(const QJsonObject& object);
|
||||||
|
bool addImage(const QJsonObject& object);
|
||||||
|
bool addMaterial(const QJsonObject& object);
|
||||||
|
bool addMesh(const QJsonObject& object);
|
||||||
|
bool addNode(const QJsonObject& object);
|
||||||
|
bool addSampler(const QJsonObject& object);
|
||||||
|
bool addScene(const QJsonObject& object);
|
||||||
|
bool addSkin(const QJsonObject& object);
|
||||||
|
bool addTexture(const QJsonObject& object);
|
||||||
|
|
||||||
|
bool readBinary(const QString& url, QByteArray& outdata);
|
||||||
|
|
||||||
|
template<typename T, typename L>
|
||||||
|
bool readArray(const QByteArray& bin, int byteOffset, int byteLength,
|
||||||
|
QVector<L>& outarray, int accessorType);
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
bool addArrayOfType(const QByteArray& bin, int byteOffset, int byteLength,
|
||||||
|
QVector<T>& outarray, int accessorType, int componentType);
|
||||||
|
|
||||||
|
void retriangulate(const QVector<int>& in_indices, const QVector<glm::vec3>& in_vertices,
|
||||||
|
const QVector<glm::vec3>& in_normals, QVector<int>& out_indices,
|
||||||
|
QVector<glm::vec3>& out_vertices, QVector<glm::vec3>& out_normals);
|
||||||
|
|
||||||
|
std::tuple<bool, QByteArray> requestData(QUrl& url);
|
||||||
|
QNetworkReply* request(QUrl& url, bool isTest);
|
||||||
|
bool doesResourceExist(const QString& url);
|
||||||
|
|
||||||
|
|
||||||
|
void setFBXMaterial(FBXMaterial& fbxmat, const GLTFMaterial& material);
|
||||||
|
FBXTexture getFBXTexture(const GLTFTexture& texture);
|
||||||
|
void fbxDebugDump(const FBXGeometry& fbxgeo);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // hifi_GLTFReader_h
|
|
@ -14,6 +14,7 @@
|
||||||
#include <FSTReader.h>
|
#include <FSTReader.h>
|
||||||
#include "FBXReader.h"
|
#include "FBXReader.h"
|
||||||
#include "OBJReader.h"
|
#include "OBJReader.h"
|
||||||
|
#include "GLTFReader.h"
|
||||||
|
|
||||||
#include <gpu/Batch.h>
|
#include <gpu/Batch.h>
|
||||||
#include <gpu/Stream.h>
|
#include <gpu/Stream.h>
|
||||||
|
@ -175,9 +176,12 @@ void GeometryReader::run() {
|
||||||
|
|
||||||
QString urlname = _url.path().toLower();
|
QString urlname = _url.path().toLower();
|
||||||
if (!urlname.isEmpty() && !_url.path().isEmpty() &&
|
if (!urlname.isEmpty() && !_url.path().isEmpty() &&
|
||||||
|
|
||||||
(_url.path().toLower().endsWith(".fbx") ||
|
(_url.path().toLower().endsWith(".fbx") ||
|
||||||
_url.path().toLower().endsWith(".obj") ||
|
_url.path().toLower().endsWith(".obj") ||
|
||||||
_url.path().toLower().endsWith(".obj.gz"))) {
|
_url.path().toLower().endsWith(".obj.gz") ||
|
||||||
|
_url.path().toLower().endsWith(".gltf"))) {
|
||||||
|
|
||||||
FBXGeometry::Pointer fbxGeometry;
|
FBXGeometry::Pointer fbxGeometry;
|
||||||
|
|
||||||
if (_url.path().toLower().endsWith(".fbx")) {
|
if (_url.path().toLower().endsWith(".fbx")) {
|
||||||
|
@ -189,12 +193,18 @@ void GeometryReader::run() {
|
||||||
fbxGeometry.reset(OBJReader().readOBJ(_data, _mapping, _combineParts, _url));
|
fbxGeometry.reset(OBJReader().readOBJ(_data, _mapping, _combineParts, _url));
|
||||||
} else if (_url.path().toLower().endsWith(".obj.gz")) {
|
} else if (_url.path().toLower().endsWith(".obj.gz")) {
|
||||||
QByteArray uncompressedData;
|
QByteArray uncompressedData;
|
||||||
if (gunzip(_data, uncompressedData)){
|
if (gunzip(_data, uncompressedData)) {
|
||||||
fbxGeometry.reset(OBJReader().readOBJ(uncompressedData, _mapping, _combineParts, _url));
|
fbxGeometry.reset(OBJReader().readOBJ(uncompressedData, _mapping, _combineParts, _url));
|
||||||
} else {
|
} else {
|
||||||
throw QString("failed to decompress .obj.gz" );
|
throw QString("failed to decompress .obj.gz");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} else if (_url.path().toLower().endsWith(".gltf")) {
|
||||||
|
std::shared_ptr<GLTFReader> glreader = std::make_shared<GLTFReader>();
|
||||||
|
fbxGeometry.reset(glreader->readGLTF(_data, _mapping, _url));
|
||||||
|
if (fbxGeometry->meshes.size() == 0 && fbxGeometry->joints.size() == 0) {
|
||||||
|
throw QString("empty geometry, possibly due to an unsupported GLTF version");
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
throw QString("unsupported format");
|
throw QString("unsupported format");
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue