#include #include #include #include #include "model_mesh.h" #include "version.h" float ModelMesh::m_defaultMetalness = 0.0; float ModelMesh::m_defaultRoughness = 1.0; ModelMesh::ModelMesh(const ModelMesh &mesh) : m_triangleVertices(nullptr), m_triangleVertexCount(0), m_textureImage(nullptr) { if (nullptr != mesh.m_triangleVertices && mesh.m_triangleVertexCount > 0) { this->m_triangleVertices = new ModelOpenGLVertex[mesh.m_triangleVertexCount]; this->m_triangleVertexCount = mesh.m_triangleVertexCount; for (int i = 0; i < mesh.m_triangleVertexCount; i++) this->m_triangleVertices[i] = mesh.m_triangleVertices[i]; } if (nullptr != mesh.m_textureImage) { this->m_textureImage = new QImage(*mesh.m_textureImage); } if (nullptr != mesh.m_normalMapImage) { this->m_normalMapImage = new QImage(*mesh.m_normalMapImage); } if (nullptr != mesh.m_metalnessRoughnessAmbientOcclusionImage) { this->m_metalnessRoughnessAmbientOcclusionImage = new QImage(*mesh.m_metalnessRoughnessAmbientOcclusionImage); this->m_hasMetalnessInImage = mesh.m_hasMetalnessInImage; this->m_hasRoughnessInImage = mesh.m_hasRoughnessInImage; this->m_hasAmbientOcclusionInImage = mesh.m_hasAmbientOcclusionInImage; } this->m_vertices = mesh.m_vertices; this->m_faces = mesh.m_faces; this->m_triangulatedVertices = mesh.m_triangulatedVertices; this->m_meshId = mesh.meshId(); } void ModelMesh::removeColor() { delete this->m_textureImage; this->m_textureImage = nullptr; delete this->m_normalMapImage; this->m_normalMapImage = nullptr; delete this->m_metalnessRoughnessAmbientOcclusionImage; this->m_metalnessRoughnessAmbientOcclusionImage = nullptr; this->m_hasMetalnessInImage = false; this->m_hasRoughnessInImage = false; this->m_hasAmbientOcclusionInImage = false; for (int i = 0; i < this->m_triangleVertexCount; ++i) { auto &vertex = this->m_triangleVertices[i]; vertex.colorR = 1.0; vertex.colorG = 1.0; vertex.colorB = 1.0; } } ModelMesh::ModelMesh(ModelOpenGLVertex *triangleVertices, int vertexNum) : m_triangleVertices(triangleVertices), m_triangleVertexCount(vertexNum), m_textureImage(nullptr) { } ModelMesh::ModelMesh(const std::vector &vertices, const std::vector> &triangles, const std::vector> &triangleVertexNormals, const dust3d::Color &color, float metalness, float roughness) { m_triangleVertexCount = (int)triangles.size() * 3; m_triangleVertices = new ModelOpenGLVertex[m_triangleVertexCount]; int destIndex = 0; for (size_t i = 0; i < triangles.size(); ++i) { for (auto j = 0; j < 3; j++) { int vertexIndex = (int)triangles[i][j]; const dust3d::Vector3 *srcVert = &vertices[vertexIndex]; const dust3d::Vector3 *srcNormal = &(triangleVertexNormals)[i][j]; ModelOpenGLVertex *dest = &m_triangleVertices[destIndex]; dest->colorR = color.r(); dest->colorG = color.g(); dest->colorB = color.b(); dest->alpha = color.alpha(); dest->posX = srcVert->x(); dest->posY = srcVert->y(); dest->posZ = srcVert->z(); dest->texU = 0; dest->texV = 0; dest->normX = srcNormal->x(); dest->normY = srcNormal->y(); dest->normZ = srcNormal->z(); dest->metalness = metalness; dest->roughness = roughness; dest->tangentX = 0; dest->tangentY = 0; dest->tangentZ = 0; destIndex++; } } } ModelMesh::ModelMesh(dust3d::Object &object) : m_triangleVertices(nullptr), m_triangleVertexCount(0), m_textureImage(nullptr) { m_meshId = object.meshId; m_vertices = object.vertices; m_faces = object.triangleAndQuads; std::map, const dust3d::ObjectNode *> nodeMap; for (size_t i = 0; i < object.nodes.size(); ++i) { const auto &node = object.nodes[i]; nodeMap.insert({{node.partId, node.nodeId}, &node}); } m_triangleVertexCount = (int)object.triangles.size() * 3; m_triangleVertices = new ModelOpenGLVertex[m_triangleVertexCount]; int destIndex = 0; const auto triangleVertexNormals = object.triangleVertexNormals(); const auto triangleVertexUvs = object.triangleVertexUvs(); const auto triangleTangents = object.triangleTangents(); const dust3d::Vector3 defaultNormal = dust3d::Vector3(0, 0, 0); const dust3d::Vector2 defaultUv = dust3d::Vector2(0, 0); const dust3d::Vector3 defaultTangent = dust3d::Vector3(0, 0, 0); for (size_t i = 0; i < object.triangles.size(); ++i) { const auto &triangleColor = &object.triangleColors[i]; for (auto j = 0; j < 3; j++) { int vertexIndex = (int)object.triangles[i][j]; const dust3d::Vector3 *srcVert = &object.vertices[vertexIndex]; const dust3d::Vector3 *srcNormal = &defaultNormal; if (triangleVertexNormals) srcNormal = &(*triangleVertexNormals)[i][j]; const dust3d::Vector2 *srcUv = &defaultUv; if (triangleVertexUvs) srcUv = &(*triangleVertexUvs)[i][j]; const dust3d::Vector3 *srcTangent = &defaultTangent; if (triangleTangents) srcTangent = &(*triangleTangents)[i]; ModelOpenGLVertex *dest = &m_triangleVertices[destIndex]; dest->colorR = triangleColor->r(); dest->colorG = triangleColor->g(); dest->colorB = triangleColor->b(); dest->alpha = triangleColor->alpha(); dest->posX = srcVert->x(); dest->posY = srcVert->y(); dest->posZ = srcVert->z(); dest->texU = srcUv->x(); dest->texV = srcUv->y(); dest->normX = srcNormal->x(); dest->normY = srcNormal->y(); dest->normZ = srcNormal->z(); auto findNode = nodeMap.find(object.vertexSourceNodes[vertexIndex]); if (findNode != nodeMap.end()) { dest->metalness = findNode->second->metalness; dest->roughness = findNode->second->roughness; } else { dest->metalness = m_defaultMetalness; dest->roughness = m_defaultRoughness; } dest->tangentX = srcTangent->x(); dest->tangentY = srcTangent->y(); dest->tangentZ = srcTangent->z(); destIndex++; } } } ModelMesh::ModelMesh() : m_triangleVertices(nullptr), m_triangleVertexCount(0), m_textureImage(nullptr) { } ModelMesh::~ModelMesh() { delete[] m_triangleVertices; m_triangleVertexCount = 0; delete m_textureImage; delete m_normalMapImage; delete m_metalnessRoughnessAmbientOcclusionImage; } const std::vector &ModelMesh::vertices() { return m_vertices; } const std::vector> &ModelMesh::faces() { return m_faces; } const std::vector &ModelMesh::triangulatedVertices() { return m_triangulatedVertices; } ModelOpenGLVertex *ModelMesh::triangleVertices() { return m_triangleVertices; } int ModelMesh::triangleVertexCount() { return m_triangleVertexCount; } void ModelMesh::setTextureImage(QImage *textureImage) { m_textureImage = textureImage; } const QImage *ModelMesh::textureImage() { return m_textureImage; } void ModelMesh::setNormalMapImage(QImage *normalMapImage) { m_normalMapImage = normalMapImage; } const QImage *ModelMesh::normalMapImage() { return m_normalMapImage; } const QImage *ModelMesh::metalnessRoughnessAmbientOcclusionImage() { return m_metalnessRoughnessAmbientOcclusionImage; } void ModelMesh::setMetalnessRoughnessAmbientOcclusionImage(QImage *image) { m_metalnessRoughnessAmbientOcclusionImage = image; } bool ModelMesh::hasMetalnessInImage() { return m_hasMetalnessInImage; } void ModelMesh::setHasMetalnessInImage(bool hasInImage) { m_hasMetalnessInImage = hasInImage; } bool ModelMesh::hasRoughnessInImage() { return m_hasRoughnessInImage; } void ModelMesh::setHasRoughnessInImage(bool hasInImage) { m_hasRoughnessInImage = hasInImage; } bool ModelMesh::hasAmbientOcclusionInImage() { return m_hasAmbientOcclusionInImage; } void ModelMesh::setHasAmbientOcclusionInImage(bool hasInImage) { m_hasAmbientOcclusionInImage = hasInImage; } void ModelMesh::exportAsObj(QTextStream *textStream) { auto &stream = *textStream; stream << "# " << APP_NAME << " " << APP_HUMAN_VER << endl; stream << "# " << APP_HOMEPAGE_URL << endl; for (std::vector::const_iterator it = vertices().begin() ; it != vertices().end(); ++it) { stream << "v " << QString::number((*it).x()) << " " << QString::number((*it).y()) << " " << QString::number((*it).z()) << endl; } for (std::vector>::const_iterator it = faces().begin() ; it != faces().end(); ++it) { stream << "f"; for (std::vector::const_iterator subIt = (*it).begin() ; subIt != (*it).end(); ++subIt) { stream << " " << QString::number((1 + *subIt)); } stream << endl; } } void ModelMesh::exportAsObj(const QString &filename) { QFile file(filename); if (file.open(QIODevice::WriteOnly)) { QTextStream stream(&file); exportAsObj(&stream); } } void ModelMesh::updateTriangleVertices(ModelOpenGLVertex *triangleVertices, int triangleVertexCount) { delete[] m_triangleVertices; m_triangleVertices = 0; m_triangleVertexCount = 0; m_triangleVertices = triangleVertices; m_triangleVertexCount = triangleVertexCount; } quint64 ModelMesh::meshId() const { return m_meshId; } void ModelMesh::setMeshId(quint64 id) { m_meshId = id; }