glTF importer Demo

Imports a glTF model as the default avatar.
Geometry data and materials are imported.
No bone information is imported.
This commit is contained in:
Luis Cuenca 2017-09-05 13:32:51 -07:00
parent 304c6451eb
commit d7c525cf3a
11 changed files with 2082 additions and 14 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 539 KiB

View file

@ -0,0 +1,209 @@
{
"accessors" : [
{
"bufferView" : 0,
"componentType" : 5123,
"count" : 46356,
"max" : [
14358
],
"min" : [
0
],
"type" : "SCALAR"
},
{
"bufferView" : 1,
"componentType" : 5126,
"count" : 14359,
"max" : [
0.9449769854545593,
1.0,
0.9009739756584167
],
"min" : [
-0.9449769854545593,
-1.0,
-0.9009950160980225
],
"type" : "VEC3"
},
{
"bufferView" : 2,
"componentType" : 5126,
"count" : 14359,
"max" : [
1.0,
1.0,
1.0
],
"min" : [
-1.0,
-1.0,
-1.0
],
"type" : "VEC3"
},
{
"bufferView" : 3,
"componentType" : 5126,
"count" : 14359,
"max" : [
0.9999759793281555,
1.998665988445282
],
"min" : [
0.002448640065267682,
1.0005531199858524
],
"type" : "VEC2"
}
],
"asset" : {
"generator" : "Khronos Blender glTF 2.0 exporter",
"version" : "2.0"
},
"bufferViews" : [
{
"buffer" : 0,
"byteLength" : 92712,
"byteOffset" : 0,
"target" : 34963
},
{
"buffer" : 0,
"byteLength" : 172308,
"byteOffset" : 92712,
"target" : 34962
},
{
"buffer" : 0,
"byteLength" : 172308,
"byteOffset" : 265020,
"target" : 34962
},
{
"buffer" : 0,
"byteLength" : 114872,
"byteOffset" : 437328,
"target" : 34962
}
],
"buffers" : [
{
"byteLength" : 552200,
"uri" : "DamagedHelmet.bin"
}
],
"images" : [
{
"uri" : "Default_albedo.jpg"
},
{
"uri" : "Default_normal.jpg"
},
{
"uri" : "Default_metalRoughness.jpg"
},
{
"uri" : "Default_emissive.jpg"
},
{
"uri" : "Default_AO.jpg"
}
],
"materials" : [
{
"emissiveFactor" : [
1.0,
1.0,
1.0
],
"emissiveTexture" : {
"index" : 3
},
"name" : "glTF Material",
"normalTexture" : {
"index" : 1
},
"occlusionTexture" : {
"index" : 4
},
"pbrMetallicRoughness" : {
"baseColorTexture" : {
"index" : 0
},
"metallicRoughnessTexture" : {
"index" : 2
}
}
}
],
"meshes" : [
{
"name" : "mesh_helmet_LP_13930damagedHelmet",
"primitives" : [
{
"attributes" : {
"NORMAL" : 2,
"POSITION" : 1,
"TEXCOORD_0" : 3
},
"indices" : 0,
"material" : 0
}
]
}
],
"nodes" : [
{
"mesh" : 0,
"name" : "node_damagedHelmet_-6514",
"rotation" : [
0.7071068286895752,
0.15,
-0.25,
0.7071068286895752
],
"scale" : [
0.5,
0.5,
0.5
]
}
],
"samplers" : [
{}
],
"scene" : 0,
"scenes" : [
{
"name" : "Scene",
"nodes" : [
0
]
}
],
"textures" : [
{
"sampler" : 0,
"source" : 0
},
{
"sampler" : 0,
"source" : 1
},
{
"sampler" : 0,
"source" : 2
},
{
"sampler" : 0,
"source" : 3
},
{
"sampler" : 0,
"source" : 4
}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 353 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 914 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 95 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 506 KiB

View file

@ -1,7 +1,7 @@
name = mannequin
name = Avocado
type = body+head
scale = 1
filename = mannequin/mannequin.baked.fbx
filename = DamagedHelmet/DamagedHelmet.gltf
joint = jointEyeLeft = LeftEye
joint = jointRightHand = RightHand
joint = jointHead = Head

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,582 @@
//
// GLTFReader.h
// interface/src/renderer
//
// 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 "FBXReader.h"
#include <QtNetwork/QNetworkReply>
#include "ModelFormatLogging.h"
#include <memory.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> GLTFReader::requestData(QUrl& url);
QNetworkReply* GLTFReader::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

View file

@ -14,6 +14,7 @@
#include <FSTReader.h>
#include "FBXReader.h"
#include "OBJReader.h"
#include "GLTFReader.h"
#include <gpu/Batch.h>
#include <gpu/Stream.h>
@ -173,9 +174,10 @@ void GeometryReader::run() {
QString urlname = _url.path().toLower();
if (!urlname.isEmpty() && !_url.path().isEmpty() &&
(_url.path().toLower().endsWith(".fbx") ||
_url.path().toLower().endsWith(".obj") ||
_url.path().toLower().endsWith(".obj.gz"))) {
(_url.path().toLower().endsWith(".fbx") ||
_url.path().toLower().endsWith(".obj") ||
_url.path().toLower().endsWith(".obj.gz") ||
_url.path().toLower().endsWith(".gltf"))) {
FBXGeometry::Pointer fbxGeometry;
if (_url.path().toLower().endsWith(".fbx")) {
@ -183,17 +185,28 @@ void GeometryReader::run() {
if (fbxGeometry->meshes.size() == 0 && fbxGeometry->joints.size() == 0) {
throw QString("empty geometry, possibly due to an unsupported FBX version");
}
} else if (_url.path().toLower().endsWith(".obj")) {
}
else if (_url.path().toLower().endsWith(".obj")) {
fbxGeometry.reset(OBJReader().readOBJ(_data, _mapping, _combineParts, _url));
} else if (_url.path().toLower().endsWith(".obj.gz")) {
QByteArray uncompressedData;
if (gunzip(_data, uncompressedData)){
fbxGeometry.reset(OBJReader().readOBJ(uncompressedData, _mapping, _combineParts, _url));
} else {
throw QString("failed to decompress .obj.gz" );
}
}
else if (_url.path().toLower().endsWith(".obj.gz")) {
QByteArray uncompressedData;
if (gunzip(_data, uncompressedData)) {
fbxGeometry.reset(OBJReader().readOBJ(uncompressedData, _mapping, _combineParts, _url));
}
else {
throw QString("failed to decompress .obj.gz");
}
} else {
}
else if (_url.path().toLower().endsWith(".gltf")) {
std::unique_ptr<GLTFReader> glreader = std::make_unique<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 {
throw QString("unsupported format");
}