summaryrefslogtreecommitdiffstats
path: root/src/datavis3d/utils/vertexindexer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/datavis3d/utils/vertexindexer.cpp')
-rw-r--r--src/datavis3d/utils/vertexindexer.cpp137
1 files changed, 137 insertions, 0 deletions
diff --git a/src/datavis3d/utils/vertexindexer.cpp b/src/datavis3d/utils/vertexindexer.cpp
new file mode 100644
index 00000000..c54cbf8a
--- /dev/null
+++ b/src/datavis3d/utils/vertexindexer.cpp
@@ -0,0 +1,137 @@
+#include "vertexindexer_p.h"
+
+#include <string.h> // for memcmp
+
+#include <QDebug>
+
+QTCOMMERCIALDATAVIS3D_BEGIN_NAMESPACE
+
+int unique_vertices = 0;
+
+// Returns true if v1 can be considered equal to v2
+bool VertexIndexer::is_near(float v1, float v2)
+{
+ return fabs(v1 - v2) < 0.01f;
+}
+
+// Searches through all already-exported vertices
+// for a similar one.
+// Similar = same position + same UVs + same normal
+bool VertexIndexer::getSimilarVertexIndex(QVector3D &in_vertex
+ , QVector2D &in_uv
+ , QVector3D &in_normal
+ , QVector<QVector3D> &out_vertices
+ , QVector<QVector2D> &out_uvs
+ , QVector<QVector3D> &out_normals
+ , unsigned short &result)
+{
+ // Lame linear search
+ for (int i = 0; i < out_vertices.size(); i++) {
+ if (is_near(in_vertex.x() , out_vertices[i].x())
+ && is_near(in_vertex.y() , out_vertices[i].y())
+ && is_near(in_vertex.z() , out_vertices[i].z())
+ && is_near(in_uv.x() , out_uvs [i].x())
+ && is_near(in_uv.y() , out_uvs [i].y())
+ && is_near(in_normal.x() , out_normals [i].x())
+ && is_near(in_normal.y() , out_normals [i].y())
+ && is_near(in_normal.z() , out_normals [i].z())) {
+ result = i;
+ return true;
+ }
+ }
+ // No other vertex could be used instead.
+ // Looks like we'll have to add it to the VBO.
+ return false;
+}
+
+bool VertexIndexer::getSimilarVertexIndex_fast(PackedVertex &packed
+ , QMap<PackedVertex, unsigned short> &VertexToOutIndex
+ , unsigned short &result)
+{
+ QMap<PackedVertex, unsigned short>::iterator it = VertexToOutIndex.find(packed);
+ if (it == VertexToOutIndex.end()) {
+ return false;
+ }
+ else {
+ result = it.value();
+ return true;
+ }
+}
+
+void VertexIndexer::indexVBO(QVector<QVector3D> &in_vertices
+ , QVector<QVector2D> &in_uvs
+ , QVector<QVector3D> &in_normals
+ , QVector<unsigned short> &out_indices
+ , QVector<QVector3D> &out_vertices
+ , QVector<QVector2D> &out_uvs
+ , QVector<QVector3D> &out_normals)
+{
+ unique_vertices = 0;
+ QMap<PackedVertex, unsigned short> VertexToOutIndex;
+
+ // For each input vertex
+ for (int i = 0; i < in_vertices.size(); i++) {
+ PackedVertex packed = {in_vertices[i], in_uvs[i], in_normals[i]};
+
+ // Try to find a similar vertex in out_XXXX
+ unsigned short index;
+ bool found = getSimilarVertexIndex_fast(packed, VertexToOutIndex, index);
+
+ if (found) { // A similar vertex is already in the VBO, use it instead !
+ out_indices.append(index);
+ }
+ else { // If not, it needs to be added in the output data.
+ unique_vertices++;
+ out_vertices.append(in_vertices[i]);
+ out_uvs.append(in_uvs[i]);
+ out_normals.append(in_normals[i]);
+ unsigned short newindex = (unsigned short)out_vertices.size() - 1;
+ out_indices.append(newindex);
+ VertexToOutIndex[packed] = newindex;
+ }
+ }
+ qDebug() << "unique vertices" << unique_vertices;
+}
+
+void VertexIndexer::indexVBO_TBN(QVector<QVector3D> &in_vertices
+ , QVector<QVector2D> &in_uvs
+ , QVector<QVector3D> &in_normals
+ , QVector<QVector3D> &in_tangents
+ , QVector<QVector3D> &in_bitangents
+ , QVector<unsigned short> &out_indices
+ , QVector<QVector3D> &out_vertices
+ , QVector<QVector2D> &out_uvs
+ , QVector<QVector3D> &out_normals
+ , QVector<QVector3D> &out_tangents
+ , QVector<QVector3D> &out_bitangents)
+{
+ unique_vertices = 0;
+ // For each input vertex
+ for (int i = 0; i < in_vertices.size(); i++) {
+
+ // Try to find a similar vertex in out_XXXX
+ unsigned short index;
+ bool found = getSimilarVertexIndex(in_vertices[i], in_uvs[i], in_normals[i]
+ , out_vertices, out_uvs, out_normals, index);
+
+ if (found) { // A similar vertex is already in the VBO, use it instead !
+ out_indices.append(index);
+
+ // Average the tangents and the bitangents
+ out_tangents[index] += in_tangents[i];
+ out_bitangents[index] += in_bitangents[i];
+ }
+ else { // If not, it needs to be added in the output data.
+ unique_vertices++;
+ out_vertices.append(in_vertices[i]);
+ out_uvs.append(in_uvs[i]);
+ out_normals.append(in_normals[i]);
+ out_tangents.append(in_tangents[i]);
+ out_bitangents.append(in_bitangents[i]);
+ out_indices.append((unsigned short)out_vertices.size() - 1);
+ }
+ }
+ qDebug() << "unique vertices" << unique_vertices;
+}
+
+QTCOMMERCIALDATAVIS3D_END_NAMESPACE