198 lines
6.9 KiB
C++
198 lines
6.9 KiB
C++
// Copyright (C) 2024 Jérôme "SirLynix" Leclercq (lynix680@gmail.com)
|
|
// This file is part of the "Nazara Engine - Core module"
|
|
// For conditions of distribution and use, see copyright notice in Export.hpp
|
|
|
|
#pragma once
|
|
|
|
#ifndef NAZARA_CORE_MESH_HPP
|
|
#define NAZARA_CORE_MESH_HPP
|
|
|
|
#include <NazaraUtils/Prerequisites.hpp>
|
|
#include <Nazara/Core/Enums.hpp>
|
|
#include <Nazara/Core/Export.hpp>
|
|
#include <Nazara/Core/ObjectLibrary.hpp>
|
|
#include <Nazara/Core/Resource.hpp>
|
|
#include <Nazara/Core/ResourceLoader.hpp>
|
|
#include <Nazara/Core/ResourceManager.hpp>
|
|
#include <Nazara/Core/ResourceParameters.hpp>
|
|
#include <Nazara/Core/ResourceSaver.hpp>
|
|
#include <Nazara/Core/Skeleton.hpp>
|
|
#include <Nazara/Core/SoftwareBuffer.hpp>
|
|
#include <Nazara/Core/SubMesh.hpp>
|
|
#include <Nazara/Core/VertexDeclaration.hpp>
|
|
#include <Nazara/Core/VertexStruct.hpp>
|
|
#include <Nazara/Math/Box.hpp>
|
|
#include <unordered_map>
|
|
#include <vector>
|
|
|
|
namespace Nz
|
|
{
|
|
struct SerializationContext;
|
|
|
|
struct NAZARA_CORE_API MeshParams : ResourceParameters
|
|
{
|
|
// How buffer will be allocated (by default in RAM)
|
|
BufferFactory bufferFactory = &SoftwareBufferFactory;
|
|
|
|
// Buffer usage flags used to build the index buffers
|
|
BufferUsageFlags indexBufferFlags = BufferUsage::DirectMapping | BufferUsage::Read | BufferUsage::Write;
|
|
|
|
// Buffer usage flags used to build the vertex buffers
|
|
BufferUsageFlags vertexBufferFlags = BufferUsage::DirectMapping | BufferUsage::Read | BufferUsage::Write;
|
|
|
|
// Transform vertices and joints by these transformations
|
|
Vector3f vertexOffset = Vector3f::Zero();
|
|
|
|
Quaternionf vertexRotation = Quaternionf::Identity();
|
|
|
|
Vector3f vertexScale = Vector3f::Unit();
|
|
|
|
// Offset to apply on the texture coordinates (not scaled)
|
|
Vector2f texCoordOffset = {0.f, 0.f};
|
|
|
|
// Scale to apply on the texture coordinates
|
|
Vector2f texCoordScale = {1.f, 1.f};
|
|
|
|
// If true, will load an animated version of the model if possible
|
|
bool animated = true;
|
|
|
|
// If true, will center the mesh vertices around the origin
|
|
bool center = false;
|
|
|
|
// Optimize the index buffers after loading, improve cache locality (and thus rendering speed) but increase loading time.
|
|
#ifndef NAZARA_DEBUG
|
|
bool optimizeIndexBuffers = true;
|
|
#else
|
|
bool optimizeIndexBuffers = false;
|
|
#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 = VertexDeclaration::Get(VertexLayout::XYZ_Normal_UV_Tangent);
|
|
|
|
bool IsValid() const;
|
|
};
|
|
|
|
NAZARA_CORE_API bool Serialize(SerializationContext& context, const MeshParams& params, TypeTag<MeshParams>);
|
|
NAZARA_CORE_API bool Unserialize(SerializationContext& context, MeshParams* params, TypeTag<MeshParams>);
|
|
|
|
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<Mesh>;
|
|
using MeshLoader = ResourceLoader<Mesh, MeshParams>;
|
|
using MeshManager = ResourceManager<Mesh, MeshParams>;
|
|
using MeshSaver = ResourceSaver<Mesh, MeshParams>;
|
|
|
|
struct MeshImpl;
|
|
|
|
class NAZARA_CORE_API Mesh : public Resource
|
|
{
|
|
public:
|
|
using Params = MeshParams;
|
|
|
|
inline Mesh();
|
|
Mesh(const Mesh&) = delete;
|
|
Mesh(Mesh&&) = delete;
|
|
~Mesh() = default;
|
|
|
|
void AddSubMesh(std::shared_ptr<SubMesh> subMesh);
|
|
void AddSubMesh(std::string identifier, std::shared_ptr<SubMesh> subMesh);
|
|
|
|
std::shared_ptr<SubMesh> BuildSubMesh(const Primitive& primitive, const MeshParams& params = MeshParams());
|
|
void BuildSubMeshes(const PrimitiveList& primitiveList, 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<SubMesh>& GetSubMesh(std::string_view identifier) const;
|
|
const std::shared_ptr<SubMesh>& GetSubMesh(std::size_t index) const;
|
|
std::size_t GetSubMeshCount() const;
|
|
std::size_t GetSubMeshIndex(std::string_view identifier) const;
|
|
UInt32 GetTriangleCount() const;
|
|
UInt32 GetVertexCount() const;
|
|
|
|
bool HasSubMesh(std::string_view identifier) const;
|
|
bool HasSubMesh(std::size_t index = 0) const;
|
|
|
|
void InvalidateAABB() const;
|
|
|
|
bool IsAnimable() const;
|
|
bool IsValid() const;
|
|
|
|
void Recenter();
|
|
|
|
void RemoveSubMesh(std::string_view identifier);
|
|
void RemoveSubMesh(std::size_t index);
|
|
|
|
bool SaveToFile(const std::filesystem::path& filePath, const MeshParams& params = MeshParams());
|
|
bool SaveToStream(Stream& stream, std::string_view 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<Mesh> Build(std::shared_ptr<StaticMesh> staticMesh);
|
|
static inline std::shared_ptr<Mesh> Build(const Primitive& primitive, const MeshParams& params = MeshParams());
|
|
static inline std::shared_ptr<Mesh> Build(const PrimitiveList& primitiveList, const MeshParams& params = MeshParams());
|
|
|
|
static std::shared_ptr<Mesh> LoadFromFile(const std::filesystem::path& filePath, const MeshParams& params = MeshParams());
|
|
static std::shared_ptr<Mesh> LoadFromMemory(const void* data, std::size_t size, const MeshParams& params = MeshParams());
|
|
static std::shared_ptr<Mesh> LoadFromStream(Stream& stream, const MeshParams& params = MeshParams());
|
|
|
|
// Signals:
|
|
NazaraSignal(OnMeshInvalidateAABB, const Mesh* /*mesh*/);
|
|
|
|
private:
|
|
struct SubMeshData
|
|
{
|
|
std::shared_ptr<SubMesh> subMesh;
|
|
|
|
NazaraSlot(SubMesh, OnSubMeshInvalidateAABB, onSubMeshInvalidated);
|
|
};
|
|
|
|
std::size_t m_jointCount; // Only used by skeletal meshes
|
|
std::unordered_map<std::string, std::size_t, StringHash<>, std::equal_to<>> m_subMeshMap;
|
|
std::vector<ParameterList> m_materialData;
|
|
std::vector<SubMeshData> 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 <Nazara/Core/Mesh.inl>
|
|
|
|
#endif // NAZARA_CORE_MESH_HPP
|