diff --git a/QtMeshViewer/Header/FileInterface.h b/QtMeshViewer/Header/FileInterface.h index 26fee9c..37f5940 100644 --- a/QtMeshViewer/Header/FileInterface.h +++ b/QtMeshViewer/Header/FileInterface.h @@ -18,6 +18,9 @@ struct VertexData QVector3D position; QVector2D texCoord; QVector3D vertexNormal; + QVector3D polygonNormal; + QVector3D tangent; + QVector3D bitangent; }; struct Segment { diff --git a/QtMeshViewer/Source/MshFile.cpp b/QtMeshViewer/Source/MshFile.cpp index c3f52aa..96676f3 100644 --- a/QtMeshViewer/Source/MshFile.cpp +++ b/QtMeshViewer/Source/MshFile.cpp @@ -572,18 +572,106 @@ void MshFile::analyseSegmChunks(Model * dataDestination, QList& ch if (tmp_buffer.size() == 5) { - for (size_t i = 0; i < 3; i++) - new_segment->indices.push_back(tmp_buffer.takeFirst()); + // calculate poylgon normal, tangent and bitangent + QVector3D vec1, vec2, norm, tan, bi; + QVector2D uv1, uv2; + float f; + + vec1 = new_segment->vertices[tmp_buffer[0]].position - new_segment->vertices[tmp_buffer[1]].position; + vec2 = new_segment->vertices[tmp_buffer[0]].position - new_segment->vertices[tmp_buffer[2]].position; + uv1 = new_segment->vertices[tmp_buffer[0]].texCoord - new_segment->vertices[tmp_buffer[1]].texCoord; + uv2 = new_segment->vertices[tmp_buffer[0]].texCoord - new_segment->vertices[tmp_buffer[2]].texCoord; + f = 1.0f / (uv1.x() * uv2.y() - uv2.x() * uv1.y()); + + norm = QVector3D::crossProduct(vec1, vec2).normalized(); + + tan.setX(f * (uv2.y() * vec1.x() - uv1.y() * vec2.x())); + tan.setY(f * (uv2.y() * vec1.y() - uv1.y() * vec2.y())); + tan.setZ(f * (uv2.y() * vec1.z() - uv1.y() * vec2.z())); + tan.normalize(); + + bi.setX(f * (-uv2.x() * vec1.x() + uv1.x() * vec2.x())); + bi.setY(f * (-uv2.x() * vec1.y() + uv1.x() * vec2.y())); + bi.setZ(f * (-uv2.x() * vec1.z() + uv1.x() * vec2.z())); + bi.normalize(); + + for (int k = 0; k < 3; k++) + { + // polygon normal wasn't calculated before + if (new_segment->vertices[tmp_buffer[k]].polygonNormal == QVector3D(0, 0, 0)) + { + new_segment->vertices[tmp_buffer[k]].polygonNormal = norm; + new_segment->vertices[tmp_buffer[k]].tangent = tan; + new_segment->vertices[tmp_buffer[k]].bitangent = bi; + + new_segment->indices.push_back(tmp_buffer[k]); + } + // polygon normal already calculated so duplicate the vertex + else + { + new_segment->vertices.push_back(new_segment->vertices[tmp_buffer[k]]); + new_segment->vertices.back().polygonNormal = norm; + new_segment->vertices.back().tangent = tan; + new_segment->vertices.back().bitangent = bi; + new_segment->indices.push_back(new_segment->vertices.size() - 1); + } + } + tmp_buffer.remove(0, 3); } else if (tmp_buffer.size() > 5) { unsigned int tmp_multiPolySize = tmp_buffer.size() - 2; + + // calculate poylgon normal, tangent and bitangent + QVector3D vec1, vec2, norm, tan, bi; + QVector2D uv1, uv2; + float f; + + vec1 = new_segment->vertices[tmp_buffer[0]].position - new_segment->vertices[tmp_buffer[1]].position; + vec2 = new_segment->vertices[tmp_buffer[0]].position - new_segment->vertices[tmp_buffer[2]].position; + uv1 = new_segment->vertices[tmp_buffer[0]].texCoord - new_segment->vertices[tmp_buffer[1]].texCoord; + uv2 = new_segment->vertices[tmp_buffer[0]].texCoord - new_segment->vertices[tmp_buffer[2]].texCoord; + f = 1.0f / (uv1.x() * uv2.y() - uv2.x() * uv1.y()); + + norm = QVector3D::crossProduct(vec1, vec2).normalized(); + + tan.setX(f * (uv2.y() * vec1.x() - uv1.y() * vec2.x())); + tan.setY(f * (uv2.y() * vec1.y() - uv1.y() * vec2.y())); + tan.setZ(f * (uv2.y() * vec1.z() - uv1.y() * vec2.z())); + tan.normalize(); + + bi.setX(f * (-uv2.x() * vec1.x() + uv1.x() * vec2.x())); + bi.setY(f * (-uv2.x() * vec1.y() + uv1.x() * vec2.y())); + bi.setZ(f * (-uv2.x() * vec1.z() + uv1.x() * vec2.z())); + bi.normalize(); + // for every triangle of the multi polygon.. for (unsigned int tri = 0; tri < tmp_multiPolySize - 2; tri++) + { // ..calculate the edge indices for (int triEdge = 0; triEdge < 3; triEdge++) - new_segment->indices.push_back(tmp_buffer[(tri + triEdge - ((tri % 2) * (triEdge - 1) * 2))]); + { + int curIndi = tmp_buffer[(tri + triEdge - ((tri % 2) * (triEdge - 1) * 2))]; + // polygon normal wasn't calculated before + if (new_segment->vertices[curIndi].polygonNormal == QVector3D(0, 0, 0)) + { + new_segment->vertices[curIndi].polygonNormal = norm; + new_segment->vertices[curIndi].tangent = tan; + new_segment->vertices[curIndi].bitangent = bi; + new_segment->indices.push_back(curIndi); + } + // polygon normal already calculated so duplicate the vertex + else + { + new_segment->vertices.push_back(new_segment->vertices[curIndi]); + new_segment->vertices.back().polygonNormal = norm; + new_segment->vertices.back().tangent = tan; + new_segment->vertices.back().bitangent = bi; + new_segment->indices.push_back(new_segment->vertices.size() - 1); + } + } + } tmp_buffer.remove(0, tmp_multiPolySize); } @@ -594,17 +682,107 @@ void MshFile::analyseSegmChunks(Model * dataDestination, QList& ch // save the last polygon (no 2 high bit followed) if (tmp_buffer.size() == 3) { - for (size_t i = 0; i < 3; i++) - new_segment->indices.push_back(tmp_buffer.takeFirst()); + // calculate poylgon normal, tangent and bitangent + QVector3D vec1, vec2, norm, tan, bi; + QVector2D uv1, uv2; + float f; + + vec1 = new_segment->vertices[tmp_buffer[0]].position - new_segment->vertices[tmp_buffer[1]].position; + vec2 = new_segment->vertices[tmp_buffer[0]].position - new_segment->vertices[tmp_buffer[2]].position; + uv1 = new_segment->vertices[tmp_buffer[0]].texCoord - new_segment->vertices[tmp_buffer[1]].texCoord; + uv2 = new_segment->vertices[tmp_buffer[0]].texCoord - new_segment->vertices[tmp_buffer[2]].texCoord; + f = 1.0f / (uv1.x() * uv2.y() - uv2.x() * uv1.y()); + + norm = QVector3D::crossProduct(vec1, vec2).normalized(); + + tan.setX(f * (uv2.y() * vec1.x() - uv1.y() * vec2.x())); + tan.setY(f * (uv2.y() * vec1.y() - uv1.y() * vec2.y())); + tan.setZ(f * (uv2.y() * vec1.z() - uv1.y() * vec2.z())); + tan.normalize(); + + bi.setX(f * (-uv2.x() * vec1.x() + uv1.x() * vec2.x())); + bi.setY(f * (-uv2.x() * vec1.y() + uv1.x() * vec2.y())); + bi.setZ(f * (-uv2.x() * vec1.z() + uv1.x() * vec2.z())); + bi.normalize(); + + for (int k = 0; k < 3; k++) + { + //TODO: buffer size == 1; k = 2; + // polygon normal wasn't calculated before + if (new_segment->vertices[tmp_buffer[k]].polygonNormal == QVector3D(0, 0, 0)) + { + new_segment->vertices[tmp_buffer[k]].polygonNormal = norm; + new_segment->vertices[tmp_buffer[k]].tangent = tan; + new_segment->vertices[tmp_buffer[k]].bitangent = bi; + + new_segment->indices.push_back(tmp_buffer[k]); + } + // polygon normal already calculated so duplicate the vertex + else + { + new_segment->vertices.push_back(new_segment->vertices[tmp_buffer[k]]); + new_segment->vertices.back().polygonNormal = norm; + new_segment->vertices.back().tangent = tan; + new_segment->vertices.back().bitangent = bi; + new_segment->indices.push_back(new_segment->vertices.size() - 1); + } + } + tmp_buffer.remove(0, 3); } else if (tmp_buffer.size() > 3) { unsigned int tmp_multiPolySize = tmp_buffer.size(); + + // calculate poylgon normal, tangent and bitangent + QVector3D vec1, vec2, norm, tan, bi; + QVector2D uv1, uv2; + float f; + + vec1 = new_segment->vertices[tmp_buffer[0]].position - new_segment->vertices[tmp_buffer[1]].position; + vec2 = new_segment->vertices[tmp_buffer[0]].position - new_segment->vertices[tmp_buffer[2]].position; + uv1 = new_segment->vertices[tmp_buffer[0]].texCoord - new_segment->vertices[tmp_buffer[1]].texCoord; + uv2 = new_segment->vertices[tmp_buffer[0]].texCoord - new_segment->vertices[tmp_buffer[2]].texCoord; + f = 1.0f / (uv1.x() * uv2.y() - uv2.x() * uv1.y()); + + norm = QVector3D::crossProduct(vec1, vec2).normalized(); + + tan.setX(f * (uv2.y() * vec1.x() - uv1.y() * vec2.x())); + tan.setY(f * (uv2.y() * vec1.y() - uv1.y() * vec2.y())); + tan.setZ(f * (uv2.y() * vec1.z() - uv1.y() * vec2.z())); + tan.normalize(); + + bi.setX(f * (-uv2.x() * vec1.x() + uv1.x() * vec2.x())); + bi.setY(f * (-uv2.x() * vec1.y() + uv1.x() * vec2.y())); + bi.setZ(f * (-uv2.x() * vec1.z() + uv1.x() * vec2.z())); + bi.normalize(); + // for every triangle of the multi polygon.. for (unsigned int tri = 0; tri < tmp_multiPolySize - 2; tri++) + { // ..calculate the edge indices for (int triEdge = 0; triEdge < 3; triEdge++) - new_segment->indices.push_back(tmp_buffer[(tri + triEdge - ((tri % 2) * (triEdge - 1) * 2))]); + { + int curIndi = tmp_buffer[(tri + triEdge - ((tri % 2) * (triEdge - 1) * 2))]; + + // polygon normal wasn't calculated before + if (new_segment->vertices[curIndi].polygonNormal == QVector3D(0, 0, 0)) + { + new_segment->vertices[curIndi].polygonNormal = norm; + new_segment->vertices[curIndi].tangent = tan; + new_segment->vertices[curIndi].bitangent = bi; + new_segment->indices.push_back(curIndi); + } + // polygon normal already calculated so duplicate the vertex + else + { + new_segment->vertices.push_back(new_segment->vertices[curIndi]); + new_segment->vertices.back().polygonNormal = norm; + new_segment->vertices.back().tangent = tan; + new_segment->vertices.back().bitangent = bi; + new_segment->indices.push_back(new_segment->vertices.size() - 1); + } + } + } } } }