// Copyright (C) 2020 Jérôme Leclercq // This file is part of the "Nazara Engine - Utility module" // For conditions of distribution and use, see copyright notice in Config.hpp #pragma once #ifndef NAZARA_MESH_HPP #define NAZARA_MESH_HPP #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace Nz { struct NAZARA_UTILITY_API MeshParams : ResourceParameters { MeshParams(); BufferUsageFlags indexBufferFlags = 0; ///< Buffer usage flags used to build the index buffers BufferUsageFlags vertexBufferFlags = 0; ///< Buffer usage flags used to build the vertex buffers Matrix4f matrix = Matrix4f::Identity(); ///< A matrix which will transform every vertex position DataStorage storage = DataStorage::Hardware; ///< The place where the buffers will be allocated Vector2f texCoordOffset = {0.f, 0.f}; ///< Offset to apply on the texture coordinates (not scaled) Vector2f texCoordScale = {1.f, 1.f}; ///< Scale to apply on the texture coordinates bool animated = true; ///< If true, will load an animated version of the model if possible bool center = false; ///< If true, will center the mesh vertices around the origin #ifndef NAZARA_DEBUG bool optimizeIndexBuffers = true; ///< Optimize the index buffers after loading, improve cache locality (and thus rendering speed) but increase loading time. #else bool optimizeIndexBuffers = false; ///< Since this optimization take a lot of time, especially in debug mode, don't enable it by default in debug. #endif /* The declaration must have a Vector3f position component enabled * If the declaration has a Vector2f UV component enabled, UV are generated * If the declaration has a Vector3f Normals component enabled, Normals are generated. * If the declaration has a Vector3f Tangents component enabled, Tangents are generated. */ std::shared_ptr vertexDeclaration = VertexDeclaration::Get(VertexLayout::XYZ_Normal_UV_Tangent); bool IsValid() const; }; class Mesh; struct Primitive; class PrimitiveList; class StaticMesh; class SubMesh; using MeshVertex = VertexStruct_XYZ_Normal_UV_Tangent; using SkeletalMeshVertex = VertexStruct_XYZ_Normal_UV_Tangent_Skinning; using MeshLibrary = ObjectLibrary; using MeshLoader = ResourceLoader; using MeshManager = ResourceManager; using MeshSaver = ResourceSaver; struct MeshImpl; class NAZARA_UTILITY_API Mesh : public Resource { public: inline Mesh(); Mesh(const Mesh&) = delete; Mesh(Mesh&&) = delete; ~Mesh() = default; void AddSubMesh(std::shared_ptr subMesh); void AddSubMesh(const std::string& identifier, std::shared_ptr subMesh); std::shared_ptr BuildSubMesh(const Primitive& primitive, const MeshParams& params = MeshParams()); void BuildSubMeshes(const PrimitiveList& list, const MeshParams& params = MeshParams()); bool CreateSkeletal(std::size_t jointCount); bool CreateStatic(); void Destroy(); void GenerateNormals(); void GenerateNormalsAndTangents(); void GenerateTangents(); const Boxf& GetAABB() const; std::filesystem::path GetAnimation() const; AnimationType GetAnimationType() const; std::size_t GetJointCount() const; ParameterList& GetMaterialData(std::size_t index); const ParameterList& GetMaterialData(std::size_t index) const; std::size_t GetMaterialCount() const; Skeleton* GetSkeleton(); const Skeleton* GetSkeleton() const; const std::shared_ptr& GetSubMesh(const std::string& identifier) const; const std::shared_ptr& GetSubMesh(std::size_t index) const; std::size_t GetSubMeshCount() const; std::size_t GetSubMeshIndex(const std::string& identifier) const; std::size_t GetTriangleCount() const; std::size_t GetVertexCount() const; bool HasSubMesh(const std::string& identifier) const; bool HasSubMesh(std::size_t index = 0) const; void InvalidateAABB() const; bool IsAnimable() const; bool IsValid() const; void Recenter(); void RemoveSubMesh(const std::string& identifier); void RemoveSubMesh(std::size_t index); bool SaveToFile(const std::filesystem::path& filePath, const MeshParams& params = MeshParams()); bool SaveToStream(Stream& stream, const std::string& format, const MeshParams& params = MeshParams()); void SetAnimation(const std::filesystem::path& animationPath); void SetMaterialCount(std::size_t matCount); void SetMaterialData(std::size_t matIndex, ParameterList data); void Transform(const Matrix4f& matrix); Mesh& operator=(const Mesh&) = delete; Mesh& operator=(Mesh&&) = delete; static inline std::shared_ptr Build(std::shared_ptr staticMesh); static std::shared_ptr LoadFromFile(const std::filesystem::path& filePath, const MeshParams& params = MeshParams()); static std::shared_ptr LoadFromMemory(const void* data, std::size_t size, const MeshParams& params = MeshParams()); static std::shared_ptr LoadFromStream(Stream& stream, const MeshParams& params = MeshParams()); // Signals: NazaraSignal(OnMeshInvalidateAABB, const Mesh* /*mesh*/); private: struct SubMeshData { std::shared_ptr subMesh; NazaraSlot(SubMesh, OnSubMeshInvalidateAABB, onSubMeshInvalidated); }; std::size_t m_jointCount; // Only used by skeletal meshes std::unordered_map m_subMeshMap; std::vector m_materialData; std::vector m_subMeshes; AnimationType m_animationType; mutable Boxf m_aabb; Skeleton m_skeleton; // Only used by skeletal meshes std::filesystem::path m_animationPath; mutable bool m_aabbUpdated; bool m_isValid; }; } #include #endif // NAZARA_MESH_HPP