mirror of
https://github.com/overte-org/overte.git
synced 2025-04-26 02:16:26 +02:00
Merge branch 'master' of https://github.com/worklist/hifi into voxel_render_pipeline_improvement
This commit is contained in:
commit
2450d64016
4 changed files with 173 additions and 88 deletions
|
@ -19,12 +19,6 @@
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
FBXNode parseFBX(const QByteArray& data) {
|
|
||||||
QBuffer buffer(const_cast<QByteArray*>(&data));
|
|
||||||
buffer.open(QIODevice::ReadOnly);
|
|
||||||
return parseFBX(&buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class T> QVariant readArray(QDataStream& in) {
|
template<class T> QVariant readArray(QDataStream& in) {
|
||||||
quint32 arrayLength;
|
quint32 arrayLength;
|
||||||
quint32 encoding;
|
quint32 encoding;
|
||||||
|
@ -189,6 +183,41 @@ FBXNode parseFBX(QIODevice* device) {
|
||||||
return top;
|
return top;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QVariantHash parseMapping(QIODevice* device) {
|
||||||
|
QVariantHash properties;
|
||||||
|
|
||||||
|
QByteArray line;
|
||||||
|
while (!(line = device->readLine()).isEmpty()) {
|
||||||
|
if ((line = line.trimmed()).startsWith('#')) {
|
||||||
|
continue; // comment
|
||||||
|
}
|
||||||
|
QList<QByteArray> sections = line.split('=');
|
||||||
|
if (sections.size() < 2) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
QByteArray name = sections.at(0).trimmed();
|
||||||
|
if (sections.size() == 2) {
|
||||||
|
properties.insert(name, sections.at(1).trimmed());
|
||||||
|
|
||||||
|
} else if (sections.size() == 3) {
|
||||||
|
QVariantHash heading = properties.value(name).toHash();
|
||||||
|
heading.insert(sections.at(1).trimmed(), sections.at(2).trimmed());
|
||||||
|
properties.insert(name, heading);
|
||||||
|
|
||||||
|
} else if (sections.size() >= 4) {
|
||||||
|
QVariantHash heading = properties.value(name).toHash();
|
||||||
|
QVariantList contents;
|
||||||
|
for (int i = 2; i < sections.size(); i++) {
|
||||||
|
contents.append(sections.at(i).trimmed());
|
||||||
|
}
|
||||||
|
heading.insertMulti(sections.at(1).trimmed(), contents);
|
||||||
|
properties.insert(name, heading);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return properties;
|
||||||
|
}
|
||||||
|
|
||||||
QVector<glm::vec3> createVec3Vector(const QVector<double>& doubleVector) {
|
QVector<glm::vec3> createVec3Vector(const QVector<double>& doubleVector) {
|
||||||
QVector<glm::vec3> values;
|
QVector<glm::vec3> values;
|
||||||
for (const double* it = doubleVector.constData(), *end = it + doubleVector.size(); it != end; ) {
|
for (const double* it = doubleVector.constData(), *end = it + doubleVector.size(); it != end; ) {
|
||||||
|
@ -269,19 +298,6 @@ const char* FACESHIFT_BLENDSHAPES[] = {
|
||||||
""
|
""
|
||||||
};
|
};
|
||||||
|
|
||||||
QHash<QByteArray, int> createBlendshapeMap() {
|
|
||||||
QHash<QByteArray, int> map;
|
|
||||||
for (int i = 0;; i++) {
|
|
||||||
QByteArray name = FACESHIFT_BLENDSHAPES[i];
|
|
||||||
if (name != "") {
|
|
||||||
map.insert(name, i);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
return map;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class Transform {
|
class Transform {
|
||||||
public:
|
public:
|
||||||
bool inheritScale;
|
bool inheritScale;
|
||||||
|
@ -315,11 +331,10 @@ glm::mat4 getGlobalTransform(const QMultiHash<qint64, qint64>& parentMap, const
|
||||||
class ExtractedBlendshape {
|
class ExtractedBlendshape {
|
||||||
public:
|
public:
|
||||||
qint64 id;
|
qint64 id;
|
||||||
int index;
|
|
||||||
FBXBlendshape blendshape;
|
FBXBlendshape blendshape;
|
||||||
};
|
};
|
||||||
|
|
||||||
FBXGeometry extractFBXGeometry(const FBXNode& node) {
|
FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping) {
|
||||||
QHash<qint64, FBXMesh> meshes;
|
QHash<qint64, FBXMesh> meshes;
|
||||||
QVector<ExtractedBlendshape> blendshapes;
|
QVector<ExtractedBlendshape> blendshapes;
|
||||||
QMultiHash<qint64, qint64> parentMap;
|
QMultiHash<qint64, qint64> parentMap;
|
||||||
|
@ -329,10 +344,35 @@ FBXGeometry extractFBXGeometry(const FBXNode& node) {
|
||||||
QHash<qint64, QByteArray> textureFilenames;
|
QHash<qint64, QByteArray> textureFilenames;
|
||||||
QHash<qint64, qint64> diffuseTextures;
|
QHash<qint64, qint64> diffuseTextures;
|
||||||
QHash<qint64, qint64> bumpTextures;
|
QHash<qint64, qint64> bumpTextures;
|
||||||
|
|
||||||
|
QVariantHash joints = mapping.value("joint").toHash();
|
||||||
|
QByteArray jointEyeLeftName = joints.value("jointEyeLeft", "jointEyeLeft").toByteArray();
|
||||||
|
QByteArray jointEyeRightName = joints.value("jointEyeRight", "jointEyeRight").toByteArray();
|
||||||
|
QByteArray jointNeckName = joints.value("jointNeck", "jointNeck").toByteArray();
|
||||||
qint64 jointEyeLeftID = 0;
|
qint64 jointEyeLeftID = 0;
|
||||||
qint64 jointEyeRightID = 0;
|
qint64 jointEyeRightID = 0;
|
||||||
qint64 jointNeckID = 0;
|
qint64 jointNeckID = 0;
|
||||||
|
|
||||||
|
QVariantHash blendshapeMappings = mapping.value("bs").toHash();
|
||||||
|
QHash<QByteArray, QPair<int, float> > blendshapeIndices;
|
||||||
|
for (int i = 0;; i++) {
|
||||||
|
QByteArray blendshapeName = FACESHIFT_BLENDSHAPES[i];
|
||||||
|
if (blendshapeName.isEmpty()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
QList<QVariant> mappings = blendshapeMappings.values(blendshapeName);
|
||||||
|
if (mappings.isEmpty()) {
|
||||||
|
blendshapeIndices.insert("ExpressionBlendshapes." + blendshapeName, QPair<int, float>(i, 1.0f));
|
||||||
|
} else {
|
||||||
|
foreach (const QVariant& mapping, mappings) {
|
||||||
|
QVariantList blendshapeMapping = mapping.toList();
|
||||||
|
blendshapeIndices.insert(blendshapeMapping.at(0).toByteArray(),
|
||||||
|
QPair<int, float>(i, blendshapeMapping.at(1).toFloat()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
QHash<qint64, QPair<int, float> > blendshapeChannelIndices;
|
||||||
|
|
||||||
foreach (const FBXNode& child, node.children) {
|
foreach (const FBXNode& child, node.children) {
|
||||||
if (child.name == "Objects") {
|
if (child.name == "Objects") {
|
||||||
foreach (const FBXNode& object, child.children) {
|
foreach (const FBXNode& object, child.children) {
|
||||||
|
@ -387,14 +427,16 @@ FBXGeometry extractFBXGeometry(const FBXNode& node) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// same with the tex coords
|
// same with the tex coords
|
||||||
mesh.texCoords.resize(mesh.vertices.size());
|
if (!texCoordIndices.isEmpty()) {
|
||||||
for (int i = 0, n = polygonIndices.size(); i < n; i++) {
|
mesh.texCoords.resize(mesh.vertices.size());
|
||||||
int index = polygonIndices.at(i);
|
for (int i = 0, n = polygonIndices.size(); i < n; i++) {
|
||||||
int texCoordIndex = texCoordIndices.at(i);
|
int index = polygonIndices.at(i);
|
||||||
if (texCoordIndex >= 0) {
|
int texCoordIndex = texCoordIndices.at(i);
|
||||||
mesh.texCoords[index < 0 ? (-index - 1) : index] = texCoords.at(texCoordIndex);
|
if (texCoordIndex >= 0) {
|
||||||
}
|
mesh.texCoords[index < 0 ? (-index - 1) : index] = texCoords.at(texCoordIndex);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// convert the polygons to quads and triangles
|
// convert the polygons to quads and triangles
|
||||||
for (const int* beginIndex = polygonIndices.constData(), *end = beginIndex + polygonIndices.size();
|
for (const int* beginIndex = polygonIndices.constData(), *end = beginIndex + polygonIndices.size();
|
||||||
|
@ -441,22 +483,18 @@ FBXGeometry extractFBXGeometry(const FBXNode& node) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// the name is followed by a null and some type info
|
|
||||||
QByteArray name = object.properties.at(1).toByteArray();
|
|
||||||
static QHash<QByteArray, int> blendshapeMap = createBlendshapeMap();
|
|
||||||
extracted.index = blendshapeMap.value(name.left(name.indexOf('\0')));
|
|
||||||
|
|
||||||
blendshapes.append(extracted);
|
blendshapes.append(extracted);
|
||||||
}
|
}
|
||||||
} else if (object.name == "Model") {
|
} else if (object.name == "Model") {
|
||||||
QByteArray name = object.properties.at(1).toByteArray();
|
QByteArray name = object.properties.at(1).toByteArray();
|
||||||
if (name.startsWith("jointEyeLeft") || name.startsWith("EyeL") || name.startsWith("joint_Leye")) {
|
name = name.left(name.indexOf('\0'));
|
||||||
|
if (name == jointEyeLeftName || name == "EyeL" || name == "joint_Leye") {
|
||||||
jointEyeLeftID = object.properties.at(0).value<qint64>();
|
jointEyeLeftID = object.properties.at(0).value<qint64>();
|
||||||
|
|
||||||
} else if (name.startsWith("jointEyeRight") || name.startsWith("EyeR") || name.startsWith("joint_Reye")) {
|
} else if (name == jointEyeRightName || name == "EyeR" || name == "joint_Reye") {
|
||||||
jointEyeRightID = object.properties.at(0).value<qint64>();
|
jointEyeRightID = object.properties.at(0).value<qint64>();
|
||||||
|
|
||||||
} else if (name.startsWith("jointNeck") || name.startsWith("NeckRot") || name.startsWith("joint_neck")) {
|
} else if (name == jointNeckName || name == "NeckRot" || name == "joint_neck") {
|
||||||
jointNeckID = object.properties.at(0).value<qint64>();
|
jointNeckID = object.properties.at(0).value<qint64>();
|
||||||
}
|
}
|
||||||
glm::vec3 translation;
|
glm::vec3 translation;
|
||||||
|
@ -526,12 +564,18 @@ FBXGeometry extractFBXGeometry(const FBXNode& node) {
|
||||||
subobject.properties.at(0).toByteArray());
|
subobject.properties.at(0).toByteArray());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (object.name == "Deformer" && object.properties.at(2) == "Cluster") {
|
} else if (object.name == "Deformer") {
|
||||||
foreach (const FBXNode& subobject, object.children) {
|
if (object.properties.at(2) == "Cluster") {
|
||||||
if (subobject.name == "TransformLink") {
|
foreach (const FBXNode& subobject, object.children) {
|
||||||
QVector<double> values = subobject.properties.at(0).value<QVector<double> >();
|
if (subobject.name == "TransformLink") {
|
||||||
transformLinkMatrices.insert(object.properties.at(0).value<qint64>(), createMat4(values));
|
QVector<double> values = subobject.properties.at(0).value<QVector<double> >();
|
||||||
|
transformLinkMatrices.insert(object.properties.at(0).value<qint64>(), createMat4(values));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
} else if (object.properties.at(2) == "BlendShapeChannel") {
|
||||||
|
QByteArray name = object.properties.at(1).toByteArray();
|
||||||
|
blendshapeChannelIndices.insert(object.properties.at(0).value<qint64>(),
|
||||||
|
blendshapeIndices.value(name.left(name.indexOf('\0'))));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -558,13 +602,21 @@ FBXGeometry extractFBXGeometry(const FBXNode& node) {
|
||||||
// assign the blendshapes to their corresponding meshes
|
// assign the blendshapes to their corresponding meshes
|
||||||
foreach (const ExtractedBlendshape& extracted, blendshapes) {
|
foreach (const ExtractedBlendshape& extracted, blendshapes) {
|
||||||
qint64 blendshapeChannelID = parentMap.value(extracted.id);
|
qint64 blendshapeChannelID = parentMap.value(extracted.id);
|
||||||
|
QPair<int, float> index = blendshapeChannelIndices.value(blendshapeChannelID);
|
||||||
qint64 blendshapeID = parentMap.value(blendshapeChannelID);
|
qint64 blendshapeID = parentMap.value(blendshapeChannelID);
|
||||||
qint64 meshID = parentMap.value(blendshapeID);
|
qint64 meshID = parentMap.value(blendshapeID);
|
||||||
FBXMesh& mesh = meshes[meshID];
|
FBXMesh& mesh = meshes[meshID];
|
||||||
mesh.blendshapes.resize(max(mesh.blendshapes.size(), extracted.index + 1));
|
mesh.blendshapes.resize(max(mesh.blendshapes.size(), index.first + 1));
|
||||||
mesh.blendshapes[extracted.index] = extracted.blendshape;
|
mesh.blendshapes[index.first] = extracted.blendshape;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// get offset transform from mapping
|
||||||
|
float offsetScale = mapping.value("scale", 1.0f).toFloat();
|
||||||
|
glm::mat4 offset = glm::translate(mapping.value("tx").toFloat(), mapping.value("ty").toFloat(),
|
||||||
|
mapping.value("tz").toFloat()) * glm::mat4_cast(glm::quat(glm::radians(glm::vec3(mapping.value("rx").toFloat(),
|
||||||
|
mapping.value("ry").toFloat(), mapping.value("rz").toFloat())))) *
|
||||||
|
glm::scale(offsetScale, offsetScale, offsetScale);
|
||||||
|
|
||||||
// as a temporary hack, put the mesh with the most blendshapes on top; assume it to be the face
|
// as a temporary hack, put the mesh with the most blendshapes on top; assume it to be the face
|
||||||
FBXGeometry geometry;
|
FBXGeometry geometry;
|
||||||
int mostBlendshapes = 0;
|
int mostBlendshapes = 0;
|
||||||
|
@ -601,11 +653,11 @@ FBXGeometry extractFBXGeometry(const FBXNode& node) {
|
||||||
|
|
||||||
// see http://stackoverflow.com/questions/13566608/loading-skinning-information-from-fbx for a discussion
|
// see http://stackoverflow.com/questions/13566608/loading-skinning-information-from-fbx for a discussion
|
||||||
// of skinning information in FBX
|
// of skinning information in FBX
|
||||||
glm::mat4 jointTransform = getGlobalTransform(parentMap, localTransforms, jointID);
|
glm::mat4 jointTransform = offset * getGlobalTransform(parentMap, localTransforms, jointID);
|
||||||
mesh.transform = jointTransform * glm::inverse(transformLinkMatrices.value(clusterID)) * modelTransform;
|
mesh.transform = jointTransform * glm::inverse(transformLinkMatrices.value(clusterID)) * modelTransform;
|
||||||
|
|
||||||
// extract translation component for pivot
|
// extract translation component for pivot
|
||||||
glm::mat4 jointTransformScaled = getGlobalTransform(parentMap, localTransforms, jointID, true);
|
glm::mat4 jointTransformScaled = offset * getGlobalTransform(parentMap, localTransforms, jointID, true);
|
||||||
mesh.pivot = glm::vec3(jointTransformScaled[3][0], jointTransformScaled[3][1], jointTransformScaled[3][2]);
|
mesh.pivot = glm::vec3(jointTransformScaled[3][0], jointTransformScaled[3][1], jointTransformScaled[3][2]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -620,7 +672,7 @@ FBXGeometry extractFBXGeometry(const FBXNode& node) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// extract translation component for neck pivot
|
// extract translation component for neck pivot
|
||||||
glm::mat4 neckTransform = getGlobalTransform(parentMap, localTransforms, jointNeckID, true);
|
glm::mat4 neckTransform = offset * getGlobalTransform(parentMap, localTransforms, jointNeckID, true);
|
||||||
geometry.neckPivot = glm::vec3(neckTransform[3][0], neckTransform[3][1], neckTransform[3][2]);
|
geometry.neckPivot = glm::vec3(neckTransform[3][0], neckTransform[3][1], neckTransform[3][2]);
|
||||||
|
|
||||||
return geometry;
|
return geometry;
|
||||||
|
@ -638,3 +690,13 @@ void printNode(const FBXNode& node, int indent) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FBXGeometry readFBX(const QByteArray& model, const QByteArray& mapping) {
|
||||||
|
QBuffer modelBuffer(const_cast<QByteArray*>(&model));
|
||||||
|
modelBuffer.open(QIODevice::ReadOnly);
|
||||||
|
|
||||||
|
QBuffer mappingBuffer(const_cast<QByteArray*>(&mapping));
|
||||||
|
mappingBuffer.open(QIODevice::ReadOnly);
|
||||||
|
|
||||||
|
return extractFBXGeometry(parseFBX(&modelBuffer), parseMapping(&mappingBuffer));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,8 +14,6 @@
|
||||||
|
|
||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
|
|
||||||
class QIODevice;
|
|
||||||
|
|
||||||
class FBXNode;
|
class FBXNode;
|
||||||
|
|
||||||
typedef QList<FBXNode> FBXNodeList;
|
typedef QList<FBXNode> FBXNodeList;
|
||||||
|
@ -68,17 +66,8 @@ public:
|
||||||
glm::vec3 neckPivot;
|
glm::vec3 neckPivot;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Parses the input from the supplied data as an FBX file.
|
/// Reads FBX geometry from the supplied model and mapping data.
|
||||||
/// \exception QString if an error occurs in parsing
|
/// \exception QString if an error occurs in parsing
|
||||||
FBXNode parseFBX(const QByteArray& data);
|
FBXGeometry readFBX(const QByteArray& model, const QByteArray& mapping);
|
||||||
|
|
||||||
/// Parses the input from the supplied device as an FBX file.
|
|
||||||
/// \exception QString if an error occurs in parsing
|
|
||||||
FBXNode parseFBX(QIODevice* device);
|
|
||||||
|
|
||||||
/// Extracts the geometry from a parsed FBX node.
|
|
||||||
FBXGeometry extractFBXGeometry(const FBXNode& node);
|
|
||||||
|
|
||||||
void printNode(const FBXNode& node, int indent = 0);
|
|
||||||
|
|
||||||
#endif /* defined(__interface__FBXReader__) */
|
#endif /* defined(__interface__FBXReader__) */
|
||||||
|
|
|
@ -250,21 +250,37 @@ QSharedPointer<NetworkGeometry> GeometryCache::getGeometry(const QUrl& url) {
|
||||||
return geometry;
|
return geometry;
|
||||||
}
|
}
|
||||||
|
|
||||||
NetworkGeometry::NetworkGeometry(const QUrl& url) : _reply(NULL) {
|
NetworkGeometry::NetworkGeometry(const QUrl& url) :
|
||||||
|
_modelReply(NULL),
|
||||||
|
_mappingReply(NULL)
|
||||||
|
{
|
||||||
if (!url.isValid()) {
|
if (!url.isValid()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
QNetworkRequest request(url);
|
QNetworkRequest modelRequest(url);
|
||||||
request.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferCache);
|
modelRequest.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferCache);
|
||||||
_reply = Application::getInstance()->getNetworkAccessManager()->get(request);
|
_modelReply = Application::getInstance()->getNetworkAccessManager()->get(modelRequest);
|
||||||
|
|
||||||
connect(_reply, SIGNAL(downloadProgress(qint64,qint64)), SLOT(handleDownloadProgress(qint64,qint64)));
|
connect(_modelReply, SIGNAL(downloadProgress(qint64,qint64)), SLOT(maybeReadModelWithMapping()));
|
||||||
connect(_reply, SIGNAL(error(QNetworkReply::NetworkError)), SLOT(handleReplyError()));
|
connect(_modelReply, SIGNAL(error(QNetworkReply::NetworkError)), SLOT(handleModelReplyError()));
|
||||||
|
|
||||||
|
QUrl mappingURL = url;
|
||||||
|
QString path = url.path();
|
||||||
|
mappingURL.setPath(path.left(path.lastIndexOf('.')) + ".fst");
|
||||||
|
QNetworkRequest mappingRequest(mappingURL);
|
||||||
|
mappingRequest.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferCache);
|
||||||
|
_mappingReply = Application::getInstance()->getNetworkAccessManager()->get(mappingRequest);
|
||||||
|
|
||||||
|
connect(_mappingReply, SIGNAL(downloadProgress(qint64,qint64)), SLOT(maybeReadModelWithMapping()));
|
||||||
|
connect(_mappingReply, SIGNAL(error(QNetworkReply::NetworkError)), SLOT(handleMappingReplyError()));
|
||||||
}
|
}
|
||||||
|
|
||||||
NetworkGeometry::~NetworkGeometry() {
|
NetworkGeometry::~NetworkGeometry() {
|
||||||
if (_reply != NULL) {
|
if (_modelReply != NULL) {
|
||||||
delete _reply;
|
delete _modelReply;
|
||||||
|
}
|
||||||
|
if (_mappingReply != NULL) {
|
||||||
|
delete _mappingReply;
|
||||||
}
|
}
|
||||||
foreach (const NetworkMesh& mesh, _meshes) {
|
foreach (const NetworkMesh& mesh, _meshes) {
|
||||||
glDeleteBuffers(1, &mesh.indexBufferID);
|
glDeleteBuffers(1, &mesh.indexBufferID);
|
||||||
|
@ -272,19 +288,43 @@ NetworkGeometry::~NetworkGeometry() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void NetworkGeometry::handleDownloadProgress(qint64 bytesReceived, qint64 bytesTotal) {
|
void NetworkGeometry::handleModelReplyError() {
|
||||||
if (bytesReceived < bytesTotal && !_reply->isFinished()) {
|
qDebug() << _modelReply->errorString() << "\n";
|
||||||
|
|
||||||
|
_modelReply->disconnect(this);
|
||||||
|
_modelReply->deleteLater();
|
||||||
|
_modelReply = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void NetworkGeometry::handleMappingReplyError() {
|
||||||
|
_mappingReply->disconnect(this);
|
||||||
|
_mappingReply->deleteLater();
|
||||||
|
_mappingReply = NULL;
|
||||||
|
|
||||||
|
maybeReadModelWithMapping();
|
||||||
|
}
|
||||||
|
|
||||||
|
void NetworkGeometry::maybeReadModelWithMapping() {
|
||||||
|
if (_modelReply == NULL || !_modelReply->isFinished() || (_mappingReply != NULL && !_mappingReply->isFinished())) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
QUrl url = _reply->url();
|
QUrl url = _modelReply->url();
|
||||||
QByteArray entirety = _reply->readAll();
|
QByteArray model = _modelReply->readAll();
|
||||||
_reply->disconnect(this);
|
_modelReply->disconnect(this);
|
||||||
_reply->deleteLater();
|
_modelReply->deleteLater();
|
||||||
_reply = NULL;
|
_modelReply = NULL;
|
||||||
|
|
||||||
|
QByteArray mapping;
|
||||||
|
if (_mappingReply != NULL) {
|
||||||
|
mapping = _mappingReply->readAll();
|
||||||
|
_mappingReply->disconnect(this);
|
||||||
|
_mappingReply->deleteLater();
|
||||||
|
_mappingReply = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
_geometry = extractFBXGeometry(parseFBX(entirety));
|
_geometry = readFBX(model, mapping);
|
||||||
|
|
||||||
} catch (const QString& error) {
|
} catch (const QString& error) {
|
||||||
qDebug() << "Error reading " << url << ": " << error << "\n";
|
qDebug() << "Error reading " << url << ": " << error << "\n";
|
||||||
|
@ -338,11 +378,3 @@ void NetworkGeometry::handleDownloadProgress(qint64 bytesReceived, qint64 bytesT
|
||||||
_meshes.append(networkMesh);
|
_meshes.append(networkMesh);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void NetworkGeometry::handleReplyError() {
|
|
||||||
qDebug() << _reply->errorString() << "\n";
|
|
||||||
|
|
||||||
_reply->disconnect(this);
|
|
||||||
_reply->deleteLater();
|
|
||||||
_reply = NULL;
|
|
||||||
}
|
|
||||||
|
|
|
@ -64,12 +64,14 @@ public:
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
|
|
||||||
void handleDownloadProgress(qint64 bytesReceived, qint64 bytesTotal);
|
void handleModelReplyError();
|
||||||
void handleReplyError();
|
void handleMappingReplyError();
|
||||||
|
void maybeReadModelWithMapping();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
QNetworkReply* _reply;
|
QNetworkReply* _modelReply;
|
||||||
|
QNetworkReply* _mappingReply;
|
||||||
|
|
||||||
FBXGeometry _geometry;
|
FBXGeometry _geometry;
|
||||||
QVector<NetworkMesh> _meshes;
|
QVector<NetworkMesh> _meshes;
|
||||||
|
|
Loading…
Reference in a new issue