Merge pull request #14394 from sabrina-shanman/hfm_serializer

(case 20005) Create HFMSerializer interface for model loaders
This commit is contained in:
Shannon Romano 2018-11-28 11:10:27 -08:00 committed by GitHub
commit ff934a8f87
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
31 changed files with 283 additions and 221 deletions

View file

@ -17,6 +17,7 @@
#include <QTemporaryDir> #include <QTemporaryDir>
#include <FSTReader.h> #include <FSTReader.h>
#include <FBXSerializer.h>
#include <OffscreenUi.h> #include <OffscreenUi.h>
#include "ModelSelector.h" #include "ModelSelector.h"
@ -108,7 +109,7 @@ bool ModelPackager::loadModel() {
qCDebug(interfaceapp) << "Reading FBX file : " << _fbxInfo.filePath(); qCDebug(interfaceapp) << "Reading FBX file : " << _fbxInfo.filePath();
QByteArray fbxContents = fbx.readAll(); QByteArray fbxContents = fbx.readAll();
_hfmModel.reset(readFBX(fbxContents, QVariantHash(), _fbxInfo.filePath())); _hfmModel = FBXSerializer().read(fbxContents, QVariantHash(), _fbxInfo.filePath());
// make sure we have some basic mappings // make sure we have some basic mappings
populateBasicMapping(_mapping, _fbxInfo.filePath(), *_hfmModel); populateBasicMapping(_mapping, _fbxInfo.filePath(), *_hfmModel);

View file

@ -45,7 +45,7 @@ private:
QString _scriptDir; QString _scriptDir;
QVariantHash _mapping; QVariantHash _mapping;
std::unique_ptr<hfm::Model> _hfmModel; std::shared_ptr<hfm::Model> _hfmModel;
QStringList _textures; QStringList _textures;
QStringList _scripts; QStringList _scripts;
}; };

View file

@ -14,7 +14,7 @@
#include <QDialog> #include <QDialog>
#include <FBXReader.h> #include <hfm/HFM.h>
#include <FSTReader.h> #include <FSTReader.h>
#include "ui/ModelsBrowser.h" #include "ui/ModelsBrowser.h"

View file

@ -149,7 +149,7 @@ void CollisionPick::computeShapeInfo(const CollisionRegion& pick, ShapeInfo& sha
uint32_t numIndices = (uint32_t)meshPart.triangleIndices.size(); uint32_t numIndices = (uint32_t)meshPart.triangleIndices.size();
// TODO: assert rather than workaround after we start sanitizing HFMMesh higher up // TODO: assert rather than workaround after we start sanitizing HFMMesh higher up
//assert(numIndices % TRIANGLE_STRIDE == 0); //assert(numIndices % TRIANGLE_STRIDE == 0);
numIndices -= numIndices % TRIANGLE_STRIDE; // WORKAROUND lack of sanity checking in FBXReader numIndices -= numIndices % TRIANGLE_STRIDE; // WORKAROUND lack of sanity checking in FBXSerializer
for (uint32_t j = 0; j < numIndices; j += TRIANGLE_STRIDE) { for (uint32_t j = 0; j < numIndices; j += TRIANGLE_STRIDE) {
glm::vec3 p0 = mesh.vertices[meshPart.triangleIndices[j]]; glm::vec3 p0 = mesh.vertices[meshPart.triangleIndices[j]];
@ -170,7 +170,7 @@ void CollisionPick::computeShapeInfo(const CollisionRegion& pick, ShapeInfo& sha
numIndices = (uint32_t)meshPart.quadIndices.size(); numIndices = (uint32_t)meshPart.quadIndices.size();
// TODO: assert rather than workaround after we start sanitizing HFMMesh higher up // TODO: assert rather than workaround after we start sanitizing HFMMesh higher up
//assert(numIndices % QUAD_STRIDE == 0); //assert(numIndices % QUAD_STRIDE == 0);
numIndices -= numIndices % QUAD_STRIDE; // WORKAROUND lack of sanity checking in FBXReader numIndices -= numIndices % QUAD_STRIDE; // WORKAROUND lack of sanity checking in FBXSerializer
for (uint32_t j = 0; j < numIndices; j += QUAD_STRIDE) { for (uint32_t j = 0; j < numIndices; j += QUAD_STRIDE) {
glm::vec3 p0 = mesh.vertices[meshPart.quadIndices[j]]; glm::vec3 p0 = mesh.vertices[meshPart.quadIndices[j]];
@ -305,7 +305,7 @@ void CollisionPick::computeShapeInfo(const CollisionRegion& pick, ShapeInfo& sha
auto numIndices = meshPart.triangleIndices.count(); auto numIndices = meshPart.triangleIndices.count();
// TODO: assert rather than workaround after we start sanitizing HFMMesh higher up // TODO: assert rather than workaround after we start sanitizing HFMMesh higher up
//assert(numIndices% TRIANGLE_STRIDE == 0); //assert(numIndices% TRIANGLE_STRIDE == 0);
numIndices -= numIndices % TRIANGLE_STRIDE; // WORKAROUND lack of sanity checking in FBXReader numIndices -= numIndices % TRIANGLE_STRIDE; // WORKAROUND lack of sanity checking in FBXSerializer
auto indexItr = meshPart.triangleIndices.cbegin(); auto indexItr = meshPart.triangleIndices.cbegin();
while (indexItr != meshPart.triangleIndices.cend()) { while (indexItr != meshPart.triangleIndices.cend()) {

View file

@ -15,7 +15,7 @@
#include <glm/glm.hpp> #include <glm/glm.hpp>
#include <glm/gtc/quaternion.hpp> #include <glm/gtc/quaternion.hpp>
#include <FBXReader.h> #include <FBXSerializer.h>
#include "AnimPose.h" #include "AnimPose.h"
class AnimSkeleton { class AnimSkeleton {

View file

@ -71,7 +71,7 @@ void AnimationReader::run() {
// Parse the FBX directly from the QNetworkReply // Parse the FBX directly from the QNetworkReply
HFMModel::Pointer hfmModel; HFMModel::Pointer hfmModel;
if (_url.path().toLower().endsWith(".fbx")) { if (_url.path().toLower().endsWith(".fbx")) {
hfmModel.reset(readFBX(_data, QVariantHash(), _url.path())); hfmModel = FBXSerializer().read(_data, QVariantHash(), _url.path());
} else { } else {
QString errorStr("usupported format"); QString errorStr("usupported format");
emit onError(299, errorStr); emit onError(299, errorStr);

View file

@ -17,7 +17,7 @@
#include <QtScript/QScriptValue> #include <QtScript/QScriptValue>
#include <DependencyManager.h> #include <DependencyManager.h>
#include <FBXReader.h> #include <FBXSerializer.h>
#include <ResourceCache.h> #include <ResourceCache.h>
class Animation; class Animation;

View file

@ -15,7 +15,7 @@
#include <QObject> #include <QObject>
#include <QScriptable> #include <QScriptable>
#include <FBXReader.h> #include <FBXSerializer.h>
class QScriptEngine; class QScriptEngine;

View file

@ -27,7 +27,7 @@
#include <PathUtils.h> #include <PathUtils.h>
#include <FBXReader.h> #include <FBXSerializer.h>
#include <FBXWriter.h> #include <FBXWriter.h>
#include "ModelBakingLoggingCategory.h" #include "ModelBakingLoggingCategory.h"
@ -187,10 +187,10 @@ void FBXBaker::importScene() {
return; return;
} }
FBXReader reader; FBXSerializer fbxSerializer;
qCDebug(model_baking) << "Parsing" << _modelURL; qCDebug(model_baking) << "Parsing" << _modelURL;
_rootNode = reader._rootNode = reader.parseFBX(&fbxFile); _rootNode = fbxSerializer._rootNode = fbxSerializer.parseFBX(&fbxFile);
#ifdef HIFI_DUMP_FBX #ifdef HIFI_DUMP_FBX
{ {
@ -206,8 +206,8 @@ void FBXBaker::importScene() {
} }
#endif #endif
_hfmModel = reader.extractHFMModel({}, _modelURL.toString()); _hfmModel = fbxSerializer.extractHFMModel({}, _modelURL.toString());
_textureContentMap = reader._textureContent; _textureContentMap = fbxSerializer._textureContent;
} }
void FBXBaker::rewriteAndBakeSceneModels() { void FBXBaker::rewriteAndBakeSceneModels() {
@ -232,7 +232,7 @@ void FBXBaker::rewriteAndBakeSceneModels() {
if (objectChild.name == "Geometry") { if (objectChild.name == "Geometry") {
// TODO Pull this out of _hfmModel instead so we don't have to reprocess it // TODO Pull this out of _hfmModel instead so we don't have to reprocess it
auto extractedMesh = FBXReader::extractMesh(objectChild, meshIndex, false); auto extractedMesh = FBXSerializer::extractMesh(objectChild, meshIndex, false);
// Callback to get MaterialID // Callback to get MaterialID
GetMaterialIDCallback materialIDcallback = [&extractedMesh](int partIndex) { GetMaterialIDCallback materialIDcallback = [&extractedMesh](int partIndex) {

View file

@ -13,7 +13,6 @@
#include <PathUtils.h> #include <PathUtils.h>
#include <FBXReader.h>
#include <FBXWriter.h> #include <FBXWriter.h>
#ifdef _WIN32 #ifdef _WIN32

View file

@ -14,7 +14,7 @@
#include <PathUtils.h> #include <PathUtils.h>
#include <NetworkAccessManager.h> #include <NetworkAccessManager.h>
#include "OBJReader.h" #include "OBJSerializer.h"
#include "FBXWriter.h" #include "FBXWriter.h"
const double UNIT_SCALE_FACTOR = 100.0; const double UNIT_SCALE_FACTOR = 100.0;
@ -143,9 +143,10 @@ void OBJBaker::bakeOBJ() {
QByteArray objData = objFile.readAll(); QByteArray objData = objFile.readAll();
bool combineParts = true; // set true so that OBJReader reads material info from material library OBJSerializer serializer;
OBJReader reader; QVariantHash mapping;
auto geometry = reader.readOBJ(objData, QVariantHash(), combineParts, _modelURL); mapping["combineParts"] = true; // set true so that OBJSerializer reads material info from material library
auto geometry = serializer.read(objData, mapping, _modelURL);
// Write OBJ Data as FBX tree nodes // Write OBJ Data as FBX tree nodes
createFBXNodeTree(_rootNode, *geometry); createFBXNodeTree(_rootNode, *geometry);
@ -219,7 +220,7 @@ void OBJBaker::createFBXNodeTree(FBXNode& rootNode, HFMModel& hfmModel) {
FBXNode materialNode; FBXNode materialNode;
materialNode.name = MATERIAL_NODE_NAME; materialNode.name = MATERIAL_NODE_NAME;
if (hfmModel.materials.size() == 1) { if (hfmModel.materials.size() == 1) {
// case when no material information is provided, OBJReader considers it as a single default material // case when no material information is provided, OBJSerializer considers it as a single default material
for (auto& materialID : hfmModel.materials.keys()) { for (auto& materialID : hfmModel.materials.keys()) {
setMaterialNodeProperties(materialNode, materialID, hfmModel); setMaterialNodeProperties(materialNode, materialID, hfmModel);
} }

View file

@ -421,7 +421,7 @@ void RenderableModelEntityItem::computeShapeInfo(ShapeInfo& shapeInfo) {
uint32_t numIndices = (uint32_t)meshPart.triangleIndices.size(); uint32_t numIndices = (uint32_t)meshPart.triangleIndices.size();
// TODO: assert rather than workaround after we start sanitizing HFMMesh higher up // TODO: assert rather than workaround after we start sanitizing HFMMesh higher up
//assert(numIndices % TRIANGLE_STRIDE == 0); //assert(numIndices % TRIANGLE_STRIDE == 0);
numIndices -= numIndices % TRIANGLE_STRIDE; // WORKAROUND lack of sanity checking in FBXReader numIndices -= numIndices % TRIANGLE_STRIDE; // WORKAROUND lack of sanity checking in FBXSerializer
for (uint32_t j = 0; j < numIndices; j += TRIANGLE_STRIDE) { for (uint32_t j = 0; j < numIndices; j += TRIANGLE_STRIDE) {
glm::vec3 p0 = mesh.vertices[meshPart.triangleIndices[j]]; glm::vec3 p0 = mesh.vertices[meshPart.triangleIndices[j]];
@ -442,7 +442,7 @@ void RenderableModelEntityItem::computeShapeInfo(ShapeInfo& shapeInfo) {
numIndices = (uint32_t)meshPart.quadIndices.size(); numIndices = (uint32_t)meshPart.quadIndices.size();
// TODO: assert rather than workaround after we start sanitizing HFMMesh higher up // TODO: assert rather than workaround after we start sanitizing HFMMesh higher up
//assert(numIndices % QUAD_STRIDE == 0); //assert(numIndices % QUAD_STRIDE == 0);
numIndices -= numIndices % QUAD_STRIDE; // WORKAROUND lack of sanity checking in FBXReader numIndices -= numIndices % QUAD_STRIDE; // WORKAROUND lack of sanity checking in FBXSerializer
for (uint32_t j = 0; j < numIndices; j += QUAD_STRIDE) { for (uint32_t j = 0; j < numIndices; j += QUAD_STRIDE) {
glm::vec3 p0 = mesh.vertices[meshPart.quadIndices[j]]; glm::vec3 p0 = mesh.vertices[meshPart.quadIndices[j]];
@ -595,7 +595,7 @@ void RenderableModelEntityItem::computeShapeInfo(ShapeInfo& shapeInfo) {
if (partItr->_topology == graphics::Mesh::TRIANGLES) { if (partItr->_topology == graphics::Mesh::TRIANGLES) {
// TODO: assert rather than workaround after we start sanitizing HFMMesh higher up // TODO: assert rather than workaround after we start sanitizing HFMMesh higher up
//assert(numIndices % TRIANGLE_STRIDE == 0); //assert(numIndices % TRIANGLE_STRIDE == 0);
numIndices -= numIndices % TRIANGLE_STRIDE; // WORKAROUND lack of sanity checking in FBXReader numIndices -= numIndices % TRIANGLE_STRIDE; // WORKAROUND lack of sanity checking in FBXSerializer
auto indexItr = indices.cbegin<const gpu::BufferView::Index>() + partItr->_startIndex; auto indexItr = indices.cbegin<const gpu::BufferView::Index>() + partItr->_startIndex;
auto indexEnd = indexItr + numIndices; auto indexEnd = indexItr + numIndices;
@ -652,7 +652,7 @@ void RenderableModelEntityItem::computeShapeInfo(ShapeInfo& shapeInfo) {
if (partItr->_topology == graphics::Mesh::TRIANGLES) { if (partItr->_topology == graphics::Mesh::TRIANGLES) {
// TODO: assert rather than workaround after we start sanitizing HFMMesh higher up // TODO: assert rather than workaround after we start sanitizing HFMMesh higher up
//assert(numIndices% TRIANGLE_STRIDE == 0); //assert(numIndices% TRIANGLE_STRIDE == 0);
numIndices -= numIndices % TRIANGLE_STRIDE; // WORKAROUND lack of sanity checking in FBXReader numIndices -= numIndices % TRIANGLE_STRIDE; // WORKAROUND lack of sanity checking in FBXSerializer
auto indexItr = indices.cbegin<const gpu::BufferView::Index>() + partItr->_startIndex; auto indexItr = indices.cbegin<const gpu::BufferView::Index>() + partItr->_startIndex;
auto indexEnd = indexItr + numIndices; auto indexEnd = indexItr + numIndices;

View file

@ -33,7 +33,7 @@ using NormalType = glm::vec3;
#define FBX_NORMAL_ELEMENT gpu::Element::VEC3F_XYZ #define FBX_NORMAL_ELEMENT gpu::Element::VEC3F_XYZ
#endif #endif
// See comment in FBXReader::parseFBX(). // See comment in FBXSerializer::parseFBX().
static const int FBX_HEADER_BYTES_BEFORE_VERSION = 23; static const int FBX_HEADER_BYTES_BEFORE_VERSION = 23;
static const QByteArray FBX_BINARY_PROLOG("Kaydara FBX Binary "); static const QByteArray FBX_BINARY_PROLOG("Kaydara FBX Binary ");
static const QByteArray FBX_BINARY_PROLOG2("\0\x1a\0", 3); static const QByteArray FBX_BINARY_PROLOG2("\0\x1a\0", 3);

View file

@ -1,6 +1,6 @@
// //
// FBXReader.cpp // FBXSerializer.cpp
// interface/src/renderer // libraries/fbx/src
// //
// Created by Andrzej Kapolka on 9/18/13. // Created by Andrzej Kapolka on 9/18/13.
// Copyright 2013 High Fidelity, Inc. // Copyright 2013 High Fidelity, Inc.
@ -9,7 +9,7 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
// //
#include "FBXReader.h" #include "FBXSerializer.h"
#include <iostream> #include <iostream>
#include <QBuffer> #include <QBuffer>
@ -36,7 +36,7 @@
#include <hfm/ModelFormatLogging.h> #include <hfm/ModelFormatLogging.h>
// TOOL: Uncomment the following line to enable the filtering of all the unkwnon fields of a node so we can break point easily while loading a model with problems... // TOOL: Uncomment the following line to enable the filtering of all the unkwnon fields of a node so we can break point easily while loading a model with problems...
//#define DEBUG_FBXREADER //#define DEBUG_FBXSERIALIZER
using namespace std; using namespace std;
@ -254,13 +254,13 @@ HFMBlendshape extractBlendshape(const FBXNode& object) {
HFMBlendshape blendshape; HFMBlendshape blendshape;
foreach (const FBXNode& data, object.children) { foreach (const FBXNode& data, object.children) {
if (data.name == "Indexes") { if (data.name == "Indexes") {
blendshape.indices = FBXReader::getIntVector(data); blendshape.indices = FBXSerializer::getIntVector(data);
} else if (data.name == "Vertices") { } else if (data.name == "Vertices") {
blendshape.vertices = FBXReader::createVec3Vector(FBXReader::getDoubleVector(data)); blendshape.vertices = FBXSerializer::createVec3Vector(FBXSerializer::getDoubleVector(data));
} else if (data.name == "Normals") { } else if (data.name == "Normals") {
blendshape.normals = FBXReader::createVec3Vector(FBXReader::getDoubleVector(data)); blendshape.normals = FBXSerializer::createVec3Vector(FBXSerializer::getDoubleVector(data));
} }
} }
return blendshape; return blendshape;
@ -384,7 +384,7 @@ HFMLight extractLight(const FBXNode& object) {
if (propname == "Intensity") { if (propname == "Intensity") {
light.intensity = 0.01f * property.properties.at(valIndex).value<float>(); light.intensity = 0.01f * property.properties.at(valIndex).value<float>();
} else if (propname == "Color") { } else if (propname == "Color") {
light.color = FBXReader::getVec3(property.properties, valIndex); light.color = FBXSerializer::getVec3(property.properties, valIndex);
} }
} }
} }
@ -392,7 +392,7 @@ HFMLight extractLight(const FBXNode& object) {
|| subobject.name == "TypeFlags") { || subobject.name == "TypeFlags") {
} }
} }
#if defined(DEBUG_FBXREADER) #if defined(DEBUG_FBXSERIALIZER)
QString type = object.properties.at(0).toString(); QString type = object.properties.at(0).toString();
type = object.properties.at(1).toString(); type = object.properties.at(1).toString();
@ -441,7 +441,7 @@ QMap<QString, glm::quat> getJointRotationOffsets(const QVariantHash& mapping) {
return jointRotationOffsets; return jointRotationOffsets;
} }
HFMModel* FBXReader::extractHFMModel(const QVariantHash& mapping, const QString& url) { HFMModel* FBXSerializer::extractHFMModel(const QVariantHash& mapping, const QString& url) {
const FBXNode& node = _rootNode; const FBXNode& node = _rootNode;
QMap<QString, ExtractedMesh> meshes; QMap<QString, ExtractedMesh> meshes;
QHash<QString, QString> modelIDsToNames; QHash<QString, QString> modelIDsToNames;
@ -512,7 +512,7 @@ HFMModel* FBXReader::extractHFMModel(const QVariantHash& mapping, const QString&
} }
} }
QMultiHash<QString, WeightedIndex> blendshapeChannelIndices; QMultiHash<QString, WeightedIndex> blendshapeChannelIndices;
#if defined(DEBUG_FBXREADER) #if defined(DEBUG_FBXSERIALIZER)
int unknown = 0; int unknown = 0;
#endif #endif
HFMModel* hfmModelPtr = new HFMModel; HFMModel* hfmModelPtr = new HFMModel;
@ -760,7 +760,7 @@ HFMModel* FBXReader::extractHFMModel(const QVariantHash& mapping, const QString&
extractBlendshape(subobject) }; extractBlendshape(subobject) };
blendshapes.append(blendshape); blendshapes.append(blendshape);
} }
#if defined(DEBUG_FBXREADER) #if defined(DEBUG_FBXSERIALIZER)
else if (subobject.name == "TypeFlags") { else if (subobject.name == "TypeFlags") {
QString attributetype = subobject.properties.at(0).toString(); QString attributetype = subobject.properties.at(0).toString();
if (!attributetype.empty()) { if (!attributetype.empty()) {
@ -886,7 +886,7 @@ HFMModel* FBXReader::extractHFMModel(const QVariantHash& mapping, const QString&
tex.scaling.z = 1.0f; tex.scaling.z = 1.0f;
} }
} }
#if defined(DEBUG_FBXREADER) #if defined(DEBUG_FBXSERIALIZER)
else { else {
QString propName = v; QString propName = v;
unknown++; unknown++;
@ -895,7 +895,7 @@ HFMModel* FBXReader::extractHFMModel(const QVariantHash& mapping, const QString&
} }
} }
} }
#if defined(DEBUG_FBXREADER) #if defined(DEBUG_FBXSERIALIZER)
else { else {
if (subobject.name == "Type") { if (subobject.name == "Type") {
} else if (subobject.name == "Version") { } else if (subobject.name == "Version") {
@ -1068,7 +1068,7 @@ HFMModel* FBXReader::extractHFMModel(const QVariantHash& mapping, const QString&
} }
} }
} }
#if defined(DEBUG_FBXREADER) #if defined(DEBUG_FBXSERIALIZER)
else { else {
QString propname = subobject.name.data(); QString propname = subobject.name.data();
int unknown = 0; int unknown = 0;
@ -1085,7 +1085,7 @@ HFMModel* FBXReader::extractHFMModel(const QVariantHash& mapping, const QString&
} else if (object.name == "NodeAttribute") { } else if (object.name == "NodeAttribute") {
#if defined(DEBUG_FBXREADER) #if defined(DEBUG_FBXSERIALIZER)
std::vector<QString> properties; std::vector<QString> properties;
foreach(const QVariant& v, object.properties) { foreach(const QVariant& v, object.properties) {
properties.push_back(v.toString()); properties.push_back(v.toString());
@ -1148,7 +1148,7 @@ HFMModel* FBXReader::extractHFMModel(const QVariantHash& mapping, const QString&
animationCurves.insert(getID(object.properties), curve); animationCurves.insert(getID(object.properties), curve);
} }
#if defined(DEBUG_FBXREADER) #if defined(DEBUG_FBXSERIALIZER)
else { else {
QString objectname = object.name.data(); QString objectname = object.name.data();
if ( objectname == "Pose" if ( objectname == "Pose"
@ -1239,7 +1239,7 @@ HFMModel* FBXReader::extractHFMModel(const QVariantHash& mapping, const QString&
} }
} }
} }
#if defined(DEBUG_FBXREADER) #if defined(DEBUG_FBXSERIALIZER)
else { else {
QString objectname = child.name.data(); QString objectname = child.name.data();
if ( objectname == "Pose" if ( objectname == "Pose"
@ -1833,17 +1833,11 @@ HFMModel* FBXReader::extractHFMModel(const QVariantHash& mapping, const QString&
return hfmModelPtr; return hfmModelPtr;
} }
HFMModel* readFBX(const QByteArray& data, const QVariantHash& mapping, const QString& url, bool loadLightmaps, float lightmapLevel) { HFMModel::Pointer FBXSerializer::read(const QByteArray& data, const QVariantHash& mapping, const QUrl& url) {
QBuffer buffer(const_cast<QByteArray*>(&data)); QBuffer buffer(const_cast<QByteArray*>(&data));
buffer.open(QIODevice::ReadOnly); buffer.open(QIODevice::ReadOnly);
return readFBX(&buffer, mapping, url, loadLightmaps, lightmapLevel);
}
HFMModel* readFBX(QIODevice* device, const QVariantHash& mapping, const QString& url, bool loadLightmaps, float lightmapLevel) { _rootNode = parseFBX(&buffer);
FBXReader reader;
reader._rootNode = FBXReader::parseFBX(device);
reader._loadLightmaps = loadLightmaps;
reader._lightmapLevel = lightmapLevel;
return reader.extractHFMModel(mapping, url); return HFMModel::Pointer(extractHFMModel(mapping, url.toString()));
} }

View file

@ -1,6 +1,6 @@
// //
// FBXReader.h // FBXSerializer.h
// interface/src/renderer // libraries/fbx/src
// //
// Created by Andrzej Kapolka on 9/18/13. // Created by Andrzej Kapolka on 9/18/13.
// Copyright 2013 High Fidelity, Inc. // Copyright 2013 High Fidelity, Inc.
@ -9,8 +9,8 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
// //
#ifndef hifi_FBXReader_h #ifndef hifi_FBXSerializer_h
#define hifi_FBXReader_h #define hifi_FBXSerializer_h
#include <QtGlobal> #include <QtGlobal>
#include <QMetaType> #include <QMetaType>
@ -27,7 +27,7 @@
#include <Transform.h> #include <Transform.h>
#include "FBX.h" #include "FBX.h"
#include <hfm/HFM.h> #include <hfm/HFMSerializer.h>
#include <graphics/Geometry.h> #include <graphics/Geometry.h>
#include <graphics/Material.h> #include <graphics/Material.h>
@ -35,14 +35,6 @@
class QIODevice; class QIODevice;
class FBXNode; class FBXNode;
/// Reads HFMModel from the supplied model and mapping data.
/// \exception QString if an error occurs in parsing
HFMModel* readFBX(const QByteArray& data, const QVariantHash& mapping, const QString& url = "", bool loadLightmaps = true, float lightmapLevel = 1.0f);
/// Reads HFMModel from the supplied model and mapping data.
/// \exception QString if an error occurs in parsing
HFMModel* readFBX(QIODevice* device, const QVariantHash& mapping, const QString& url = "", bool loadLightmaps = true, float lightmapLevel = 1.0f);
class TextureParam { class TextureParam {
public: public:
glm::vec2 UVTranslation; glm::vec2 UVTranslation;
@ -102,9 +94,12 @@ public:
class ExtractedMesh; class ExtractedMesh;
class FBXReader { class FBXSerializer : public HFMSerializer {
public: public:
HFMModel* _hfmModel; HFMModel* _hfmModel;
/// Reads HFMModel from the supplied model and mapping data.
/// \exception QString if an error occurs in parsing
HFMModel::Pointer read(const QByteArray& data, const QVariantHash& mapping, const QUrl& url = QUrl()) override;
FBXNode _rootNode; FBXNode _rootNode;
static FBXNode parseFBX(QIODevice* device); static FBXNode parseFBX(QIODevice* device);
@ -147,9 +142,9 @@ public:
void consolidateHFMMaterials(const QVariantHash& mapping); void consolidateHFMMaterials(const QVariantHash& mapping);
bool _loadLightmaps = true; bool _loadLightmaps { true };
float _lightmapOffset = 0.0f; float _lightmapOffset { 0.0f };
float _lightmapLevel; float _lightmapLevel { 1.0f };
QMultiMap<QString, QString> _connectionParentMap; QMultiMap<QString, QString> _connectionParentMap;
QMultiMap<QString, QString> _connectionChildMap; QMultiMap<QString, QString> _connectionChildMap;
@ -166,4 +161,4 @@ public:
static QVector<double> getDoubleVector(const FBXNode& node); static QVector<double> getDoubleVector(const FBXNode& node);
}; };
#endif // hifi_FBXReader_h #endif // hifi_FBXSerializer_h

View file

@ -1,5 +1,5 @@
// //
// FBXReader_Material.cpp // FBXSerializer_Material.cpp
// interface/src/fbx // interface/src/fbx
// //
// Created by Sam Gateau on 8/27/2015. // Created by Sam Gateau on 8/27/2015.
@ -9,7 +9,7 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
// //
#include "FBXReader.h" #include "FBXSerializer.h"
#include <iostream> #include <iostream>
#include <memory> #include <memory>
@ -27,7 +27,7 @@
#include <hfm/ModelFormatLogging.h> #include <hfm/ModelFormatLogging.h>
HFMTexture FBXReader::getTexture(const QString& textureID) { HFMTexture FBXSerializer::getTexture(const QString& textureID) {
HFMTexture texture; HFMTexture texture;
const QByteArray& filepath = _textureFilepaths.value(textureID); const QByteArray& filepath = _textureFilepaths.value(textureID);
texture.content = _textureContent.value(filepath); texture.content = _textureContent.value(filepath);
@ -69,7 +69,7 @@ HFMTexture FBXReader::getTexture(const QString& textureID) {
return texture; return texture;
} }
void FBXReader::consolidateHFMMaterials(const QVariantHash& mapping) { void FBXSerializer::consolidateHFMMaterials(const QVariantHash& mapping) {
QString materialMapString = mapping.value("materialMap").toString(); QString materialMapString = mapping.value("materialMap").toString();
QJsonDocument materialMapDocument = QJsonDocument::fromJson(materialMapString.toUtf8()); QJsonDocument materialMapDocument = QJsonDocument::fromJson(materialMapString.toUtf8());

View file

@ -1,5 +1,5 @@
// //
// FBXReader_Mesh.cpp // FBXSerializer_Mesh.cpp
// interface/src/fbx // interface/src/fbx
// //
// Created by Sam Gateau on 8/27/2015. // Created by Sam Gateau on 8/27/2015.
@ -33,7 +33,7 @@
#include <LogHandler.h> #include <LogHandler.h>
#include <hfm/ModelFormatLogging.h> #include <hfm/ModelFormatLogging.h>
#include "FBXReader.h" #include "FBXSerializer.h"
#include <memory> #include <memory>
@ -191,7 +191,7 @@ void appendIndex(MeshData& data, QVector<int>& indices, int index, bool deduplic
} }
} }
ExtractedMesh FBXReader::extractMesh(const FBXNode& object, unsigned int& meshIndex, bool deduplicate) { ExtractedMesh FBXSerializer::extractMesh(const FBXNode& object, unsigned int& meshIndex, bool deduplicate) {
MeshData data; MeshData data;
data.extracted.mesh.meshIndex = meshIndex++; data.extracted.mesh.meshIndex = meshIndex++;
@ -254,7 +254,7 @@ ExtractedMesh FBXReader::extractMesh(const FBXNode& object, unsigned int& meshIn
data.colorsByVertex = true; data.colorsByVertex = true;
} }
#if defined(FBXREADER_KILL_BLACK_COLOR_ATTRIBUTE) #if defined(FBXSERIALIZER_KILL_BLACK_COLOR_ATTRIBUTE)
// Potential feature where we decide to kill the color attribute is to dark? // Potential feature where we decide to kill the color attribute is to dark?
// Tested with the model: // Tested with the model:
// https://hifi-public.s3.amazonaws.com/ryan/gardenLight2.fbx // https://hifi-public.s3.amazonaws.com/ryan/gardenLight2.fbx
@ -281,7 +281,7 @@ ExtractedMesh FBXReader::extractMesh(const FBXNode& object, unsigned int& meshIn
} else if (subdata.name == "Name") { } else if (subdata.name == "Name") {
attrib.name = subdata.properties.at(0).toString(); attrib.name = subdata.properties.at(0).toString();
} }
#if defined(DEBUG_FBXREADER) #if defined(DEBUG_FBXSERIALIZER)
else { else {
int unknown = 0; int unknown = 0;
QString subname = subdata.name.data(); QString subname = subdata.name.data();
@ -307,7 +307,7 @@ ExtractedMesh FBXReader::extractMesh(const FBXNode& object, unsigned int& meshIn
} else if (subdata.name == "Name") { } else if (subdata.name == "Name") {
attrib.name = subdata.properties.at(0).toString(); attrib.name = subdata.properties.at(0).toString();
} }
#if defined(DEBUG_FBXREADER) #if defined(DEBUG_FBXSERIALIZER)
else { else {
int unknown = 0; int unknown = 0;
QString subname = subdata.name.data(); QString subname = subdata.name.data();
@ -557,7 +557,7 @@ ExtractedMesh FBXReader::extractMesh(const FBXNode& object, unsigned int& meshIn
return data.extracted; return data.extracted;
} }
glm::vec3 FBXReader::normalizeDirForPacking(const glm::vec3& dir) { glm::vec3 FBXSerializer::normalizeDirForPacking(const glm::vec3& dir) {
auto maxCoord = glm::max(fabsf(dir.x), glm::max(fabsf(dir.y), fabsf(dir.z))); auto maxCoord = glm::max(fabsf(dir.x), glm::max(fabsf(dir.y), fabsf(dir.z)));
if (maxCoord > 1e-6f) { if (maxCoord > 1e-6f) {
return dir / maxCoord; return dir / maxCoord;
@ -565,7 +565,7 @@ glm::vec3 FBXReader::normalizeDirForPacking(const glm::vec3& dir) {
return dir; return dir;
} }
void FBXReader::buildModelMesh(HFMMesh& extractedMesh, const QString& url) { void FBXSerializer::buildModelMesh(HFMMesh& extractedMesh, const QString& url) {
unsigned int totalSourceIndices = 0; unsigned int totalSourceIndices = 0;
foreach(const HFMMeshPart& part, extractedMesh.parts) { foreach(const HFMMeshPart& part, extractedMesh.parts) {
totalSourceIndices += (part.quadTrianglesIndices.size() + part.triangleIndices.size()); totalSourceIndices += (part.quadTrianglesIndices.size() + part.triangleIndices.size());

View file

@ -1,5 +1,5 @@
// //
// FBXReader_Node.cpp // FBXSerializer_Node.cpp
// interface/src/fbx // interface/src/fbx
// //
// Created by Sam Gateau on 8/27/2015. // Created by Sam Gateau on 8/27/2015.
@ -9,7 +9,7 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
// //
#include "FBXReader.h" #include "FBXSerializer.h"
#include <iostream> #include <iostream>
#include <QtCore/QBuffer> #include <QtCore/QBuffer>
@ -345,7 +345,7 @@ FBXNode parseTextFBXNode(Tokenizer& tokenizer) {
return node; return node;
} }
FBXNode FBXReader::parseFBX(QIODevice* device) { FBXNode FBXSerializer::parseFBX(QIODevice* device) {
PROFILE_RANGE_EX(resource_parse, __FUNCTION__, 0xff0000ff, device); PROFILE_RANGE_EX(resource_parse, __FUNCTION__, 0xff0000ff, device);
// verify the prolog // verify the prolog
if (device->peek(FBX_BINARY_PROLOG.size()) != FBX_BINARY_PROLOG) { if (device->peek(FBX_BINARY_PROLOG.size()) != FBX_BINARY_PROLOG) {
@ -398,12 +398,12 @@ FBXNode FBXReader::parseFBX(QIODevice* device) {
} }
glm::vec3 FBXReader::getVec3(const QVariantList& properties, int index) { glm::vec3 FBXSerializer::getVec3(const QVariantList& properties, int index) {
return glm::vec3(properties.at(index).value<double>(), properties.at(index + 1).value<double>(), return glm::vec3(properties.at(index).value<double>(), properties.at(index + 1).value<double>(),
properties.at(index + 2).value<double>()); properties.at(index + 2).value<double>());
} }
QVector<glm::vec4> FBXReader::createVec4Vector(const QVector<double>& doubleVector) { QVector<glm::vec4> FBXSerializer::createVec4Vector(const QVector<double>& doubleVector) {
QVector<glm::vec4> values; QVector<glm::vec4> values;
for (const double* it = doubleVector.constData(), *end = it + ((doubleVector.size() / 4) * 4); it != end; ) { for (const double* it = doubleVector.constData(), *end = it + ((doubleVector.size() / 4) * 4); it != end; ) {
float x = *it++; float x = *it++;
@ -416,7 +416,7 @@ QVector<glm::vec4> FBXReader::createVec4Vector(const QVector<double>& doubleVect
} }
QVector<glm::vec4> FBXReader::createVec4VectorRGBA(const QVector<double>& doubleVector, glm::vec4& average) { QVector<glm::vec4> FBXSerializer::createVec4VectorRGBA(const QVector<double>& doubleVector, glm::vec4& average) {
QVector<glm::vec4> values; QVector<glm::vec4> values;
for (const double* it = doubleVector.constData(), *end = it + ((doubleVector.size() / 4) * 4); it != end; ) { for (const double* it = doubleVector.constData(), *end = it + ((doubleVector.size() / 4) * 4); it != end; ) {
float x = *it++; float x = *it++;
@ -433,7 +433,7 @@ QVector<glm::vec4> FBXReader::createVec4VectorRGBA(const QVector<double>& double
return values; return values;
} }
QVector<glm::vec3> FBXReader::createVec3Vector(const QVector<double>& doubleVector) { QVector<glm::vec3> FBXSerializer::createVec3Vector(const QVector<double>& doubleVector) {
QVector<glm::vec3> values; QVector<glm::vec3> values;
for (const double* it = doubleVector.constData(), *end = it + ((doubleVector.size() / 3) * 3); it != end; ) { for (const double* it = doubleVector.constData(), *end = it + ((doubleVector.size() / 3) * 3); it != end; ) {
float x = *it++; float x = *it++;
@ -444,7 +444,7 @@ QVector<glm::vec3> FBXReader::createVec3Vector(const QVector<double>& doubleVect
return values; return values;
} }
QVector<glm::vec2> FBXReader::createVec2Vector(const QVector<double>& doubleVector) { QVector<glm::vec2> FBXSerializer::createVec2Vector(const QVector<double>& doubleVector) {
QVector<glm::vec2> values; QVector<glm::vec2> values;
for (const double* it = doubleVector.constData(), *end = it + ((doubleVector.size() / 2) * 2); it != end; ) { for (const double* it = doubleVector.constData(), *end = it + ((doubleVector.size() / 2) * 2); it != end; ) {
float s = *it++; float s = *it++;
@ -454,14 +454,14 @@ QVector<glm::vec2> FBXReader::createVec2Vector(const QVector<double>& doubleVect
return values; return values;
} }
glm::mat4 FBXReader::createMat4(const QVector<double>& doubleVector) { glm::mat4 FBXSerializer::createMat4(const QVector<double>& doubleVector) {
return glm::mat4(doubleVector.at(0), doubleVector.at(1), doubleVector.at(2), doubleVector.at(3), return glm::mat4(doubleVector.at(0), doubleVector.at(1), doubleVector.at(2), doubleVector.at(3),
doubleVector.at(4), doubleVector.at(5), doubleVector.at(6), doubleVector.at(7), doubleVector.at(4), doubleVector.at(5), doubleVector.at(6), doubleVector.at(7),
doubleVector.at(8), doubleVector.at(9), doubleVector.at(10), doubleVector.at(11), doubleVector.at(8), doubleVector.at(9), doubleVector.at(10), doubleVector.at(11),
doubleVector.at(12), doubleVector.at(13), doubleVector.at(14), doubleVector.at(15)); doubleVector.at(12), doubleVector.at(13), doubleVector.at(14), doubleVector.at(15));
} }
QVector<int> FBXReader::getIntVector(const FBXNode& node) { QVector<int> FBXSerializer::getIntVector(const FBXNode& node) {
foreach (const FBXNode& child, node.children) { foreach (const FBXNode& child, node.children) {
if (child.name == "a") { if (child.name == "a") {
return getIntVector(child); return getIntVector(child);
@ -480,7 +480,7 @@ QVector<int> FBXReader::getIntVector(const FBXNode& node) {
return vector; return vector;
} }
QVector<float> FBXReader::getFloatVector(const FBXNode& node) { QVector<float> FBXSerializer::getFloatVector(const FBXNode& node) {
foreach (const FBXNode& child, node.children) { foreach (const FBXNode& child, node.children) {
if (child.name == "a") { if (child.name == "a") {
return getFloatVector(child); return getFloatVector(child);
@ -499,7 +499,7 @@ QVector<float> FBXReader::getFloatVector(const FBXNode& node) {
return vector; return vector;
} }
QVector<double> FBXReader::getDoubleVector(const FBXNode& node) { QVector<double> FBXSerializer::getDoubleVector(const FBXNode& node) {
foreach (const FBXNode& child, node.children) { foreach (const FBXNode& child, node.children) {
if (child.name == "a") { if (child.name == "a") {
return getDoubleVector(child); return getDoubleVector(child);

View file

@ -1,5 +1,5 @@
// //
// GLTFReader.cpp // GLTFSerializer.cpp
// libraries/fbx/src // libraries/fbx/src
// //
// Created by Luis Cuenca on 8/30/17. // Created by Luis Cuenca on 8/30/17.
@ -9,7 +9,7 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
// //
#include "GLTFReader.h" #include "GLTFSerializer.h"
#include <QtCore/QBuffer> #include <QtCore/QBuffer>
#include <QtCore/QIODevice> #include <QtCore/QIODevice>
@ -33,14 +33,14 @@
#include <ResourceManager.h> #include <ResourceManager.h>
#include <PathUtils.h> #include <PathUtils.h>
#include "FBXReader.h" #include "FBXSerializer.h"
GLTFReader::GLTFReader() { GLTFSerializer::GLTFSerializer() {
} }
bool GLTFReader::getStringVal(const QJsonObject& object, const QString& fieldname, bool GLTFSerializer::getStringVal(const QJsonObject& object, const QString& fieldname,
QString& value, QMap<QString, bool>& defined) { QString& value, QMap<QString, bool>& defined) {
bool _defined = (object.contains(fieldname) && object[fieldname].isString()); bool _defined = (object.contains(fieldname) && object[fieldname].isString());
if (_defined) { if (_defined) {
@ -50,7 +50,7 @@ bool GLTFReader::getStringVal(const QJsonObject& object, const QString& fieldnam
return _defined; return _defined;
} }
bool GLTFReader::getBoolVal(const QJsonObject& object, const QString& fieldname, bool GLTFSerializer::getBoolVal(const QJsonObject& object, const QString& fieldname,
bool& value, QMap<QString, bool>& defined) { bool& value, QMap<QString, bool>& defined) {
bool _defined = (object.contains(fieldname) && object[fieldname].isBool()); bool _defined = (object.contains(fieldname) && object[fieldname].isBool());
if (_defined) { if (_defined) {
@ -60,7 +60,7 @@ bool GLTFReader::getBoolVal(const QJsonObject& object, const QString& fieldname,
return _defined; return _defined;
} }
bool GLTFReader::getIntVal(const QJsonObject& object, const QString& fieldname, bool GLTFSerializer::getIntVal(const QJsonObject& object, const QString& fieldname,
int& value, QMap<QString, bool>& defined) { int& value, QMap<QString, bool>& defined) {
bool _defined = (object.contains(fieldname) && !object[fieldname].isNull()); bool _defined = (object.contains(fieldname) && !object[fieldname].isNull());
if (_defined) { if (_defined) {
@ -70,7 +70,7 @@ bool GLTFReader::getIntVal(const QJsonObject& object, const QString& fieldname,
return _defined; return _defined;
} }
bool GLTFReader::getDoubleVal(const QJsonObject& object, const QString& fieldname, bool GLTFSerializer::getDoubleVal(const QJsonObject& object, const QString& fieldname,
double& value, QMap<QString, bool>& defined) { double& value, QMap<QString, bool>& defined) {
bool _defined = (object.contains(fieldname) && object[fieldname].isDouble()); bool _defined = (object.contains(fieldname) && object[fieldname].isDouble());
if (_defined) { if (_defined) {
@ -79,7 +79,7 @@ bool GLTFReader::getDoubleVal(const QJsonObject& object, const QString& fieldnam
defined.insert(fieldname, _defined); defined.insert(fieldname, _defined);
return _defined; return _defined;
} }
bool GLTFReader::getObjectVal(const QJsonObject& object, const QString& fieldname, bool GLTFSerializer::getObjectVal(const QJsonObject& object, const QString& fieldname,
QJsonObject& value, QMap<QString, bool>& defined) { QJsonObject& value, QMap<QString, bool>& defined) {
bool _defined = (object.contains(fieldname) && object[fieldname].isObject()); bool _defined = (object.contains(fieldname) && object[fieldname].isObject());
if (_defined) { if (_defined) {
@ -89,7 +89,7 @@ bool GLTFReader::getObjectVal(const QJsonObject& object, const QString& fieldnam
return _defined; return _defined;
} }
bool GLTFReader::getIntArrayVal(const QJsonObject& object, const QString& fieldname, bool GLTFSerializer::getIntArrayVal(const QJsonObject& object, const QString& fieldname,
QVector<int>& values, QMap<QString, bool>& defined) { QVector<int>& values, QMap<QString, bool>& defined) {
bool _defined = (object.contains(fieldname) && object[fieldname].isArray()); bool _defined = (object.contains(fieldname) && object[fieldname].isArray());
if (_defined) { if (_defined) {
@ -104,7 +104,7 @@ bool GLTFReader::getIntArrayVal(const QJsonObject& object, const QString& fieldn
return _defined; return _defined;
} }
bool GLTFReader::getDoubleArrayVal(const QJsonObject& object, const QString& fieldname, bool GLTFSerializer::getDoubleArrayVal(const QJsonObject& object, const QString& fieldname,
QVector<double>& values, QMap<QString, bool>& defined) { QVector<double>& values, QMap<QString, bool>& defined) {
bool _defined = (object.contains(fieldname) && object[fieldname].isArray()); bool _defined = (object.contains(fieldname) && object[fieldname].isArray());
if (_defined) { if (_defined) {
@ -119,7 +119,7 @@ bool GLTFReader::getDoubleArrayVal(const QJsonObject& object, const QString& fie
return _defined; return _defined;
} }
bool GLTFReader::getObjectArrayVal(const QJsonObject& object, const QString& fieldname, bool GLTFSerializer::getObjectArrayVal(const QJsonObject& object, const QString& fieldname,
QJsonArray& objects, QMap<QString, bool>& defined) { QJsonArray& objects, QMap<QString, bool>& defined) {
bool _defined = (object.contains(fieldname) && object[fieldname].isArray()); bool _defined = (object.contains(fieldname) && object[fieldname].isArray());
if (_defined) { if (_defined) {
@ -129,7 +129,7 @@ bool GLTFReader::getObjectArrayVal(const QJsonObject& object, const QString& fie
return _defined; return _defined;
} }
int GLTFReader::getMeshPrimitiveRenderingMode(const QString& type) int GLTFSerializer::getMeshPrimitiveRenderingMode(const QString& type)
{ {
if (type == "POINTS") { if (type == "POINTS") {
return GLTFMeshPrimitivesRenderingMode::POINTS; return GLTFMeshPrimitivesRenderingMode::POINTS;
@ -155,7 +155,7 @@ int GLTFReader::getMeshPrimitiveRenderingMode(const QString& type)
return GLTFMeshPrimitivesRenderingMode::TRIANGLES; return GLTFMeshPrimitivesRenderingMode::TRIANGLES;
} }
int GLTFReader::getAccessorType(const QString& type) int GLTFSerializer::getAccessorType(const QString& type)
{ {
if (type == "SCALAR") { if (type == "SCALAR") {
return GLTFAccessorType::SCALAR; return GLTFAccessorType::SCALAR;
@ -181,7 +181,7 @@ int GLTFReader::getAccessorType(const QString& type)
return GLTFAccessorType::SCALAR; return GLTFAccessorType::SCALAR;
} }
int GLTFReader::getMaterialAlphaMode(const QString& type) int GLTFSerializer::getMaterialAlphaMode(const QString& type)
{ {
if (type == "OPAQUE") { if (type == "OPAQUE") {
return GLTFMaterialAlphaMode::OPAQUE; return GLTFMaterialAlphaMode::OPAQUE;
@ -195,7 +195,7 @@ int GLTFReader::getMaterialAlphaMode(const QString& type)
return GLTFMaterialAlphaMode::OPAQUE; return GLTFMaterialAlphaMode::OPAQUE;
} }
int GLTFReader::getCameraType(const QString& type) int GLTFSerializer::getCameraType(const QString& type)
{ {
if (type == "orthographic") { if (type == "orthographic") {
return GLTFCameraTypes::ORTHOGRAPHIC; return GLTFCameraTypes::ORTHOGRAPHIC;
@ -206,7 +206,7 @@ int GLTFReader::getCameraType(const QString& type)
return GLTFCameraTypes::PERSPECTIVE; return GLTFCameraTypes::PERSPECTIVE;
} }
int GLTFReader::getImageMimeType(const QString& mime) int GLTFSerializer::getImageMimeType(const QString& mime)
{ {
if (mime == "image/jpeg") { if (mime == "image/jpeg") {
return GLTFImageMimetype::JPEG; return GLTFImageMimetype::JPEG;
@ -217,7 +217,7 @@ int GLTFReader::getImageMimeType(const QString& mime)
return GLTFImageMimetype::JPEG; return GLTFImageMimetype::JPEG;
} }
int GLTFReader::getAnimationSamplerInterpolation(const QString& interpolation) int GLTFSerializer::getAnimationSamplerInterpolation(const QString& interpolation)
{ {
if (interpolation == "LINEAR") { if (interpolation == "LINEAR") {
return GLTFAnimationSamplerInterpolation::LINEAR; return GLTFAnimationSamplerInterpolation::LINEAR;
@ -225,7 +225,7 @@ int GLTFReader::getAnimationSamplerInterpolation(const QString& interpolation)
return GLTFAnimationSamplerInterpolation::LINEAR; return GLTFAnimationSamplerInterpolation::LINEAR;
} }
bool GLTFReader::setAsset(const QJsonObject& object) { bool GLTFSerializer::setAsset(const QJsonObject& object) {
QJsonObject jsAsset; QJsonObject jsAsset;
bool isAssetDefined = getObjectVal(object, "asset", jsAsset, _file.defined); bool isAssetDefined = getObjectVal(object, "asset", jsAsset, _file.defined);
if (isAssetDefined) { if (isAssetDefined) {
@ -239,7 +239,7 @@ bool GLTFReader::setAsset(const QJsonObject& object) {
return isAssetDefined; return isAssetDefined;
} }
bool GLTFReader::addAccessor(const QJsonObject& object) { bool GLTFSerializer::addAccessor(const QJsonObject& object) {
GLTFAccessor accessor; GLTFAccessor accessor;
getIntVal(object, "bufferView", accessor.bufferView, accessor.defined); getIntVal(object, "bufferView", accessor.bufferView, accessor.defined);
@ -259,7 +259,7 @@ bool GLTFReader::addAccessor(const QJsonObject& object) {
return true; return true;
} }
bool GLTFReader::addAnimation(const QJsonObject& object) { bool GLTFSerializer::addAnimation(const QJsonObject& object) {
GLTFAnimation animation; GLTFAnimation animation;
QJsonArray channels; QJsonArray channels;
@ -297,7 +297,7 @@ bool GLTFReader::addAnimation(const QJsonObject& object) {
return true; return true;
} }
bool GLTFReader::addBufferView(const QJsonObject& object) { bool GLTFSerializer::addBufferView(const QJsonObject& object) {
GLTFBufferView bufferview; GLTFBufferView bufferview;
getIntVal(object, "buffer", bufferview.buffer, bufferview.defined); getIntVal(object, "buffer", bufferview.buffer, bufferview.defined);
@ -310,7 +310,7 @@ bool GLTFReader::addBufferView(const QJsonObject& object) {
return true; return true;
} }
bool GLTFReader::addBuffer(const QJsonObject& object) { bool GLTFSerializer::addBuffer(const QJsonObject& object) {
GLTFBuffer buffer; GLTFBuffer buffer;
getIntVal(object, "byteLength", buffer.byteLength, buffer.defined); getIntVal(object, "byteLength", buffer.byteLength, buffer.defined);
@ -324,7 +324,7 @@ bool GLTFReader::addBuffer(const QJsonObject& object) {
return true; return true;
} }
bool GLTFReader::addCamera(const QJsonObject& object) { bool GLTFSerializer::addCamera(const QJsonObject& object) {
GLTFCamera camera; GLTFCamera camera;
QJsonObject jsPerspective; QJsonObject jsPerspective;
@ -352,7 +352,7 @@ bool GLTFReader::addCamera(const QJsonObject& object) {
return true; return true;
} }
bool GLTFReader::addImage(const QJsonObject& object) { bool GLTFSerializer::addImage(const QJsonObject& object) {
GLTFImage image; GLTFImage image;
QString mime; QString mime;
@ -367,7 +367,7 @@ bool GLTFReader::addImage(const QJsonObject& object) {
return true; return true;
} }
bool GLTFReader::getIndexFromObject(const QJsonObject& object, const QString& field, bool GLTFSerializer::getIndexFromObject(const QJsonObject& object, const QString& field,
int& outidx, QMap<QString, bool>& defined) { int& outidx, QMap<QString, bool>& defined) {
QJsonObject subobject; QJsonObject subobject;
if (getObjectVal(object, field, subobject, defined)) { if (getObjectVal(object, field, subobject, defined)) {
@ -377,7 +377,7 @@ bool GLTFReader::getIndexFromObject(const QJsonObject& object, const QString& fi
return false; return false;
} }
bool GLTFReader::addMaterial(const QJsonObject& object) { bool GLTFSerializer::addMaterial(const QJsonObject& object) {
GLTFMaterial material; GLTFMaterial material;
getStringVal(object, "name", material.name, material.defined); getStringVal(object, "name", material.name, material.defined);
@ -413,7 +413,7 @@ bool GLTFReader::addMaterial(const QJsonObject& object) {
return true; return true;
} }
bool GLTFReader::addMesh(const QJsonObject& object) { bool GLTFSerializer::addMesh(const QJsonObject& object) {
GLTFMesh mesh; GLTFMesh mesh;
getStringVal(object, "name", mesh.name, mesh.defined); getStringVal(object, "name", mesh.name, mesh.defined);
@ -467,7 +467,7 @@ bool GLTFReader::addMesh(const QJsonObject& object) {
return true; return true;
} }
bool GLTFReader::addNode(const QJsonObject& object) { bool GLTFSerializer::addNode(const QJsonObject& object) {
GLTFNode node; GLTFNode node;
getStringVal(object, "name", node.name, node.defined); getStringVal(object, "name", node.name, node.defined);
@ -487,7 +487,7 @@ bool GLTFReader::addNode(const QJsonObject& object) {
return true; return true;
} }
bool GLTFReader::addSampler(const QJsonObject& object) { bool GLTFSerializer::addSampler(const QJsonObject& object) {
GLTFSampler sampler; GLTFSampler sampler;
getIntVal(object, "magFilter", sampler.magFilter, sampler.defined); getIntVal(object, "magFilter", sampler.magFilter, sampler.defined);
@ -501,7 +501,7 @@ bool GLTFReader::addSampler(const QJsonObject& object) {
} }
bool GLTFReader::addScene(const QJsonObject& object) { bool GLTFSerializer::addScene(const QJsonObject& object) {
GLTFScene scene; GLTFScene scene;
getStringVal(object, "name", scene.name, scene.defined); getStringVal(object, "name", scene.name, scene.defined);
@ -511,7 +511,7 @@ bool GLTFReader::addScene(const QJsonObject& object) {
return true; return true;
} }
bool GLTFReader::addSkin(const QJsonObject& object) { bool GLTFSerializer::addSkin(const QJsonObject& object) {
GLTFSkin skin; GLTFSkin skin;
getIntVal(object, "inverseBindMatrices", skin.inverseBindMatrices, skin.defined); getIntVal(object, "inverseBindMatrices", skin.inverseBindMatrices, skin.defined);
@ -523,7 +523,7 @@ bool GLTFReader::addSkin(const QJsonObject& object) {
return true; return true;
} }
bool GLTFReader::addTexture(const QJsonObject& object) { bool GLTFSerializer::addTexture(const QJsonObject& object) {
GLTFTexture texture; GLTFTexture texture;
getIntVal(object, "sampler", texture.sampler, texture.defined); getIntVal(object, "sampler", texture.sampler, texture.defined);
getIntVal(object, "source", texture.source, texture.defined); getIntVal(object, "source", texture.source, texture.defined);
@ -533,7 +533,7 @@ bool GLTFReader::addTexture(const QJsonObject& object) {
return true; return true;
} }
bool GLTFReader::parseGLTF(const QByteArray& data) { bool GLTFSerializer::parseGLTF(const QByteArray& data) {
PROFILE_RANGE_EX(resource_parse, __FUNCTION__, 0xffff0000, nullptr); PROFILE_RANGE_EX(resource_parse, __FUNCTION__, 0xffff0000, nullptr);
QJsonDocument d = QJsonDocument::fromJson(data); QJsonDocument d = QJsonDocument::fromJson(data);
@ -664,7 +664,7 @@ bool GLTFReader::parseGLTF(const QByteArray& data) {
return true; return true;
} }
glm::mat4 GLTFReader::getModelTransform(const GLTFNode& node) { glm::mat4 GLTFSerializer::getModelTransform(const GLTFNode& node) {
glm::mat4 tmat = glm::mat4(1.0); glm::mat4 tmat = glm::mat4(1.0);
if (node.defined["matrix"] && node.matrix.size() == 16) { if (node.defined["matrix"] && node.matrix.size() == 16) {
@ -697,7 +697,7 @@ glm::mat4 GLTFReader::getModelTransform(const GLTFNode& node) {
return tmat; return tmat;
} }
bool GLTFReader::buildGeometry(HFMModel& hfmModel, const QUrl& url) { bool GLTFSerializer::buildGeometry(HFMModel& hfmModel, const QUrl& url) {
//Build dependencies //Build dependencies
QVector<QVector<int>> nodeDependencies(_file.nodes.size()); QVector<QVector<int>> nodeDependencies(_file.nodes.size());
@ -899,7 +899,7 @@ bool GLTFReader::buildGeometry(HFMModel& hfmModel, const QUrl& url) {
} }
mesh.meshIndex = hfmModel.meshes.size(); mesh.meshIndex = hfmModel.meshes.size();
FBXReader::buildModelMesh(mesh, url.toString()); FBXSerializer::buildModelMesh(mesh, url.toString());
} }
} }
@ -910,13 +910,12 @@ bool GLTFReader::buildGeometry(HFMModel& hfmModel, const QUrl& url) {
return true; return true;
} }
HFMModel* GLTFReader::readGLTF(QByteArray& data, const QVariantHash& mapping, HFMModel::Pointer GLTFSerializer::read(const QByteArray& data, const QVariantHash& mapping, const QUrl& url) {
const QUrl& url, bool loadLightmaps, float lightmapLevel) {
_url = url; _url = url;
// Normalize url for local files // Normalize url for local files
QUrl normalizeUrl = DependencyManager::get<ResourceManager>()->normalizeURL(url); QUrl normalizeUrl = DependencyManager::get<ResourceManager>()->normalizeURL(_url);
if (normalizeUrl.scheme().isEmpty() || (normalizeUrl.scheme() == "file")) { if (normalizeUrl.scheme().isEmpty() || (normalizeUrl.scheme() == "file")) {
QString localFileName = PathUtils::expandToLocalDataAbsolutePath(normalizeUrl).toLocalFile(); QString localFileName = PathUtils::expandToLocalDataAbsolutePath(normalizeUrl).toLocalFile();
_url = QUrl(QFileInfo(localFileName).absoluteFilePath()); _url = QUrl(QFileInfo(localFileName).absoluteFilePath());
@ -924,17 +923,17 @@ HFMModel* GLTFReader::readGLTF(QByteArray& data, const QVariantHash& mapping,
parseGLTF(data); parseGLTF(data);
//_file.dump(); //_file.dump();
HFMModel* hfmModelPtr = new HFMModel(); auto hfmModelPtr = std::make_shared<HFMModel>();
HFMModel& hfmModel = *hfmModelPtr; HFMModel& hfmModel = *hfmModelPtr;
buildGeometry(hfmModel, url); buildGeometry(hfmModel, _url);
//hfmDebugDump(data); //hfmDebugDump(data);
return hfmModelPtr; return hfmModelPtr;
} }
bool GLTFReader::readBinary(const QString& url, QByteArray& outdata) { bool GLTFSerializer::readBinary(const QString& url, QByteArray& outdata) {
QUrl binaryUrl = _url.resolved(url); QUrl binaryUrl = _url.resolved(url);
bool success; bool success;
@ -943,7 +942,7 @@ bool GLTFReader::readBinary(const QString& url, QByteArray& outdata) {
return success; return success;
} }
bool GLTFReader::doesResourceExist(const QString& url) { bool GLTFSerializer::doesResourceExist(const QString& url) {
if (_url.isEmpty()) { if (_url.isEmpty()) {
return false; return false;
} }
@ -951,9 +950,9 @@ bool GLTFReader::doesResourceExist(const QString& url) {
return DependencyManager::get<ResourceManager>()->resourceExists(candidateUrl); return DependencyManager::get<ResourceManager>()->resourceExists(candidateUrl);
} }
std::tuple<bool, QByteArray> GLTFReader::requestData(QUrl& url) { std::tuple<bool, QByteArray> GLTFSerializer::requestData(QUrl& url) {
auto request = DependencyManager::get<ResourceManager>()->createResourceRequest( auto request = DependencyManager::get<ResourceManager>()->createResourceRequest(
nullptr, url, true, -1, "GLTFReader::requestData"); nullptr, url, true, -1, "GLTFSerializer::requestData");
if (!request) { if (!request) {
return std::make_tuple(false, QByteArray()); return std::make_tuple(false, QByteArray());
@ -972,7 +971,7 @@ std::tuple<bool, QByteArray> GLTFReader::requestData(QUrl& url) {
} }
QNetworkReply* GLTFReader::request(QUrl& url, bool isTest) { QNetworkReply* GLTFSerializer::request(QUrl& url, bool isTest) {
if (!qApp) { if (!qApp) {
return nullptr; return nullptr;
} }
@ -996,7 +995,7 @@ QNetworkReply* GLTFReader::request(QUrl& url, bool isTest) {
return netReply; // trying to sync later on. return netReply; // trying to sync later on.
} }
HFMTexture GLTFReader::getHFMTexture(const GLTFTexture& texture) { HFMTexture GLTFSerializer::getHFMTexture(const GLTFTexture& texture) {
HFMTexture fbxtex = HFMTexture(); HFMTexture fbxtex = HFMTexture();
fbxtex.texcoordSet = 0; fbxtex.texcoordSet = 0;
@ -1011,7 +1010,7 @@ HFMTexture GLTFReader::getHFMTexture(const GLTFTexture& texture) {
return fbxtex; return fbxtex;
} }
void GLTFReader::setHFMMaterial(HFMMaterial& fbxmat, const GLTFMaterial& material) { void GLTFSerializer::setHFMMaterial(HFMMaterial& fbxmat, const GLTFMaterial& material) {
if (material.defined["name"]) { if (material.defined["name"]) {
@ -1074,7 +1073,7 @@ void GLTFReader::setHFMMaterial(HFMMaterial& fbxmat, const GLTFMaterial& materia
} }
template<typename T, typename L> template<typename T, typename L>
bool GLTFReader::readArray(const QByteArray& bin, int byteOffset, int count, bool GLTFSerializer::readArray(const QByteArray& bin, int byteOffset, int count,
QVector<L>& outarray, int accessorType) { QVector<L>& outarray, int accessorType) {
QDataStream blobstream(bin); QDataStream blobstream(bin);
@ -1131,7 +1130,7 @@ bool GLTFReader::readArray(const QByteArray& bin, int byteOffset, int count,
return true; return true;
} }
template<typename T> template<typename T>
bool GLTFReader::addArrayOfType(const QByteArray& bin, int byteOffset, int count, bool GLTFSerializer::addArrayOfType(const QByteArray& bin, int byteOffset, int count,
QVector<T>& outarray, int accessorType, int componentType) { QVector<T>& outarray, int accessorType, int componentType) {
switch (componentType) { switch (componentType) {
@ -1155,7 +1154,7 @@ bool GLTFReader::addArrayOfType(const QByteArray& bin, int byteOffset, int count
return false; return false;
} }
void GLTFReader::retriangulate(const QVector<int>& inIndices, const QVector<glm::vec3>& in_vertices, void GLTFSerializer::retriangulate(const QVector<int>& inIndices, const QVector<glm::vec3>& in_vertices,
const QVector<glm::vec3>& in_normals, QVector<int>& outIndices, const QVector<glm::vec3>& in_normals, QVector<int>& outIndices,
QVector<glm::vec3>& out_vertices, QVector<glm::vec3>& out_normals) { QVector<glm::vec3>& out_vertices, QVector<glm::vec3>& out_normals) {
for (int i = 0; i < inIndices.size(); i = i + 3) { for (int i = 0; i < inIndices.size(); i = i + 3) {
@ -1178,7 +1177,7 @@ void GLTFReader::retriangulate(const QVector<int>& inIndices, const QVector<glm:
} }
} }
void GLTFReader::hfmDebugDump(const HFMModel& hfmModel) { void GLTFSerializer::hfmDebugDump(const HFMModel& hfmModel) {
qCDebug(modelformat) << "---------------- hfmModel ----------------"; qCDebug(modelformat) << "---------------- hfmModel ----------------";
qCDebug(modelformat) << " hasSkeletonJoints =" << hfmModel.hasSkeletonJoints; qCDebug(modelformat) << " hasSkeletonJoints =" << hfmModel.hasSkeletonJoints;
qCDebug(modelformat) << " offset =" << hfmModel.offset; qCDebug(modelformat) << " offset =" << hfmModel.offset;

View file

@ -1,5 +1,5 @@
// //
// GLTFReader.h // GLTFSerializer.h
// libraries/fbx/src // libraries/fbx/src
// //
// Created by Luis Cuenca on 8/30/17. // Created by Luis Cuenca on 8/30/17.
@ -9,13 +9,14 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
// //
#ifndef hifi_GLTFReader_h #ifndef hifi_GLTFSerializer_h
#define hifi_GLTFReader_h #define hifi_GLTFSerializer_h
#include <memory.h> #include <memory.h>
#include <QtNetwork/QNetworkReply> #include <QtNetwork/QNetworkReply>
#include <hfm/ModelFormatLogging.h> #include <hfm/ModelFormatLogging.h>
#include "FBXReader.h" #include <hfm/HFMSerializer.h>
#include "FBXSerializer.h"
struct GLTFAsset { struct GLTFAsset {
@ -699,12 +700,11 @@ struct GLTFFile {
} }
}; };
class GLTFReader : public QObject { class GLTFSerializer : public QObject, public HFMSerializer {
Q_OBJECT Q_OBJECT
public: public:
GLTFReader(); GLTFSerializer();
HFMModel* readGLTF(QByteArray& data, const QVariantHash& mapping, HFMModel::Pointer read(const QByteArray& data, const QVariantHash& mapping, const QUrl& url = QUrl()) override;
const QUrl& url, bool loadLightmaps = true, float lightmapLevel = 1.0f);
private: private:
GLTFFile _file; GLTFFile _file;
QUrl _url; QUrl _url;
@ -780,4 +780,4 @@ private:
void hfmDebugDump(const HFMModel& hfmModel); void hfmDebugDump(const HFMModel& hfmModel);
}; };
#endif // hifi_GLTFReader_h #endif // hifi_GLTFSerializer_h

View file

@ -1,5 +1,5 @@
// //
// OBJReader.cpp // OBJSerializer.cpp
// libraries/fbx/src/ // libraries/fbx/src/
// //
// Created by Seth Alves on 3/7/15. // Created by Seth Alves on 3/7/15.
@ -12,7 +12,7 @@
// http://www.scratchapixel.com/old/lessons/3d-advanced-lessons/obj-file-format/obj-file-format/ // http://www.scratchapixel.com/old/lessons/3d-advanced-lessons/obj-file-format/obj-file-format/
// http://paulbourke.net/dataformats/obj/ // http://paulbourke.net/dataformats/obj/
#include "OBJReader.h" #include "OBJSerializer.h"
#include <ctype.h> // .obj files are not locale-specific. The C/ASCII charset applies. #include <ctype.h> // .obj files are not locale-specific. The C/ASCII charset applies.
#include <sstream> #include <sstream>
@ -27,7 +27,7 @@
#include <NetworkAccessManager.h> #include <NetworkAccessManager.h>
#include <ResourceManager.h> #include <ResourceManager.h>
#include "FBXReader.h" #include "FBXSerializer.h"
#include <hfm/ModelFormatLogging.h> #include <hfm/ModelFormatLogging.h>
#include <shared/PlatformHacks.h> #include <shared/PlatformHacks.h>
@ -238,7 +238,7 @@ void OBJFace::addFrom(const OBJFace* face, int index) { // add using data from f
} }
} }
bool OBJReader::isValidTexture(const QByteArray &filename) { bool OBJSerializer::isValidTexture(const QByteArray &filename) {
if (_url.isEmpty()) { if (_url.isEmpty()) {
return false; return false;
} }
@ -247,7 +247,7 @@ bool OBJReader::isValidTexture(const QByteArray &filename) {
return DependencyManager::get<ResourceManager>()->resourceExists(candidateUrl); return DependencyManager::get<ResourceManager>()->resourceExists(candidateUrl);
} }
void OBJReader::parseMaterialLibrary(QIODevice* device) { void OBJSerializer::parseMaterialLibrary(QIODevice* device) {
OBJTokenizer tokenizer(device); OBJTokenizer tokenizer(device);
QString matName = SMART_DEFAULT_MATERIAL_NAME; QString matName = SMART_DEFAULT_MATERIAL_NAME;
OBJMaterial& currentMaterial = materials[matName]; OBJMaterial& currentMaterial = materials[matName];
@ -255,7 +255,7 @@ void OBJReader::parseMaterialLibrary(QIODevice* device) {
switch (tokenizer.nextToken()) { switch (tokenizer.nextToken()) {
case OBJTokenizer::COMMENT_TOKEN: case OBJTokenizer::COMMENT_TOKEN:
#ifdef WANT_DEBUG #ifdef WANT_DEBUG
qCDebug(modelformat) << "OBJ Reader MTLLIB comment:" << tokenizer.getComment(); qCDebug(modelformat) << "OBJSerializer MTLLIB comment:" << tokenizer.getComment();
#endif #endif
break; break;
case OBJTokenizer::DATUM_TOKEN: case OBJTokenizer::DATUM_TOKEN:
@ -264,7 +264,7 @@ void OBJReader::parseMaterialLibrary(QIODevice* device) {
materials[matName] = currentMaterial; materials[matName] = currentMaterial;
#ifdef WANT_DEBUG #ifdef WANT_DEBUG
qCDebug(modelformat) << qCDebug(modelformat) <<
"OBJ Reader Last material illumination model:" << currentMaterial.illuminationModel << "OBJSerializer Last material illumination model:" << currentMaterial.illuminationModel <<
" shininess:" << currentMaterial.shininess << " shininess:" << currentMaterial.shininess <<
" opacity:" << currentMaterial.opacity << " opacity:" << currentMaterial.opacity <<
" diffuse color:" << currentMaterial.diffuseColor << " diffuse color:" << currentMaterial.diffuseColor <<
@ -287,7 +287,7 @@ void OBJReader::parseMaterialLibrary(QIODevice* device) {
matName = tokenizer.getDatum(); matName = tokenizer.getDatum();
currentMaterial = materials[matName]; currentMaterial = materials[matName];
#ifdef WANT_DEBUG #ifdef WANT_DEBUG
qCDebug(modelformat) << "OBJ Reader Starting new material definition " << matName; qCDebug(modelformat) << "OBJSerializer Starting new material definition " << matName;
#endif #endif
currentMaterial.diffuseTextureFilename = ""; currentMaterial.diffuseTextureFilename = "";
currentMaterial.emissiveTextureFilename = ""; currentMaterial.emissiveTextureFilename = "";
@ -299,7 +299,7 @@ void OBJReader::parseMaterialLibrary(QIODevice* device) {
currentMaterial.shininess = tokenizer.getFloat(); currentMaterial.shininess = tokenizer.getFloat();
} else if (token == "Ni") { } else if (token == "Ni") {
#ifdef WANT_DEBUG #ifdef WANT_DEBUG
qCDebug(modelformat) << "OBJ Reader Ignoring material Ni " << tokenizer.getFloat(); qCDebug(modelformat) << "OBJSerializer Ignoring material Ni " << tokenizer.getFloat();
#else #else
tokenizer.getFloat(); tokenizer.getFloat();
#endif #endif
@ -311,13 +311,13 @@ void OBJReader::parseMaterialLibrary(QIODevice* device) {
currentMaterial.illuminationModel = tokenizer.getFloat(); currentMaterial.illuminationModel = tokenizer.getFloat();
} else if (token == "Tf") { } else if (token == "Tf") {
#ifdef WANT_DEBUG #ifdef WANT_DEBUG
qCDebug(modelformat) << "OBJ Reader Ignoring material Tf " << tokenizer.getVec3(); qCDebug(modelformat) << "OBJSerializer Ignoring material Tf " << tokenizer.getVec3();
#else #else
tokenizer.getVec3(); tokenizer.getVec3();
#endif #endif
} else if (token == "Ka") { } else if (token == "Ka") {
#ifdef WANT_DEBUG #ifdef WANT_DEBUG
qCDebug(modelformat) << "OBJ Reader Ignoring material Ka " << tokenizer.getVec3();; qCDebug(modelformat) << "OBJSerializer Ignoring material Ka " << tokenizer.getVec3();;
#else #else
tokenizer.getVec3(); tokenizer.getVec3();
#endif #endif
@ -334,7 +334,7 @@ void OBJReader::parseMaterialLibrary(QIODevice* device) {
parseTextureLine(textureLine, filename, textureOptions); parseTextureLine(textureLine, filename, textureOptions);
if (filename.endsWith(".tga")) { if (filename.endsWith(".tga")) {
#ifdef WANT_DEBUG #ifdef WANT_DEBUG
qCDebug(modelformat) << "OBJ Reader WARNING: currently ignoring tga texture " << filename << " in " << _url; qCDebug(modelformat) << "OBJSerializer WARNING: currently ignoring tga texture " << filename << " in " << _url;
#endif #endif
break; break;
} }
@ -354,7 +354,7 @@ void OBJReader::parseMaterialLibrary(QIODevice* device) {
} }
} }
void OBJReader::parseTextureLine(const QByteArray& textureLine, QByteArray& filename, OBJMaterialTextureOptions& textureOptions) { void OBJSerializer::parseTextureLine(const QByteArray& textureLine, QByteArray& filename, OBJMaterialTextureOptions& textureOptions) {
// Texture options reference http://paulbourke.net/dataformats/mtl/ // Texture options reference http://paulbourke.net/dataformats/mtl/
// and https://wikivisually.com/wiki/Material_Template_Library // and https://wikivisually.com/wiki/Material_Template_Library
@ -368,7 +368,7 @@ void OBJReader::parseTextureLine(const QByteArray& textureLine, QByteArray& file
if (option == "-blendu" || option == "-blendv") { if (option == "-blendu" || option == "-blendv") {
#ifdef WANT_DEBUG #ifdef WANT_DEBUG
const std::string& onoff = parser[i++]; const std::string& onoff = parser[i++];
qCDebug(modelformat) << "OBJ Reader WARNING: Ignoring texture option" << option.c_str() << onoff.c_str(); qCDebug(modelformat) << "OBJSerializer WARNING: Ignoring texture option" << option.c_str() << onoff.c_str();
#endif #endif
} else if (option == "-bm") { } else if (option == "-bm") {
const std::string& bm = parser[i++]; const std::string& bm = parser[i++];
@ -377,22 +377,22 @@ void OBJReader::parseTextureLine(const QByteArray& textureLine, QByteArray& file
#ifdef WANT_DEBUG #ifdef WANT_DEBUG
const std::string& boost = parser[i++]; const std::string& boost = parser[i++];
float boostFloat = std::stof(boost); float boostFloat = std::stof(boost);
qCDebug(modelformat) << "OBJ Reader WARNING: Ignoring texture option" << option.c_str() << boost.c_str(); qCDebug(modelformat) << "OBJSerializer WARNING: Ignoring texture option" << option.c_str() << boost.c_str();
#endif #endif
} else if (option == "-cc") { } else if (option == "-cc") {
#ifdef WANT_DEBUG #ifdef WANT_DEBUG
const std::string& onoff = parser[i++]; const std::string& onoff = parser[i++];
qCDebug(modelformat) << "OBJ Reader WARNING: Ignoring texture option" << option.c_str() << onoff.c_str(); qCDebug(modelformat) << "OBJSerializer WARNING: Ignoring texture option" << option.c_str() << onoff.c_str();
#endif #endif
} else if (option == "-clamp") { } else if (option == "-clamp") {
#ifdef WANT_DEBUG #ifdef WANT_DEBUG
const std::string& onoff = parser[i++]; const std::string& onoff = parser[i++];
qCDebug(modelformat) << "OBJ Reader WARNING: Ignoring texture option" << option.c_str() << onoff.c_str(); qCDebug(modelformat) << "OBJSerializer WARNING: Ignoring texture option" << option.c_str() << onoff.c_str();
#endif #endif
} else if (option == "-imfchan") { } else if (option == "-imfchan") {
#ifdef WANT_DEBUG #ifdef WANT_DEBUG
const std::string& imfchan = parser[i++]; const std::string& imfchan = parser[i++];
qCDebug(modelformat) << "OBJ Reader WARNING: Ignoring texture option" << option.c_str() << imfchan.c_str(); qCDebug(modelformat) << "OBJSerializer WARNING: Ignoring texture option" << option.c_str() << imfchan.c_str();
#endif #endif
} else if (option == "-mm") { } else if (option == "-mm") {
if (i + 1 < parser.size()) { if (i + 1 < parser.size()) {
@ -401,7 +401,7 @@ void OBJReader::parseTextureLine(const QByteArray& textureLine, QByteArray& file
const std::string& mmGain = parser[i++]; const std::string& mmGain = parser[i++];
float mmBaseFloat = std::stof(mmBase); float mmBaseFloat = std::stof(mmBase);
float mmGainFloat = std::stof(mmGain); float mmGainFloat = std::stof(mmGain);
qCDebug(modelformat) << "OBJ Reader WARNING: Ignoring texture option" << option.c_str() << mmBase.c_str() << mmGain.c_str(); qCDebug(modelformat) << "OBJSerializer WARNING: Ignoring texture option" << option.c_str() << mmBase.c_str() << mmGain.c_str();
#endif #endif
} }
} else if (option == "-o" || option == "-s" || option == "-t") { } else if (option == "-o" || option == "-s" || option == "-t") {
@ -413,23 +413,23 @@ void OBJReader::parseTextureLine(const QByteArray& textureLine, QByteArray& file
float uFloat = std::stof(u); float uFloat = std::stof(u);
float vFloat = std::stof(v); float vFloat = std::stof(v);
float wFloat = std::stof(w); float wFloat = std::stof(w);
qCDebug(modelformat) << "OBJ Reader WARNING: Ignoring texture option" << option.c_str() << u.c_str() << v.c_str() << w.c_str(); qCDebug(modelformat) << "OBJSerializer WARNING: Ignoring texture option" << option.c_str() << u.c_str() << v.c_str() << w.c_str();
#endif #endif
} }
} else if (option == "-texres") { } else if (option == "-texres") {
#ifdef WANT_DEBUG #ifdef WANT_DEBUG
const std::string& texres = parser[i++]; const std::string& texres = parser[i++];
float texresFloat = std::stof(texres); float texresFloat = std::stof(texres);
qCDebug(modelformat) << "OBJ Reader WARNING: Ignoring texture option" << option.c_str() << texres.c_str(); qCDebug(modelformat) << "OBJSerializer WARNING: Ignoring texture option" << option.c_str() << texres.c_str();
#endif #endif
} else if (option == "-type") { } else if (option == "-type") {
#ifdef WANT_DEBUG #ifdef WANT_DEBUG
const std::string& type = parser[i++]; const std::string& type = parser[i++];
qCDebug(modelformat) << "OBJ Reader WARNING: Ignoring texture option" << option.c_str() << type.c_str(); qCDebug(modelformat) << "OBJSerializer WARNING: Ignoring texture option" << option.c_str() << type.c_str();
#endif #endif
} else if (option[0] == '-') { } else if (option[0] == '-') {
#ifdef WANT_DEBUG #ifdef WANT_DEBUG
qCDebug(modelformat) << "OBJ Reader WARNING: Ignoring unsupported texture option" << option.c_str(); qCDebug(modelformat) << "OBJSerializer WARNING: Ignoring unsupported texture option" << option.c_str();
#endif #endif
} }
} else { // assume filename at end when no more options } else { // assume filename at end when no more options
@ -444,7 +444,7 @@ void OBJReader::parseTextureLine(const QByteArray& textureLine, QByteArray& file
std::tuple<bool, QByteArray> requestData(QUrl& url) { std::tuple<bool, QByteArray> requestData(QUrl& url) {
auto request = DependencyManager::get<ResourceManager>()->createResourceRequest( auto request = DependencyManager::get<ResourceManager>()->createResourceRequest(
nullptr, url, true, -1, "(OBJReader) requestData"); nullptr, url, true, -1, "(OBJSerializer) requestData");
if (!request) { if (!request) {
return std::make_tuple(false, QByteArray()); return std::make_tuple(false, QByteArray());
@ -488,7 +488,7 @@ QNetworkReply* request(QUrl& url, bool isTest) {
} }
bool OBJReader::parseOBJGroup(OBJTokenizer& tokenizer, const QVariantHash& mapping, HFMModel& hfmModel, bool OBJSerializer::parseOBJGroup(OBJTokenizer& tokenizer, const QVariantHash& mapping, HFMModel& hfmModel,
float& scaleGuess, bool combineParts) { float& scaleGuess, bool combineParts) {
FaceGroup faces; FaceGroup faces;
HFMMesh& mesh = hfmModel.meshes[0]; HFMMesh& mesh = hfmModel.meshes[0];
@ -557,7 +557,7 @@ bool OBJReader::parseOBJGroup(OBJTokenizer& tokenizer, const QVariantHash& mappi
currentMaterialName = nextName; currentMaterialName = nextName;
} }
#ifdef WANT_DEBUG #ifdef WANT_DEBUG
qCDebug(modelformat) << "OBJ Reader new current material:" << currentMaterialName; qCDebug(modelformat) << "OBJSerializer new current material:" << currentMaterialName;
#endif #endif
} }
} else if (token == "v") { } else if (token == "v") {
@ -652,12 +652,12 @@ done:
} }
HFMModel::Pointer OBJReader::readOBJ(QByteArray& data, const QVariantHash& mapping, bool combineParts, const QUrl& url) { HFMModel::Pointer OBJSerializer::read(const QByteArray& data, const QVariantHash& mapping, const QUrl& url) {
PROFILE_RANGE_EX(resource_parse, __FUNCTION__, 0xffff0000, nullptr); PROFILE_RANGE_EX(resource_parse, __FUNCTION__, 0xffff0000, nullptr);
QBuffer buffer { &data }; QBuffer buffer { const_cast<QByteArray*>(&data) };
buffer.open(QIODevice::ReadOnly); buffer.open(QIODevice::ReadOnly);
auto hfmModelPtr { std::make_shared<HFMModel>() }; auto hfmModelPtr = std::make_shared<HFMModel>();
HFMModel& hfmModel { *hfmModelPtr }; HFMModel& hfmModel { *hfmModelPtr };
OBJTokenizer tokenizer { &buffer }; OBJTokenizer tokenizer { &buffer };
float scaleGuess = 1.0f; float scaleGuess = 1.0f;
@ -665,6 +665,7 @@ HFMModel::Pointer OBJReader::readOBJ(QByteArray& data, const QVariantHash& mappi
bool needsMaterialLibrary = false; bool needsMaterialLibrary = false;
_url = url; _url = url;
bool combineParts = mapping.value("combineParts").toBool();
hfmModel.meshExtents.reset(); hfmModel.meshExtents.reset();
hfmModel.meshes.append(HFMMesh()); hfmModel.meshes.append(HFMMesh());
@ -720,7 +721,7 @@ HFMModel::Pointer OBJReader::readOBJ(QByteArray& data, const QVariantHash& mappi
QString groupMaterialName = face.materialName; QString groupMaterialName = face.materialName;
if (groupMaterialName.isEmpty() && specifiesUV) { if (groupMaterialName.isEmpty() && specifiesUV) {
#ifdef WANT_DEBUG #ifdef WANT_DEBUG
qCDebug(modelformat) << "OBJ Reader WARNING: " << url qCDebug(modelformat) << "OBJSerializer WARNING: " << url
<< " needs a texture that isn't specified. Using default mechanism."; << " needs a texture that isn't specified. Using default mechanism.";
#endif #endif
groupMaterialName = SMART_DEFAULT_MATERIAL_NAME; groupMaterialName = SMART_DEFAULT_MATERIAL_NAME;
@ -822,11 +823,11 @@ HFMModel::Pointer OBJReader::readOBJ(QByteArray& data, const QVariantHash& mappi
} }
// Build the single mesh. // Build the single mesh.
FBXReader::buildModelMesh(mesh, url.toString()); FBXSerializer::buildModelMesh(mesh, _url.toString());
// hfmDebugDump(hfmModel); // hfmDebugDump(hfmModel);
} catch(const std::exception& e) { } catch(const std::exception& e) {
qCDebug(modelformat) << "OBJ reader fail: " << e.what(); qCDebug(modelformat) << "OBJSerializer fail: " << e.what();
} }
QString queryPart = _url.query(); QString queryPart = _url.query();
@ -838,14 +839,14 @@ HFMModel::Pointer OBJReader::readOBJ(QByteArray& data, const QVariantHash& mappi
} }
// Some .obj files use the convention that a group with uv coordinates that doesn't define a material, should use // Some .obj files use the convention that a group with uv coordinates that doesn't define a material, should use
// a texture with the same basename as the .obj file. // a texture with the same basename as the .obj file.
if (preDefinedMaterial.userSpecifiesUV && !url.isEmpty()) { if (preDefinedMaterial.userSpecifiesUV && !_url.isEmpty()) {
QString filename = url.fileName(); QString filename = _url.fileName();
int extIndex = filename.lastIndexOf('.'); // by construction, this does not fail int extIndex = filename.lastIndexOf('.'); // by construction, this does not fail
QString basename = filename.remove(extIndex + 1, sizeof("obj")); QString basename = filename.remove(extIndex + 1, sizeof("obj"));
preDefinedMaterial.diffuseColor = glm::vec3(1.0f); preDefinedMaterial.diffuseColor = glm::vec3(1.0f);
QVector<QByteArray> extensions = { "jpg", "jpeg", "png", "tga" }; QVector<QByteArray> extensions = { "jpg", "jpeg", "png", "tga" };
QByteArray base = basename.toUtf8(), textName = ""; QByteArray base = basename.toUtf8(), textName = "";
qCDebug(modelformat) << "OBJ Reader looking for default texture"; qCDebug(modelformat) << "OBJSerializer looking for default texture";
for (int i = 0; i < extensions.count(); i++) { for (int i = 0; i < extensions.count(); i++) {
QByteArray candidateString = base + extensions[i]; QByteArray candidateString = base + extensions[i];
if (isValidTexture(candidateString)) { if (isValidTexture(candidateString)) {
@ -856,7 +857,7 @@ HFMModel::Pointer OBJReader::readOBJ(QByteArray& data, const QVariantHash& mappi
if (!textName.isEmpty()) { if (!textName.isEmpty()) {
#ifdef WANT_DEBUG #ifdef WANT_DEBUG
qCDebug(modelformat) << "OBJ Reader found a default texture: " << textName; qCDebug(modelformat) << "OBJSerializer found a default texture: " << textName;
#endif #endif
preDefinedMaterial.diffuseTextureFilename = textName; preDefinedMaterial.diffuseTextureFilename = textName;
} }
@ -866,7 +867,7 @@ HFMModel::Pointer OBJReader::readOBJ(QByteArray& data, const QVariantHash& mappi
foreach (QString libraryName, librariesSeen.keys()) { foreach (QString libraryName, librariesSeen.keys()) {
// Throw away any path part of libraryName, and merge against original url. // Throw away any path part of libraryName, and merge against original url.
QUrl libraryUrl = _url.resolved(QUrl(libraryName).fileName()); QUrl libraryUrl = _url.resolved(QUrl(libraryName).fileName());
qCDebug(modelformat) << "OBJ Reader material library" << libraryName; qCDebug(modelformat) << "OBJSerializer material library" << libraryName;
bool success; bool success;
QByteArray data; QByteArray data;
std::tie<bool, QByteArray>(success, data) = requestData(libraryUrl); std::tie<bool, QByteArray>(success, data) = requestData(libraryUrl);
@ -875,7 +876,7 @@ HFMModel::Pointer OBJReader::readOBJ(QByteArray& data, const QVariantHash& mappi
buffer.open(QIODevice::ReadOnly); buffer.open(QIODevice::ReadOnly);
parseMaterialLibrary(&buffer); parseMaterialLibrary(&buffer);
} else { } else {
qCDebug(modelformat) << "OBJ Reader WARNING:" << libraryName << "did not answer"; qCDebug(modelformat) << "OBJSerializer WARNING:" << libraryName << "did not answer";
} }
} }
} }

View file

@ -1,6 +1,20 @@
//
// OBJSerializer.h
// libraries/fbx/src/
//
// Created by Seth Alves on 3/6/15.
// Copyright 2015 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_OBJSerializer_h
#define hifi_OBJSerializer_h
#include <QtNetwork/QNetworkReply> #include <QtNetwork/QNetworkReply>
#include "FBXReader.h" #include <hfm/HFMSerializer.h>
#include "FBXSerializer.h"
class OBJTokenizer { class OBJTokenizer {
public: public:
@ -75,7 +89,7 @@ public:
OBJMaterial() : shininess(0.0f), opacity(1.0f), diffuseColor(0.9f), specularColor(0.9f), emissiveColor(0.0f), illuminationModel(-1) {} OBJMaterial() : shininess(0.0f), opacity(1.0f), diffuseColor(0.9f), specularColor(0.9f), emissiveColor(0.0f), illuminationModel(-1) {}
}; };
class OBJReader: public QObject { // QObject so we can make network requests. class OBJSerializer: public QObject, public HFMSerializer { // QObject so we can make network requests.
Q_OBJECT Q_OBJECT
public: public:
typedef QVector<OBJFace> FaceGroup; typedef QVector<OBJFace> FaceGroup;
@ -87,7 +101,7 @@ public:
QString currentMaterialName; QString currentMaterialName;
QHash<QString, OBJMaterial> materials; QHash<QString, OBJMaterial> materials;
HFMModel::Pointer readOBJ(QByteArray& data, const QVariantHash& mapping, bool combineParts, const QUrl& url = QUrl()); HFMModel::Pointer read(const QByteArray& data, const QVariantHash& mapping, const QUrl& url = QUrl()) override;
private: private:
QUrl _url; QUrl _url;
@ -105,3 +119,5 @@ private:
// What are these utilities doing here? One is used by fbx loading code in VHACD Utils, and the other a general debugging utility. // What are these utilities doing here? One is used by fbx loading code in VHACD Utils, and the other a general debugging utility.
void setMeshPartDefaults(HFMMeshPart& meshPart, QString materialID); void setMeshPartDefaults(HFMMeshPart& meshPart, QString materialID);
void hfmDebugDump(const HFMModel& hfmModel); void hfmDebugDump(const HFMModel& hfmModel);
#endif // hifi_OBJSerializer_h

View file

@ -0,0 +1,29 @@
//
// FBXSerializer.h
// libraries/hfm/src/hfm
//
// Created by Sabrina Shanman on 2018/11/07.
// Copyright 2018 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_HFMSerializer_h
#define hifi_HFMSerializer_h
#include <shared/HifiTypes.h>
#include "HFM.h"
namespace hfm {
class Serializer {
virtual Model::Pointer read(const hifi::ByteArray& data, const hifi::VariantHash& mapping, const hifi::URL& url = hifi::URL()) = 0;
};
};
using HFMSerializer = hfm::Serializer;
#endif // hifi_HFMSerializer_h

View file

@ -12,9 +12,9 @@
#include "ModelCache.h" #include "ModelCache.h"
#include <Finally.h> #include <Finally.h>
#include <FSTReader.h> #include <FSTReader.h>
#include "FBXReader.h" #include "FBXSerializer.h"
#include "OBJReader.h" #include "OBJSerializer.h"
#include "GLTFReader.h" #include "GLTFSerializer.h"
#include <gpu/Batch.h> #include <gpu/Batch.h>
#include <gpu/Stream.h> #include <gpu/Stream.h>
@ -193,24 +193,26 @@ void GeometryReader::run() {
HFMModel::Pointer hfmModel; HFMModel::Pointer hfmModel;
QVariantHash serializerMapping = _mapping;
serializerMapping["combineParts"] = _combineParts;
if (_url.path().toLower().endsWith(".fbx")) { if (_url.path().toLower().endsWith(".fbx")) {
hfmModel.reset(readFBX(_data, _mapping, _url.path())); hfmModel = FBXSerializer().read(_data, serializerMapping, _url);
if (hfmModel->meshes.size() == 0 && hfmModel->joints.size() == 0) { if (hfmModel->meshes.size() == 0 && hfmModel->joints.size() == 0) {
throw QString("empty geometry, possibly due to an unsupported FBX version"); 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")) {
hfmModel = OBJReader().readOBJ(_data, _mapping, _combineParts, _url); hfmModel = OBJSerializer().read(_data, serializerMapping, _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)){
hfmModel = OBJReader().readOBJ(uncompressedData, _mapping, _combineParts, _url); hfmModel = OBJSerializer().read(uncompressedData, serializerMapping, _url);
} else { } else {
throw QString("failed to decompress .obj.gz"); throw QString("failed to decompress .obj.gz");
} }
} else if (_url.path().toLower().endsWith(".gltf")) { } else if (_url.path().toLower().endsWith(".gltf")) {
std::shared_ptr<GLTFReader> glreader = std::make_shared<GLTFReader>(); hfmModel = GLTFSerializer().read(_data, serializerMapping, _url);
hfmModel.reset(glreader->readGLTF(_data, _mapping, _url));
if (hfmModel->meshes.size() == 0 && hfmModel->joints.size() == 0) { if (hfmModel->meshes.size() == 0 && hfmModel->joints.size() == 0) {
throw QString("empty geometry, possibly due to an unsupported GLTF version"); throw QString("empty geometry, possibly due to an unsupported GLTF version");
} }

View file

@ -18,7 +18,7 @@
#include <graphics/Material.h> #include <graphics/Material.h>
#include <graphics/Asset.h> #include <graphics/Asset.h>
#include "FBXReader.h" #include "FBXSerializer.h"
#include "TextureCache.h" #include "TextureCache.h"
// Alias instead of derive to avoid copying // Alias instead of derive to avoid copying

View file

@ -0,0 +1,25 @@
//
// HifiTypes.h
// libraries/shared/src/shared
//
// Created by Sabrina Shanman on 2018/11/12.
// Copyright 2018 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_HifiTypes_h
#define hifi_HifiTypes_h
#include <QVarLengthArray>
#include <QVariant>
#include <QUrl>
namespace hifi {
using ByteArray = QByteArray;
using VariantHash = QVariantHash;
using URL = QUrl;
};
#endif // hifi_HifiTypes_h

View file

@ -12,7 +12,7 @@
#include <QtCore/QFile> #include <QtCore/QFile>
#include <FBXReader.h> #include <FBXSerializer.h>
struct MyVertex { struct MyVertex {
vec3 position; vec3 position;
@ -100,7 +100,7 @@ bool TestFbx::isReady() const {
void TestFbx::parseFbx(const QByteArray& fbxData) { void TestFbx::parseFbx(const QByteArray& fbxData) {
QVariantHash mapping; QVariantHash mapping;
HFMModel* hfmModel = readFBX(fbxData, mapping); HFMModel::Pointer hfmModel = FBXSerializer().read(fbxData, mapping);
size_t totalVertexCount = 0; size_t totalVertexCount = 0;
size_t totalIndexCount = 0; size_t totalIndexCount = 0;
size_t totalPartCount = 0; size_t totalPartCount = 0;
@ -163,7 +163,6 @@ void TestFbx::parseFbx(const QByteArray& fbxData) {
_vertexBuffer->append(vertices); _vertexBuffer->append(vertices);
_indexBuffer->append(indices); _indexBuffer->append(indices);
_indirectBuffer->append(parts); _indirectBuffer->append(parts);
delete hfmModel;
} }
void TestFbx::renderTest(size_t testId, RenderArgs* args) { void TestFbx::renderTest(size_t testId, RenderArgs* args) {

View file

@ -12,7 +12,7 @@
#include "SkeletonDumpApp.h" #include "SkeletonDumpApp.h"
#include <QCommandLineParser> #include <QCommandLineParser>
#include <QFile> #include <QFile>
#include <FBXReader.h> #include <FBXSerializer.h>
#include <AnimSkeleton.h> #include <AnimSkeleton.h>
SkeletonDumpApp::SkeletonDumpApp(int argc, char* argv[]) : QCoreApplication(argc, argv) { SkeletonDumpApp::SkeletonDumpApp(int argc, char* argv[]) : QCoreApplication(argc, argv) {
@ -54,7 +54,7 @@ SkeletonDumpApp::SkeletonDumpApp(int argc, char* argv[]) : QCoreApplication(argc
return; return;
} }
QByteArray blob = file.readAll(); QByteArray blob = file.readAll();
std::unique_ptr<HFMModel> geometry(readFBX(blob, QVariantHash())); HFMModel::Pointer geometry = FBXSerializer().read(blob, QVariantHash());
std::unique_ptr<AnimSkeleton> skeleton(new AnimSkeleton(*geometry)); std::unique_ptr<AnimSkeleton> skeleton(new AnimSkeleton(*geometry));
skeleton->dump(verbose); skeleton->dump(verbose);
} }

View file

@ -15,9 +15,11 @@
#include <QVector> #include <QVector>
#include <NumericalConstants.h> #include <NumericalConstants.h>
#include <FBXSerializer.h>
#include <OBJSerializer.h>
// FBXReader jumbles the order of the meshes by reading them back out of a hashtable. This will put // FBXSerializer jumbles the order of the meshes by reading them back out of a hashtable. This will put
// them back in the order in which they appeared in the file. // them back in the order in which they appeared in the file.
bool HFMModelLessThan(const HFMMesh& e1, const HFMMesh& e2) { bool HFMModelLessThan(const HFMMesh& e1, const HFMMesh& e2) {
return e1.meshIndex < e2.meshIndex; return e1.meshIndex < e2.meshIndex;
@ -43,10 +45,9 @@ bool vhacd::VHACDUtil::loadFBX(const QString filename, HFMModel& result) {
QByteArray fbxContents = fbx.readAll(); QByteArray fbxContents = fbx.readAll();
HFMModel::Pointer hfmModel; HFMModel::Pointer hfmModel;
if (filename.toLower().endsWith(".obj")) { if (filename.toLower().endsWith(".obj")) {
bool combineParts = false; hfmModel = OBJSerializer().read(fbxContents, QVariantHash(), filename);
hfmModel = OBJReader().readOBJ(fbxContents, QVariantHash(), combineParts);
} else if (filename.toLower().endsWith(".fbx")) { } else if (filename.toLower().endsWith(".fbx")) {
hfmModel.reset(readFBX(fbxContents, QVariantHash(), filename)); hfmModel = FBXSerializer().read(fbxContents, QVariantHash(), filename);
} else { } else {
qWarning() << "file has unknown extension" << filename; qWarning() << "file has unknown extension" << filename;
return false; return false;

View file

@ -18,10 +18,10 @@
#include <vector> #include <vector>
#include <chrono> //c++11 feature #include <chrono> //c++11 feature
#include <QFile> #include <QFile>
#include <FBXReader.h>
#include <OBJReader.h>
#include <VHACD.h> #include <VHACD.h>
#include <hfm/HFM.h>
namespace vhacd { namespace vhacd {
class VHACDUtil { class VHACDUtil {
public: public:

View file

@ -15,7 +15,7 @@
#include <QCoreApplication> #include <QCoreApplication>
#include <FBXReader.h> #include <FBXSerializer.h>
const int VHACD_RETURN_CODE_FAILURE_TO_READ = 1; const int VHACD_RETURN_CODE_FAILURE_TO_READ = 1;
const int VHACD_RETURN_CODE_FAILURE_TO_WRITE = 2; const int VHACD_RETURN_CODE_FAILURE_TO_WRITE = 2;