From 48144a46b1f4de9fd1c008cf6949a11095de59d0 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Tue, 31 Mar 2015 14:34:35 -0700 Subject: [PATCH] don't keep empty mesh-parts. take units hint from a common first-line comment, if it's there. --- libraries/fbx/src/OBJReader.cpp | 55 +++++++++++++++++++++++---------- 1 file changed, 39 insertions(+), 16 deletions(-) diff --git a/libraries/fbx/src/OBJReader.cpp b/libraries/fbx/src/OBJReader.cpp index db2733f27b..c87a942baa 100644 --- a/libraries/fbx/src/OBJReader.cpp +++ b/libraries/fbx/src/OBJReader.cpp @@ -27,7 +27,8 @@ public: enum SpecialToken { NO_TOKEN = -1, NO_PUSHBACKED_TOKEN = -1, - DATUM_TOKEN = 0x100 + DATUM_TOKEN = 0x100, + COMMENT_TOKEN = 0x101 }; int nextToken(); const QByteArray& getDatum() const { return _datum; } @@ -35,11 +36,13 @@ public: void skipLine() { _device->readLine(); } void pushBackToken(int token) { _pushedBackToken = token; } void ungetChar(char ch) { _device->ungetChar(ch); } + const QString getComment() const { return _comment; } private: QIODevice* _device; QByteArray _datum; int _pushedBackToken; + QString _comment; }; @@ -56,9 +59,11 @@ int OBJTokenizer::nextToken() { continue; // skip whitespace } switch (ch) { - case '#': - _device->readLine(); // skip the comment - break; + case '#': { + _comment = _device->readLine(); // skip the comment + qDebug() << "COMMENT:" << _comment; + return COMMENT_TOKEN; + } case '\"': _datum = ""; @@ -104,7 +109,8 @@ bool OBJTokenizer::isNextTokenFloat() { } bool parseOBJGroup(OBJTokenizer &tokenizer, const QVariantHash& mapping, - FBXGeometry &geometry, QVector& faceNormals, QVector& faceNormalIndexes) { + FBXGeometry &geometry, QVector& faceNormals, QVector& faceNormalIndexes, + float& scaleGuess) { FBXMesh &mesh = geometry.meshes[0]; mesh.parts.append(FBXMeshPart()); FBXMeshPart &meshPart = mesh.parts.last(); @@ -128,7 +134,17 @@ bool parseOBJGroup(OBJTokenizer &tokenizer, const QVariantHash& mapping, meshPart._material->setEmissive(glm::vec3(0.0, 0.0, 0.0)); while (true) { - if (tokenizer.nextToken() != OBJTokenizer::DATUM_TOKEN) { + int tokenType = tokenizer.nextToken(); + if (tokenType == OBJTokenizer::COMMENT_TOKEN) { + if (tokenizer.getComment().contains("This file uses centimeters as units")) { + scaleGuess = 1.0f / 100.0f; + } + if (tokenizer.getComment().contains("This file uses millimeters as units")) { + scaleGuess = 1.0f / 1000.0f; + } + continue; + } + if (tokenType != OBJTokenizer::DATUM_TOKEN) { result = false; break; } @@ -192,6 +208,7 @@ bool parseOBJGroup(OBJTokenizer &tokenizer, const QVariantHash& mapping, while (true) { if (tokenizer.nextToken() != OBJTokenizer::DATUM_TOKEN) { if (indices.count() == 0) { + // nonsense, bail out. goto done; } break; @@ -266,22 +283,22 @@ bool parseOBJGroup(OBJTokenizer &tokenizer, const QVariantHash& mapping, } } else { // something we don't (yet) care about - qDebug() << "OBJ parser is skipping a line with" << token; + // qDebug() << "OBJ parser is skipping a line with" << token; tokenizer.skipLine(); } } done: + + if (meshPart.triangleIndices.size() == 0 && meshPart.quadIndices.size() == 0) { + // empty mesh? + mesh.parts.pop_back(); + } + return result; } -FBXGeometry extractOBJGeometry(const FBXNode& node, const QVariantHash& mapping) { - FBXGeometry geometry; - return geometry; -} - - FBXGeometry readOBJ(const QByteArray& model, const QVariantHash& mapping) { QBuffer buffer(const_cast(&model)); buffer.open(QIODevice::ReadOnly); @@ -294,24 +311,30 @@ FBXGeometry readOBJ(QIODevice* device, const QVariantHash& mapping) { OBJTokenizer tokenizer(device); QVector faceNormalIndexes; QVector faceNormals; + float scaleGuess = 1.0f; faceNormalIndexes.clear(); geometry.meshExtents.reset(); geometry.meshes.append(FBXMesh()); - - try { // call parseOBJGroup as long as it's returning true. Each successful call will // add a new meshPart to the geometry's single mesh. bool success = true; while (success) { - success = parseOBJGroup(tokenizer, mapping, geometry, faceNormals, faceNormalIndexes); + success = parseOBJGroup(tokenizer, mapping, geometry, faceNormals, faceNormalIndexes, scaleGuess); } FBXMesh &mesh = geometry.meshes[0]; + // if we got a hint about units, scale all the points + if (scaleGuess != 1.0f) { + for (int i = 0; i < mesh.vertices.size(); i++) { + mesh.vertices[i] *= scaleGuess; + } + } + mesh.meshExtents.reset(); foreach (const glm::vec3& vertex, mesh.vertices) { mesh.meshExtents.addPoint(vertex);