#include "vertexindexer_p.h" #include // for memcmp #include 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 &out_vertices , QVector &out_uvs , QVector &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 &VertexToOutIndex , unsigned short &result) { QMap::iterator it = VertexToOutIndex.find(packed); if (it == VertexToOutIndex.end()) { return false; } else { result = it.value(); return true; } } void VertexIndexer::indexVBO(QVector &in_vertices , QVector &in_uvs , QVector &in_normals , QVector &out_indices , QVector &out_vertices , QVector &out_uvs , QVector &out_normals) { unique_vertices = 0; QMap 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 &in_vertices , QVector &in_uvs , QVector &in_normals , QVector &in_tangents , QVector &in_bitangents , QVector &out_indices , QVector &out_vertices , QVector &out_uvs , QVector &out_normals , QVector &out_tangents , QVector &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