]> git.sur5r.net Git - fstl/commitdiff
Adding hash-based mesh loading (better big-O)
authorMatt Keeter <matt.j.keeter@gmail.com>
Sat, 22 Mar 2014 16:54:06 +0000 (12:54 -0400)
committerMatt Keeter <matt.j.keeter@gmail.com>
Sat, 22 Mar 2014 16:54:06 +0000 (12:54 -0400)
src/loader.cpp
src/mesh.cpp
src/mesh.h

index 4131d02ae9be18c427c24b3123f735371d0eca09..f0f42683bc51710e20edbdc0bde648445784bb4c 100644 (file)
@@ -8,6 +8,14 @@ Loader::Loader(QObject* parent, const QString& filename)
 
 void Loader::run()
 {
+    QTime timer;
+    timer.start();
     emit got_mesh(Mesh::load_stl(filename));
+    qDebug() << "Sorted:" << timer.elapsed();
+
+    timer.start();
+    emit got_mesh(Mesh::load_stl_hash(filename));
+    qDebug() << "Hash:" << timer.elapsed();
+
     emit loaded_file(filename);
 }
index 36ad10e0b884f9e8125f21c64063b8441cd698c8..6520741d50772d2c11cb86f1d1b97795bd9e63f5 100644 (file)
@@ -56,6 +56,59 @@ typedef std::pair<Vec3, GLuint> Vec3i;
 
 ////////////////////////////////////////////////////////////////////////////////
 
+Mesh* Mesh::load_stl_hash(const QString& filename)
+{
+    QFile file(filename);
+    file.open(QIODevice::ReadOnly);
+
+    QDataStream data(&file);
+    data.setByteOrder(QDataStream::LittleEndian);
+    data.setFloatingPointPrecision(QDataStream::SinglePrecision);
+
+    // Skip .stl file header
+    data.skipRawData(80);
+
+    // Load the triangle count from the .stl file
+    uint32_t tri_count;
+    data >> tri_count;
+
+    // This vector will store triangles as sets of 3 indices
+    std::vector<GLuint> indices(tri_count * 3);
+
+    std::vector<GLfloat> verts;
+    verts.reserve(tri_count * 9);
+
+    QHash<QByteArray, GLuint> map;
+    map.reserve(tri_count * 3);
+
+    float xyz[3];
+    QByteArray v(sizeof(xyz), 0);
+    for (unsigned i=0; i < tri_count; ++i)
+    {
+        // Skip face's normal vector
+        data.skipRawData(3*sizeof(float));
+
+        for (int j=0; j < 3; ++j)
+        {
+            data >> xyz[0] >> xyz[1] >> xyz[2];
+            memcpy(v.data(), xyz, sizeof(xyz));
+            if (!map.contains(v))
+            {
+                map[v] = verts.size() / 3;
+                verts.push_back(xyz[0]);
+                verts.push_back(xyz[1]);
+                verts.push_back(xyz[2]);
+            }
+            indices[i*3 + j] = map[v];
+        }
+
+        // Skip face attribute
+        data.skipRawData(sizeof(uint16_t));
+    }
+
+    return new Mesh(verts, indices);
+}
+
 Mesh* Mesh::load_stl(const QString& filename)
 {
     QFile file(filename);
index f83a47708249bc007fd40e73ec6edc4b4d6b172d..80f2a1ef52f3b0a282f591cb866d34428d2c1677 100644 (file)
@@ -11,6 +11,7 @@ class Mesh
 public:
     Mesh(std::vector<GLfloat> vertices, std::vector<GLuint> indices);
     static Mesh* load_stl(const QString& filename);
+    static Mesh* load_stl_hash(const QString& filename);
 
     float min(size_t start) const;
     float max(size_t start) const;