diff --git a/src/graphics/engine/engine.cpp b/src/graphics/engine/engine.cpp index b21ff56a..4420ea81 100644 --- a/src/graphics/engine/engine.cpp +++ b/src/graphics/engine/engine.cpp @@ -4726,7 +4726,13 @@ int CEngine::AddStaticMesh(const std::string& key, const CModelMesh* mesh, const if (it == m_staticMeshBaseObjects.end()) { baseObjRank = CreateBaseObject(); - AddBaseObjTriangles(baseObjRank, mesh->GetTriangles()); + + for (size_t i = 0; i < mesh->GetPartCount(); i++) + { + const auto& part = mesh->GetPart(i); + + AddBaseObjTriangles(baseObjRank, part.GetVertices(), part.GetMaterial(), EngineTriangleType::TRIANGLES); + } m_staticMeshBaseObjects[key] = baseObjRank; } else diff --git a/src/graphics/model/model.cpp b/src/graphics/model/model.cpp index 48a6b8f5..89a4813f 100644 --- a/src/graphics/model/model.cpp +++ b/src/graphics/model/model.cpp @@ -79,7 +79,7 @@ void CModel::SetShadowSpot(const ModelShadowSpot& shadowSpot) bool CModel::HasShadowSpot() const { - return m_shadowSpot.is_initialized(); + return m_shadowSpot.has_value(); } const std::vector& CModel::GetCrashSpheres() const @@ -109,7 +109,7 @@ void CModel::SetCameraCollisionSphere(const Math::Sphere& sphere) bool CModel::HasCameraCollisionSphere() const { - return m_cameraCollisionSphere.is_initialized(); + return m_cameraCollisionSphere.has_value(); } } // namespace Gfx diff --git a/src/graphics/model/model.h b/src/graphics/model/model.h index f855741c..990f16ed 100644 --- a/src/graphics/model/model.h +++ b/src/graphics/model/model.h @@ -28,7 +28,7 @@ #include #include #include -#include +#include namespace Gfx { @@ -75,8 +75,8 @@ public: private: std::map m_meshes; std::vector m_crashSpheres; - boost::optional m_shadowSpot; - boost::optional m_cameraCollisionSphere; + std::optional m_shadowSpot; + std::optional m_cameraCollisionSphere; }; } // namespace Gfx diff --git a/src/graphics/model/model_input.cpp b/src/graphics/model/model_input.cpp index a49324cf..c7bcbddb 100644 --- a/src/graphics/model/model_input.cpp +++ b/src/graphics/model/model_input.cpp @@ -451,7 +451,9 @@ void ModelInput::ReadOldModel(CModel &model, std::istream &stream) } CModelMesh mesh; - mesh.SetTriangles(std::move(triangles)); + + for (const auto& triangle : triangles) + mesh.AddTriangle(triangle); model.AddMesh("main", std::move(mesh)); } diff --git a/src/graphics/model/model_mesh.cpp b/src/graphics/model/model_mesh.cpp index ee6c5302..cb80021c 100644 --- a/src/graphics/model/model_mesh.cpp +++ b/src/graphics/model/model_mesh.cpp @@ -22,24 +22,101 @@ namespace Gfx { +CModelPart::CModelPart(const Material& material) + : m_material(material) {} + +const Material& CModelPart::GetMaterial() const +{ + return m_material; +} + +bool CModelPart::IsIndexed() const +{ + return !m_indices.empty(); +} + +size_t CModelPart::GetVertexCount() const +{ + return m_vertices.size(); +} + +const std::vector& CModelPart::GetVertices() const +{ + return m_vertices; +} + +size_t CModelPart::GetIndexCount() const +{ + return m_indices.size(); +} + +const std::vector& CModelPart::GetIndices() const +{ + return m_indices; +} + +void CModelPart::AddVertex(const Vertex3D& vertex) +{ + m_vertices.push_back(vertex); +} + +void CModelPart::AddIndex(unsigned int index) +{ + m_indices.push_back(index); +} + void CModelMesh::AddTriangle(const ModelTriangle& triangle) { - m_triangles.push_back(triangle); + for (auto& part : m_parts) + { + if (part.GetMaterial() == triangle.material) + { + part.AddVertex(triangle.p1); + part.AddVertex(triangle.p2); + part.AddVertex(triangle.p3); + return; + } + } + + CModelPart part(triangle.material); + + part.AddVertex(triangle.p1); + part.AddVertex(triangle.p2); + part.AddVertex(triangle.p3); + + m_parts.emplace_back(part); } -void CModelMesh::SetTriangles(std::vector&& triangles) +void CModelMesh::AddTriangle(const Triangle& triangle, const Material& material) { - m_triangles = triangles; + for (auto& part : m_parts) + { + if (part.GetMaterial() == material) + { + part.AddVertex(triangle.p1); + part.AddVertex(triangle.p2); + part.AddVertex(triangle.p3); + return; + } + } + + CModelPart part(material); + + part.AddVertex(triangle.p1); + part.AddVertex(triangle.p2); + part.AddVertex(triangle.p3); + + m_parts.emplace_back(part); } -const std::vector& CModelMesh::GetTriangles() const +size_t CModelMesh::GetPartCount() const { - return m_triangles; + return m_parts.size(); } -int CModelMesh::GetTriangleCount() const +const CModelPart& CModelMesh::GetPart(size_t index) const { - return m_triangles.size(); + return m_parts[index]; } const glm::vec3& CModelMesh::GetPosition() const @@ -82,4 +159,44 @@ void CModelMesh::SetParent(const std::string& parent) m_parent = parent; } +std::vector CModelMesh::GetTriangles() const +{ + std::vector triangles; + + for (const auto& part : m_parts) + { + if (part.IsIndexed()) + { + const auto& vertices = part.GetVertices(); + const auto& indices = part.GetIndices(); + + for (size_t i = 0; i < indices.size() - 2; i += 3) + { + triangles.push_back({ + vertices[indices[i]], + vertices[indices[i + 1]], + vertices[indices[i + 2]], + part.GetMaterial() + }); + } + } + else + { + const auto& vertices = part.GetVertices(); + + for (size_t i = 0; i < vertices.size() - 2; i += 3) + { + triangles.push_back({ + vertices[i], + vertices[i + 1], + vertices[i + 2], + part.GetMaterial() + }); + } + } + } + + return triangles; +} + } // namespace Gfx diff --git a/src/graphics/model/model_mesh.h b/src/graphics/model/model_mesh.h index b3664587..3216d982 100644 --- a/src/graphics/model/model_mesh.h +++ b/src/graphics/model/model_mesh.h @@ -26,6 +26,44 @@ namespace Gfx { +/** + * \class CModelPart + * \brief Part of mesh with a common material + */ +class CModelPart +{ +public: + //! Creates new part for given material + CModelPart(const Material& material); + + //! Returns this part's material + const Material& GetMaterial() const; + + //! Returns true if this part is indexed + bool IsIndexed() const; + //! Returns the number of vertices in this part + size_t GetVertexCount() const; + //! Returns the vertices in this part + const std::vector& GetVertices() const; + //! Returns the number of indices in this part + size_t GetIndexCount() const; + //! Returns the indices in this part + const std::vector& GetIndices() const; + + //! Adds a vertex + void AddVertex(const Vertex3D& vertex); + //! Adds an index + void AddIndex(unsigned int index); + +private: + //! Material + Material m_material; + //! Vertices + std::vector m_vertices; + //! Indices + std::vector m_indices; +}; + /** * \class CModelMesh * \brief Mesh data saved in model file @@ -35,12 +73,13 @@ class CModelMesh public: //! Adds a new triangle void AddTriangle(const ModelTriangle& triangle); - //! Sets the list of triangles - void SetTriangles(std::vector &&triangles); - //! Returns the list of triangles - const std::vector& GetTriangles() const; - //! Returns number of triangles - int GetTriangleCount() const; + //! Adds a new triangle + void AddTriangle(const Triangle& triangle, const Material& material); + + //! Returns the number of parts + size_t GetPartCount() const; + //! Returns a part with given index + const CModelPart& GetPart(size_t index) const; //! Returns the mesh position const glm::vec3& GetPosition() const; @@ -62,8 +101,11 @@ public: //! Sets the name of parent mesh void SetParent(const std::string& parent); + //! Returns all model triangles of this mesh + std::vector GetTriangles() const; + private: - std::vector m_triangles; + std::vector m_parts; glm::vec3 m_position; glm::vec3 m_rotation; glm::vec3 m_scale; diff --git a/src/graphics/model/model_triangle.h b/src/graphics/model/model_triangle.h index 498dcf4a..e57eb6dc 100644 --- a/src/graphics/model/model_triangle.h +++ b/src/graphics/model/model_triangle.h @@ -25,11 +25,25 @@ namespace Gfx { +/** + * \struct Triangle + * \brief A single triangle + */ +struct Triangle +{ + //! 1st vertex + Vertex3D p1; + //! 2nd vertex + Vertex3D p2; + //! 3rd vertex + Vertex3D p3; +}; + /** * \struct ModelTriangle * \brief A single triangle in mesh as saved in model file */ -struct ModelTriangle +struct [[deprecated]] ModelTriangle { //! 1st vertex Vertex3D p1;