3 Loader::Loader(QObject* parent, const QString& filename)
4 : QThread(parent), filename(filename)
11 Mesh* mesh = load_stl();
15 emit loaded_file(filename);
20 ////////////////////////////////////////////////////////////////////////////////
25 bool operator!=(const Vec3& rhs) const
27 return x != rhs.x || y != rhs.y || z != rhs.z;
29 bool operator<(const Vec3& rhs) const
31 if (x != rhs.x) return x < rhs.x;
32 else if (y != rhs.y) return y < rhs.y;
33 else if (z != rhs.z) return z < rhs.z;
38 typedef std::pair<Vec3, GLuint> Vec3i;
40 ////////////////////////////////////////////////////////////////////////////////
42 Mesh* Loader::load_stl()
45 file.open(QIODevice::ReadOnly);
46 if (file.read(5) == "solid")
48 emit error_ascii_stl();
51 // Skip the rest of the header material
54 QDataStream data(&file);
55 data.setByteOrder(QDataStream::LittleEndian);
56 data.setFloatingPointPrecision(QDataStream::SinglePrecision);
58 // Load the triangle count from the .stl file
62 // Verify that the file is the right size
63 if (file.size() != 84 + tri_count*50)
69 // Extract vertices into an array of xyz, unsigned pairs
70 QVector<Vec3i> verts(tri_count*3);
72 // Dummy array, because readRawData is faster than skipRawData
73 char buffer[sizeof(float)*3];
75 // Store vertices in the array, processing one triangle at a time.
76 for (auto v=verts.begin(); v != verts.end(); v += 3)
78 // Skip face's normal vector
79 data.readRawData(buffer, 3*sizeof(float));
81 // Load vertex data from .stl file into vertices
82 data >> v[0].first.x >> v[0].first.y >> v[0].first.z;
83 data >> v[1].first.x >> v[1].first.y >> v[1].first.z;
84 data >> v[2].first.x >> v[2].first.y >> v[2].first.z;
86 // Skip face attribute
87 data.readRawData(buffer, sizeof(uint16_t));
90 // Save indicies as the second element in the array
91 // (so that we can reconstruct triangle order after sorting)
92 for (size_t i=0; i < tri_count*3; ++i)
97 // Sort the set of vertices (to deduplicate)
98 std::sort(verts.begin(), verts.end());
100 // This vector will store triangles as sets of 3 indices
101 std::vector<GLuint> indices(tri_count*3);
103 // Go through the sorted vertex list, deduplicating and creating
104 // an indexed geometry representation for the triangles.
105 // Unique vertices are moved so that they occupy the first vertex_count
106 // positions in the verts array.
107 size_t vertex_count = 0;
110 if (!vertex_count || v.first != verts[vertex_count-1].first)
112 verts[vertex_count++] = v;
114 indices[v.second] = vertex_count - 1;
116 verts.resize(vertex_count);
118 std::vector<GLfloat> flat_verts;
119 flat_verts.reserve(vertex_count*3);
122 flat_verts.push_back(v.first.x);
123 flat_verts.push_back(v.first.y);
124 flat_verts.push_back(v.first.z);
127 return new Mesh(flat_verts, indices);