mirror of
https://github.com/overte-org/overte.git
synced 2025-04-20 12:04:18 +02:00
object display correctly now?
This commit is contained in:
parent
3642e93b3f
commit
05e0fe3536
1 changed files with 136 additions and 168 deletions
|
@ -2,6 +2,8 @@
|
|||
|
||||
|
||||
// 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>
|
||||
|
@ -28,6 +30,7 @@ private:
|
|||
int _pushedBackToken;
|
||||
};
|
||||
|
||||
|
||||
int OBJTokenizer::nextToken() {
|
||||
if (_pushedBackToken != -1) {
|
||||
int token = _pushedBackToken;
|
||||
|
@ -78,194 +81,99 @@ int OBJTokenizer::nextToken() {
|
|||
}
|
||||
|
||||
|
||||
|
||||
bool parseOBJMesh(OBJTokenizer &tokenizer, const QVariantHash& mapping, FBXGeometry &geometry, int& indexStart) {
|
||||
FBXMesh mesh;
|
||||
FBXMeshPart meshPart;
|
||||
bool parseOBJGroup(OBJTokenizer &tokenizer, const QVariantHash& mapping, FBXGeometry &geometry) {
|
||||
FBXMesh &mesh = geometry.meshes[0];
|
||||
mesh.parts.append(FBXMeshPart());
|
||||
FBXMeshPart &meshPart = mesh.parts.last();
|
||||
bool sawG = false;
|
||||
bool meshHasData = true;
|
||||
bool result = true;
|
||||
|
||||
|
||||
// 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.materialID = QString("dontknow") + QString::number(mesh.parts.count());
|
||||
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) {
|
||||
if (tokenizer.nextToken() != OBJTokenizer::DATUM_TOKEN) {
|
||||
result = false;
|
||||
while (true) {
|
||||
if (tokenizer.nextToken() != OBJTokenizer::DATUM_TOKEN) {
|
||||
result = false;
|
||||
break;
|
||||
}
|
||||
QByteArray token = tokenizer.getDatum();
|
||||
if (token == "g") {
|
||||
if (sawG) {
|
||||
// we've encountered the beginning of the next group.
|
||||
tokenizer.pushBackToken(OBJTokenizer::DATUM_TOKEN);
|
||||
break;
|
||||
}
|
||||
QByteArray token = tokenizer.getDatum();
|
||||
if (token == "g") {
|
||||
if (sawG) {
|
||||
// we've encountered the beginning of the next group.
|
||||
sawG = true;
|
||||
if (tokenizer.nextToken() != OBJTokenizer::DATUM_TOKEN) { break; }
|
||||
QByteArray groupName = tokenizer.getDatum();
|
||||
meshPart.materialID = groupName;
|
||||
} else if (token == "v") {
|
||||
if (tokenizer.nextToken() != OBJTokenizer::DATUM_TOKEN) { break; }
|
||||
float x = std::stof(tokenizer.getDatum().data());
|
||||
// notice the order of z and y -- in OBJ files, up is the 3rd value
|
||||
if (tokenizer.nextToken() != OBJTokenizer::DATUM_TOKEN) { break; }
|
||||
float z = std::stof(tokenizer.getDatum().data());
|
||||
if (tokenizer.nextToken() != OBJTokenizer::DATUM_TOKEN) { break; }
|
||||
float y = std::stof(tokenizer.getDatum().data());
|
||||
if (tokenizer.nextToken() != OBJTokenizer::DATUM_TOKEN) { break; }
|
||||
// the spec gets vague here. might be w, might be a color... chop it off.
|
||||
tokenizer.skipLine();
|
||||
mesh.vertices.append(glm::vec3(x, y, z));
|
||||
mesh.colors.append(glm::vec3(1, 1, 1));
|
||||
} else if (token == "f") {
|
||||
// a face can have 3 or more vertices
|
||||
QVector<int> indices;
|
||||
while (true) {
|
||||
if (tokenizer.nextToken() != OBJTokenizer::DATUM_TOKEN) { goto done; }
|
||||
try {
|
||||
int vertexIndex = std::stoi(tokenizer.getDatum().data());
|
||||
// negative indexes count backward from the current end of the vertex list
|
||||
vertexIndex = (vertexIndex >= 0 ? vertexIndex : mesh.vertices.count() + vertexIndex + 1);
|
||||
// obj index is 1 based
|
||||
assert(vertexIndex >= 1);
|
||||
indices.append(vertexIndex - 1);
|
||||
}
|
||||
catch(const std::exception& e) {
|
||||
// wasn't a number, but it back.
|
||||
tokenizer.pushBackToken(OBJTokenizer::DATUM_TOKEN);
|
||||
break;
|
||||
}
|
||||
sawG = true;
|
||||
if (tokenizer.nextToken() != OBJTokenizer::DATUM_TOKEN) { break; }
|
||||
QByteArray groupName = tokenizer.getDatum();
|
||||
meshPart.materialID = groupName;
|
||||
meshHasData = true;
|
||||
} else if (token == "v") {
|
||||
if (tokenizer.nextToken() != OBJTokenizer::DATUM_TOKEN) { break; }
|
||||
float x = std::stof(tokenizer.getDatum().data());
|
||||
// notice the order of z and y -- in OBJ files, up is the 3rd value
|
||||
if (tokenizer.nextToken() != OBJTokenizer::DATUM_TOKEN) { break; }
|
||||
float z = std::stof(tokenizer.getDatum().data());
|
||||
if (tokenizer.nextToken() != OBJTokenizer::DATUM_TOKEN) { break; }
|
||||
float y = std::stof(tokenizer.getDatum().data());
|
||||
if (tokenizer.nextToken() != OBJTokenizer::DATUM_TOKEN) { break; }
|
||||
|
||||
// the spec gets vague here. might be w, might be a color... chop it off.
|
||||
tokenizer.skipLine();
|
||||
|
||||
mesh.vertices.append(glm::vec3(x, y, z));
|
||||
mesh.colors.append(glm::vec3(1, 1, 1));
|
||||
meshHasData = true;
|
||||
} else if (token == "f") {
|
||||
// a face can have 3 or more vertices
|
||||
QVector<int> indices;
|
||||
while (true) {
|
||||
if (tokenizer.nextToken() != OBJTokenizer::DATUM_TOKEN) { goto done; }
|
||||
try {
|
||||
int vertexIndex = std::stoi(tokenizer.getDatum().data());
|
||||
// negative indexes count backward from the current end of the vertex list
|
||||
vertexIndex = (vertexIndex >= 0 ? vertexIndex : mesh.vertices.count() + vertexIndex + 1);
|
||||
// obj index is 1 based
|
||||
vertexIndex = vertexIndex - 1 - indexStart;
|
||||
assert(vertexIndex >= 0);
|
||||
indices.append(vertexIndex);
|
||||
}
|
||||
catch(const std::exception& e) {
|
||||
// wasn't a number, but it back.
|
||||
tokenizer.pushBackToken(OBJTokenizer::DATUM_TOKEN);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (indices.count() == 3) {
|
||||
meshPart.triangleIndices << indices;
|
||||
} else if (indices.count() == 4) {
|
||||
meshPart.quadIndices << indices;
|
||||
} else {
|
||||
qDebug() << "no support for more than 4 vertices on a face in OBJ files";
|
||||
}
|
||||
meshHasData = true;
|
||||
} else {
|
||||
// something we don't (yet) care about
|
||||
// vp
|
||||
// mtllib
|
||||
// usemtl
|
||||
// s 1, s off
|
||||
|
||||
qDebug() << "skipping line with" << token;
|
||||
tokenizer.skipLine();
|
||||
}
|
||||
|
||||
if (indices.count() == 3) {
|
||||
// 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) {
|
||||
meshPart.quadIndices << indices;
|
||||
} else {
|
||||
qDebug() << "no support for more than 4 vertices on a face in OBJ files";
|
||||
}
|
||||
} else {
|
||||
// something we don't (yet) care about
|
||||
qDebug() << "OBJ parser is skipping a line with" << token;
|
||||
tokenizer.skipLine();
|
||||
}
|
||||
}
|
||||
catch(const std::exception& e) {
|
||||
// something went wrong, stop here.
|
||||
qDebug() << "something went wrong in obj reader";
|
||||
return false;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
|
||||
mesh.meshExtents.reset();
|
||||
foreach (const glm::vec3& vertex, mesh.vertices) {
|
||||
mesh.meshExtents.addPoint(vertex);
|
||||
geometry.meshExtents.addPoint(vertex);
|
||||
}
|
||||
|
||||
mesh.parts.append(meshPart);
|
||||
geometry.meshes.append(mesh);
|
||||
|
||||
|
||||
geometry.joints.resize(1);
|
||||
geometry.joints[ 0 ].isFree = false;
|
||||
// geometry.joints[ 0 ].freeLineage;
|
||||
geometry.joints[ 0 ].parentIndex = -1;
|
||||
geometry.joints[ 0 ].distanceToParent = 0;
|
||||
geometry.joints[ 0 ].boneRadius = 0;
|
||||
geometry.joints[ 0 ].translation = glm::vec3(0, 0, 0);
|
||||
// geometry.joints[ 0 ].preTransform = ;
|
||||
geometry.joints[ 0 ].preRotation = glm::quat(0, 0, 0, 1);
|
||||
geometry.joints[ 0 ].rotation = glm::quat(0, 0, 0, 1);
|
||||
geometry.joints[ 0 ].postRotation = glm::quat(0, 0, 0, 1);
|
||||
// geometry.joints[ 0 ].postTransform = ;
|
||||
// geometry.joints[ 0 ].transform = ;
|
||||
geometry.joints[ 0 ].rotationMin = glm::vec3(0, 0, 0);
|
||||
geometry.joints[ 0 ].rotationMax = glm::vec3(0, 0, 0);
|
||||
geometry.joints[ 0 ].inverseDefaultRotation = glm::quat(0, 0, 0, 1);
|
||||
geometry.joints[ 0 ].inverseBindRotation = glm::quat(0, 0, 0, 1);
|
||||
// geometry.joints[ 0 ].bindTransform = ;
|
||||
geometry.joints[ 0 ].name = "OBJ";
|
||||
geometry.joints[ 0 ].shapePosition = glm::vec3(0, 0, 0);
|
||||
geometry.joints[ 0 ].shapeRotation = glm::quat(0, 0, 0, 1);
|
||||
geometry.joints[ 0 ].shapeType = SPHERE_SHAPE;
|
||||
geometry.joints[ 0 ].isSkeletonJoint = false;
|
||||
|
||||
indexStart += mesh.vertices.count();
|
||||
|
||||
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);
|
||||
|
@ -276,16 +184,76 @@ FBXGeometry readOBJ(const QByteArray& model, const QVariantHash& mapping) {
|
|||
FBXGeometry readOBJ(QIODevice* device, const QVariantHash& mapping) {
|
||||
FBXGeometry geometry;
|
||||
OBJTokenizer tokenizer(device);
|
||||
int indexStart = 0;
|
||||
|
||||
geometry.meshExtents.reset();
|
||||
geometry.meshes.append(FBXMesh());
|
||||
|
||||
while (true) {
|
||||
if (!parseOBJMesh(tokenizer, mapping, geometry, indexStart)) {
|
||||
break;
|
||||
try {
|
||||
while (parseOBJGroup(tokenizer, mapping, geometry)) {
|
||||
}
|
||||
|
||||
qDebug() << "indexStart is" << indexStart;
|
||||
FBXMesh &mesh = geometry.meshes[0];
|
||||
|
||||
mesh.meshExtents.reset();
|
||||
foreach (const glm::vec3& vertex, mesh.vertices) {
|
||||
mesh.meshExtents.addPoint(vertex);
|
||||
geometry.meshExtents.addPoint(vertex);
|
||||
}
|
||||
|
||||
geometry.joints.resize(1);
|
||||
geometry.joints[ 0 ].isFree = false;
|
||||
// geometry.joints[ 0 ].freeLineage;
|
||||
geometry.joints[ 0 ].parentIndex = -1;
|
||||
geometry.joints[ 0 ].distanceToParent = 0;
|
||||
geometry.joints[ 0 ].boneRadius = 0;
|
||||
geometry.joints[ 0 ].translation = glm::vec3(0, 0, 0);
|
||||
// geometry.joints[ 0 ].preTransform = ;
|
||||
geometry.joints[ 0 ].preRotation = glm::quat(0, 0, 0, 1);
|
||||
geometry.joints[ 0 ].rotation = glm::quat(0, 0, 0, 1);
|
||||
geometry.joints[ 0 ].postRotation = glm::quat(0, 0, 0, 1);
|
||||
// geometry.joints[ 0 ].postTransform = ;
|
||||
// geometry.joints[ 0 ].transform = ;
|
||||
geometry.joints[ 0 ].rotationMin = glm::vec3(0, 0, 0);
|
||||
geometry.joints[ 0 ].rotationMax = glm::vec3(0, 0, 0);
|
||||
geometry.joints[ 0 ].inverseDefaultRotation = glm::quat(0, 0, 0, 1);
|
||||
geometry.joints[ 0 ].inverseBindRotation = glm::quat(0, 0, 0, 1);
|
||||
// geometry.joints[ 0 ].bindTransform = ;
|
||||
geometry.joints[ 0 ].name = "OBJ";
|
||||
geometry.joints[ 0 ].shapePosition = glm::vec3(0, 0, 0);
|
||||
geometry.joints[ 0 ].shapeRotation = glm::quat(0, 0, 0, 1);
|
||||
geometry.joints[ 0 ].shapeType = SPHERE_SHAPE;
|
||||
geometry.joints[ 0 ].isSkeletonJoint = false;
|
||||
|
||||
// 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());
|
||||
|
||||
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);
|
||||
|
||||
mesh.normals[ p0Index ] = n;
|
||||
mesh.normals[ p1Index ] = n;
|
||||
mesh.normals[ p2Index ] = n;
|
||||
|
||||
mesh.tangents[ p0Index ] = t;
|
||||
mesh.tangents[ p1Index ] = t;
|
||||
mesh.tangents[ p2Index ] = t;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch(const std::exception& e) {
|
||||
qDebug() << "something went wrong in OBJ reader";
|
||||
}
|
||||
|
||||
return geometry;
|
||||
|
|
Loading…
Reference in a new issue