object display correctly now?

This commit is contained in:
Seth Alves 2015-03-07 11:28:30 -08:00
parent 3642e93b3f
commit 05e0fe3536

View file

@ -2,6 +2,8 @@
// http://en.wikipedia.org/wiki/Wavefront_.obj_file // http://en.wikipedia.org/wiki/Wavefront_.obj_file
// http://www.scratchapixel.com/old/lessons/3d-advanced-lessons/obj-file-format/obj-file-format/
// http://paulbourke.net/dataformats/obj/
#include <QBuffer> #include <QBuffer>
@ -28,6 +30,7 @@ private:
int _pushedBackToken; int _pushedBackToken;
}; };
int OBJTokenizer::nextToken() { int OBJTokenizer::nextToken() {
if (_pushedBackToken != -1) { if (_pushedBackToken != -1) {
int token = _pushedBackToken; int token = _pushedBackToken;
@ -78,31 +81,22 @@ int OBJTokenizer::nextToken() {
} }
bool parseOBJGroup(OBJTokenizer &tokenizer, const QVariantHash& mapping, FBXGeometry &geometry) {
bool parseOBJMesh(OBJTokenizer &tokenizer, const QVariantHash& mapping, FBXGeometry &geometry, int& indexStart) { FBXMesh &mesh = geometry.meshes[0];
FBXMesh mesh; mesh.parts.append(FBXMeshPart());
FBXMeshPart meshPart; FBXMeshPart &meshPart = mesh.parts.last();
bool sawG = false; bool sawG = false;
bool meshHasData = true;
bool result = true; bool result = true;
meshPart.materialID = QString("dontknow") + QString::number(mesh.parts.count());
// QString materialID;
// model::MaterialPointer _material;
meshPart.materialID = "dontknow";
// meshPart._material = { glm::vec3(1.0f, 1.0f, 1.0f), glm::vec3(1.0f, 1.0f, 1.0f), glm::vec3(), 96.0f, 1.0f };
meshPart._material = model::MaterialPointer(new model::Material());
meshPart.opacity = 1.0; meshPart.opacity = 1.0;
meshPart._material = model::MaterialPointer(new model::Material());
meshPart._material->setDiffuse(glm::vec3(1.0, 1.0, 1.0));
meshPart._material->setOpacity(1.0);
meshPart._material->setSpecular(glm::vec3(1.0, 1.0, 1.0));
meshPart._material->setShininess(96.0);
meshPart._material->setEmissive(glm::vec3(0.0, 0.0, 0.0));
// material._material->setEmissive(material.emissive);
// material._material->setDiffuse(material.diffuse);
// material._material->setSpecular(material.specular);
// material._material->setShininess(material.shininess);
// material._material->setOpacity(material.opacity);
try { // XXX move this out/up
while (true) { while (true) {
if (tokenizer.nextToken() != OBJTokenizer::DATUM_TOKEN) { if (tokenizer.nextToken() != OBJTokenizer::DATUM_TOKEN) {
result = false; result = false;
@ -119,7 +113,6 @@ bool parseOBJMesh(OBJTokenizer &tokenizer, const QVariantHash& mapping, FBXGeome
if (tokenizer.nextToken() != OBJTokenizer::DATUM_TOKEN) { break; } if (tokenizer.nextToken() != OBJTokenizer::DATUM_TOKEN) { break; }
QByteArray groupName = tokenizer.getDatum(); QByteArray groupName = tokenizer.getDatum();
meshPart.materialID = groupName; meshPart.materialID = groupName;
meshHasData = true;
} else if (token == "v") { } else if (token == "v") {
if (tokenizer.nextToken() != OBJTokenizer::DATUM_TOKEN) { break; } if (tokenizer.nextToken() != OBJTokenizer::DATUM_TOKEN) { break; }
float x = std::stof(tokenizer.getDatum().data()); float x = std::stof(tokenizer.getDatum().data());
@ -129,13 +122,10 @@ bool parseOBJMesh(OBJTokenizer &tokenizer, const QVariantHash& mapping, FBXGeome
if (tokenizer.nextToken() != OBJTokenizer::DATUM_TOKEN) { break; } if (tokenizer.nextToken() != OBJTokenizer::DATUM_TOKEN) { break; }
float y = std::stof(tokenizer.getDatum().data()); float y = std::stof(tokenizer.getDatum().data());
if (tokenizer.nextToken() != OBJTokenizer::DATUM_TOKEN) { break; } if (tokenizer.nextToken() != OBJTokenizer::DATUM_TOKEN) { break; }
// the spec gets vague here. might be w, might be a color... chop it off. // the spec gets vague here. might be w, might be a color... chop it off.
tokenizer.skipLine(); tokenizer.skipLine();
mesh.vertices.append(glm::vec3(x, y, z)); mesh.vertices.append(glm::vec3(x, y, z));
mesh.colors.append(glm::vec3(1, 1, 1)); mesh.colors.append(glm::vec3(1, 1, 1));
meshHasData = true;
} else if (token == "f") { } else if (token == "f") {
// a face can have 3 or more vertices // a face can have 3 or more vertices
QVector<int> indices; QVector<int> indices;
@ -146,9 +136,8 @@ bool parseOBJMesh(OBJTokenizer &tokenizer, const QVariantHash& mapping, FBXGeome
// negative indexes count backward from the current end of the vertex list // negative indexes count backward from the current end of the vertex list
vertexIndex = (vertexIndex >= 0 ? vertexIndex : mesh.vertices.count() + vertexIndex + 1); vertexIndex = (vertexIndex >= 0 ? vertexIndex : mesh.vertices.count() + vertexIndex + 1);
// obj index is 1 based // obj index is 1 based
vertexIndex = vertexIndex - 1 - indexStart; assert(vertexIndex >= 1);
assert(vertexIndex >= 0); indices.append(vertexIndex - 1);
indices.append(vertexIndex);
} }
catch(const std::exception& e) { catch(const std::exception& e) {
// wasn't a number, but it back. // wasn't a number, but it back.
@ -158,76 +147,59 @@ bool parseOBJMesh(OBJTokenizer &tokenizer, const QVariantHash& mapping, FBXGeome
} }
if (indices.count() == 3) { if (indices.count() == 3) {
meshPart.triangleIndices << indices; // flip these around (because of the y/z swap above) so our triangles face outward
meshPart.triangleIndices.append(indices[0]);
meshPart.triangleIndices.append(indices[2]);
meshPart.triangleIndices.append(indices[1]);
} else if (indices.count() == 4) { } else if (indices.count() == 4) {
meshPart.quadIndices << indices; meshPart.quadIndices << indices;
} else { } else {
qDebug() << "no support for more than 4 vertices on a face in OBJ files"; qDebug() << "no support for more than 4 vertices on a face in OBJ files";
} }
meshHasData = true;
} else { } else {
// something we don't (yet) care about // something we don't (yet) care about
// vp qDebug() << "OBJ parser is skipping a line with" << token;
// mtllib
// usemtl
// s 1, s off
qDebug() << "skipping line with" << token;
tokenizer.skipLine(); tokenizer.skipLine();
} }
} }
}
catch(const std::exception& e) {
// something went wrong, stop here.
qDebug() << "something went wrong in obj reader";
return false;
}
done: done:
#if 0
// add bogus normal data for this mesh
// mesh.normals.resize(mesh.vertices.count());
mesh.normals.fill(glm::vec3(0,0,0), mesh.vertices.count());
mesh.tangents.fill(glm::vec3(0,0,0), mesh.vertices.count());
int triCount = meshPart.triangleIndices.count() / 3;
for (int i = 0; i < triCount; i++) {
int p0Index = meshPart.triangleIndices[ i*3 ];
int p1Index = meshPart.triangleIndices[ i*3+1 ];
int p2Index = meshPart.triangleIndices[ i*3+2 ];
glm::vec3 p0 = mesh.vertices[ p0Index ];
glm::vec3 p1 = mesh.vertices[ p1Index ];
glm::vec3 p2 = mesh.vertices[ p2Index ];
glm::vec3 n = glm::cross(p2 - p0, p1 - p0);
glm::vec3 t = glm::cross(p2 - p0, n);
mesh.normals[ p0Index ] = n;
mesh.normals[ p1Index ] = n;
mesh.normals[ p2Index ] = n;
mesh.tangents[ p0Index ] = t;
mesh.tangents[ p1Index ] = t;
mesh.tangents[ p2Index ] = t;
}
#endif
if (! meshHasData)
return result; 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<QByteArray*>(&model));
buffer.open(QIODevice::ReadOnly);
return readOBJ(&buffer, mapping);
}
FBXGeometry readOBJ(QIODevice* device, const QVariantHash& mapping) {
FBXGeometry geometry;
OBJTokenizer tokenizer(device);
geometry.meshExtents.reset();
geometry.meshes.append(FBXMesh());
try {
while (parseOBJGroup(tokenizer, mapping, geometry)) {
}
FBXMesh &mesh = geometry.meshes[0];
mesh.meshExtents.reset(); mesh.meshExtents.reset();
foreach (const glm::vec3& vertex, mesh.vertices) { foreach (const glm::vec3& vertex, mesh.vertices) {
mesh.meshExtents.addPoint(vertex); mesh.meshExtents.addPoint(vertex);
geometry.meshExtents.addPoint(vertex); geometry.meshExtents.addPoint(vertex);
} }
mesh.parts.append(meshPart);
geometry.meshes.append(mesh);
geometry.joints.resize(1); geometry.joints.resize(1);
geometry.joints[ 0 ].isFree = false; geometry.joints[ 0 ].isFree = false;
// geometry.joints[ 0 ].freeLineage; // geometry.joints[ 0 ].freeLineage;
@ -252,40 +224,36 @@ bool parseOBJMesh(OBJTokenizer &tokenizer, const QVariantHash& mapping, FBXGeome
geometry.joints[ 0 ].shapeType = SPHERE_SHAPE; geometry.joints[ 0 ].shapeType = SPHERE_SHAPE;
geometry.joints[ 0 ].isSkeletonJoint = false; geometry.joints[ 0 ].isSkeletonJoint = false;
indexStart += mesh.vertices.count(); // add bogus normal data for this mesh
mesh.normals.fill(glm::vec3(0,0,0), mesh.vertices.count());
mesh.tangents.fill(glm::vec3(0,0,0), mesh.vertices.count());
return result; foreach (FBXMeshPart meshPart, mesh.parts) {
} int triCount = meshPart.triangleIndices.count() / 3;
for (int i = 0; i < triCount; i++) {
int p0Index = meshPart.triangleIndices[ i*3 ];
int p1Index = meshPart.triangleIndices[ i*3+1 ];
int p2Index = meshPart.triangleIndices[ i*3+2 ];
glm::vec3 p0 = mesh.vertices[ p0Index ];
glm::vec3 p1 = mesh.vertices[ p1Index ];
glm::vec3 p2 = mesh.vertices[ p2Index ];
glm::vec3 n = glm::cross(p1 - p0, p2 - p0);
glm::vec3 t = glm::cross(p2 - p0, n);
FBXGeometry extractOBJGeometry(const FBXNode& node, const QVariantHash& mapping) { mesh.normals[ p0Index ] = n;
FBXGeometry geometry; mesh.normals[ p1Index ] = n;
return geometry; mesh.normals[ p2Index ] = n;
}
mesh.tangents[ p0Index ] = t;
mesh.tangents[ p1Index ] = t;
FBXGeometry readOBJ(const QByteArray& model, const QVariantHash& mapping) { mesh.tangents[ p2Index ] = t;
QBuffer buffer(const_cast<QByteArray*>(&model));
buffer.open(QIODevice::ReadOnly);
return readOBJ(&buffer, mapping);
}
FBXGeometry readOBJ(QIODevice* device, const QVariantHash& mapping) {
FBXGeometry geometry;
OBJTokenizer tokenizer(device);
int indexStart = 0;
geometry.meshExtents.reset();
while (true) {
if (!parseOBJMesh(tokenizer, mapping, geometry, indexStart)) {
break;
} }
}
qDebug() << "indexStart is" << indexStart; }
catch(const std::exception& e) {
qDebug() << "something went wrong in OBJ reader";
} }
return geometry; return geometry;