From 039b034175e839e8db00fca29b2700fb253b10c1 Mon Sep 17 00:00:00 2001 From: CatChow0 Date: Tue, 24 Jun 2025 14:24:14 +0200 Subject: [PATCH] Major - ECS - V12.0.0 --- enginecustom/enginecustom.vcxproj | 9 + enginecustom/imgui.ini | 4 +- .../src/inc/system/application_class.h | 10 + enginecustom/src/inc/system/ecs/component.h | 40 ++ .../ecs/components/identity_component.h | 58 +++ .../system/ecs/components/physics_component.h | 110 +++++ .../system/ecs/components/render_component.h | 124 ++++++ .../system/ecs/components/shader_component.h | 67 +++ .../ecs/components/transform_component.h | 101 +++++ enginecustom/src/inc/system/ecs/entity.h | 101 +++++ .../src/inc/system/ecs/entity_manager.h | 95 +++++ .../inc/system/ecs/systems/render_system.h | 222 ++++++++++ .../src/src/system/application_class.cpp | 402 ++++++------------ 13 files changed, 1070 insertions(+), 273 deletions(-) create mode 100644 enginecustom/src/inc/system/ecs/component.h create mode 100644 enginecustom/src/inc/system/ecs/components/identity_component.h create mode 100644 enginecustom/src/inc/system/ecs/components/physics_component.h create mode 100644 enginecustom/src/inc/system/ecs/components/render_component.h create mode 100644 enginecustom/src/inc/system/ecs/components/shader_component.h create mode 100644 enginecustom/src/inc/system/ecs/components/transform_component.h create mode 100644 enginecustom/src/inc/system/ecs/entity.h create mode 100644 enginecustom/src/inc/system/ecs/entity_manager.h create mode 100644 enginecustom/src/inc/system/ecs/systems/render_system.h diff --git a/enginecustom/enginecustom.vcxproj b/enginecustom/enginecustom.vcxproj index 1032e5a..f24c322 100644 --- a/enginecustom/enginecustom.vcxproj +++ b/enginecustom/enginecustom.vcxproj @@ -119,6 +119,15 @@ + + + + + + + + + diff --git a/enginecustom/imgui.ini b/enginecustom/imgui.ini index 0bb0731..cf6ea87 100644 --- a/enginecustom/imgui.ini +++ b/enginecustom/imgui.ini @@ -10,7 +10,7 @@ Collapsed=0 [Window][Khaotic Engine] Pos=1267,19 -Size=317,441 +Size=317,842 Collapsed=0 DockId=0x00000005,0 @@ -28,7 +28,7 @@ DockId=0x0000000B,0 [Window][Terrain] Pos=0,19 -Size=266,609 +Size=266,842 Collapsed=0 DockId=0x00000007,0 diff --git a/enginecustom/src/inc/system/application_class.h b/enginecustom/src/inc/system/application_class.h index e8d7d12..a6e5081 100644 --- a/enginecustom/src/inc/system/application_class.h +++ b/enginecustom/src/inc/system/application_class.h @@ -32,6 +32,12 @@ #include "shadow_map.h" #include "stats.h" +#include "ecs/components/identity_component.h" +#include "ecs/components/render_component.h" +#include "ecs/components/transform_component.h" +#include "ecs/components/physics_component.h" +#include "ecs/components/shader_component.h" +#include "ecs/systems/render_system.h" #include #include @@ -46,6 +52,8 @@ #include #include +#include "ecs/entity_manager.h" + ///////////// // GLOBALS // @@ -234,6 +242,8 @@ private : // ------------- OBJECTS -------------- // // ------------------------------------ // + std::unique_ptr entity_manager_; + object* selected_object_; std::vector cubes_; std::vector terrain_chunk_; diff --git a/enginecustom/src/inc/system/ecs/component.h b/enginecustom/src/inc/system/ecs/component.h new file mode 100644 index 0000000..700111e --- /dev/null +++ b/enginecustom/src/inc/system/ecs/component.h @@ -0,0 +1,40 @@ +#pragma once +#include +#include +#include + +namespace ecs { + +// Classe de base pour tous les composants +class Component { +public: + Component() = default; + virtual ~Component() = default; + + // Empêcher la copie + Component(const Component&) = delete; + Component& operator=(const Component&) = delete; + + // Permettre le déplacement + Component(Component&&) = default; + Component& operator=(Component&&) = default; + + // Fonction virtuelle pour initialiser le composant + virtual void Initialize() {} + + // Fonction virtuelle pour la mise à jour du composant + virtual void Update(float deltaTime) {} +}; + +// Alias utiles +using ComponentPtr = std::shared_ptr; +using ComponentTypeID = std::type_index; + +// Fonction pour obtenir l'ID de type d'un composant +template +ComponentTypeID GetComponentTypeID() { + static_assert(std::is_base_of::value, "T must derive from Component"); + return std::type_index(typeid(T)); +} + +} // namespace ecs diff --git a/enginecustom/src/inc/system/ecs/components/identity_component.h b/enginecustom/src/inc/system/ecs/components/identity_component.h new file mode 100644 index 0000000..16f5655 --- /dev/null +++ b/enginecustom/src/inc/system/ecs/components/identity_component.h @@ -0,0 +1,58 @@ +#pragma once +#include "../component.h" +#include + +namespace ecs { + +enum class ObjectType +{ + Sphere, + Cube, + Terrain, + Unknown +}; + +class IdentityComponent : public Component { +public: + IdentityComponent() : m_id(0), m_type(ObjectType::Unknown) {} + explicit IdentityComponent(int id) : m_id(id), m_type(ObjectType::Unknown) {} + IdentityComponent(int id, const std::string& name) : m_id(id), m_name(name), m_type(ObjectType::Unknown) {} + ~IdentityComponent() = default; + + void Initialize() override {} + void Update(float deltaTime) override {} + + // Getters et setters + int GetId() const { return m_id; } + void SetId(int id) { m_id = id; } + + const std::string& GetName() const { return m_name; } + void SetName(const std::string& name) { m_name = name; } + + ObjectType GetType() const { return m_type; } + void SetType(ObjectType type) { m_type = type; } + + // Conversions utiles + static std::string ObjectTypeToString(ObjectType type) { + switch (type) { + case ObjectType::Cube: return "Cube"; + case ObjectType::Sphere: return "Sphere"; + case ObjectType::Terrain: return "Terrain"; + default: return "Unknown"; + } + } + + static ObjectType StringToObjectType(const std::string& str) { + if (str == "Cube") return ObjectType::Cube; + if (str == "Sphere") return ObjectType::Sphere; + if (str == "Terrain") return ObjectType::Terrain; + return ObjectType::Unknown; + } + +private: + int m_id; + std::string m_name; + ObjectType m_type; +}; + +} // namespace ecs diff --git a/enginecustom/src/inc/system/ecs/components/physics_component.h b/enginecustom/src/inc/system/ecs/components/physics_component.h new file mode 100644 index 0000000..8245b09 --- /dev/null +++ b/enginecustom/src/inc/system/ecs/components/physics_component.h @@ -0,0 +1,110 @@ +#pragma once +#include "../component.h" +#include + +using namespace DirectX; + +namespace ecs { + +class PhysicsComponent : public Component { +public: + PhysicsComponent() { + m_Velocity = XMVectorZero(); + m_Acceleration = XMVectorZero(); + m_PreviousPosition = XMVectorZero(); + m_Mass = 1.0f; + m_BoundingRadius = 1.0f; + m_IsGrounded = false; + m_IsPhysicsEnabled = false; + m_GravityEnabled = true; + } + + ~PhysicsComponent() = default; + + void Initialize() override { + // Initialisation du composant physique + } + + void Update(float deltaTime) override { + if (!m_IsPhysicsEnabled) return; + + // Mise à jour de la vélocité basée sur l'accélération + m_Velocity = m_Velocity + m_Acceleration * deltaTime; + + // Si la physique est activée et qu'une fonction de mise à jour de position est définie + if (m_UpdatePositionCallback) { + m_UpdatePositionCallback(m_Velocity * deltaTime); + } + } + + // Lancement d'un objet + void LaunchObject(float alpha, float initialStretch, float springConstant) { + // Constants + const float gravity = -9.81f; + + // Convert alpha from degrees to radians if needed + float alphaRadians = alpha * (XM_PI / 180.0f); + + // Scale factors to make the physics simulation more visible + float scaleFactor = 200.0f; // Adjust this based on your world scale + + // Calculate initial velocity magnitude + float velocityMagnitude = initialStretch * sqrtf(springConstant / m_Mass) * + sqrtf(1.0f - powf((m_Mass * gravity * sinf(alphaRadians) / + (springConstant * initialStretch)), 2.0f)); + + // Apply scale factor + velocityMagnitude *= scaleFactor; + + // Calculate velocity components + XMVECTOR velocity = XMVectorSet( + velocityMagnitude * cosf(alphaRadians), // vx = v0 * cos(alpha) + velocityMagnitude * sinf(alphaRadians), // vy = v0 * sin(alpha) + 0.0f, // z-component (0 for 2D trajectory) + 0.0f + ); + + // Apply velocity + SetVelocity(velocity); + + // Enable physics and reset grounded state + SetPhysicsEnabled(true); + SetGrounded(false); + } + + // Setters + void SetVelocity(XMVECTOR velocity) { m_Velocity = velocity; } + void SetAcceleration(XMVECTOR acceleration) { m_Acceleration = acceleration; } + void SetMass(float mass) { m_Mass = mass; } + void SetGrounded(bool isGrounded) { m_IsGrounded = isGrounded; } + void SetPhysicsEnabled(bool enabled) { m_IsPhysicsEnabled = enabled; } + void SetBoundingRadius(float radius) { m_BoundingRadius = radius; } + void SetPreviousPosition(XMVECTOR position) { m_PreviousPosition = position; } + void SetGravityEnabled(bool enabled) { m_GravityEnabled = enabled; } + void SetUpdatePositionCallback(std::function callback) { m_UpdatePositionCallback = callback; } + + // Getters + XMVECTOR GetVelocity() const { return m_Velocity; } + XMVECTOR GetAcceleration() const { return m_Acceleration; } + float GetMass() const { return m_Mass; } + bool IsGrounded() const { return m_IsGrounded; } + bool IsPhysicsEnabled() const { return m_IsPhysicsEnabled; } + float GetBoundingRadius() const { return m_BoundingRadius; } + XMVECTOR GetPreviousPosition() const { return m_PreviousPosition; } + bool IsGravityEnabled() const { return m_GravityEnabled; } + +private: + XMVECTOR m_Velocity; + XMVECTOR m_Acceleration; + XMVECTOR m_PreviousPosition; + float m_Mass; + float m_BoundingRadius; + bool m_IsGrounded; + bool m_IsPhysicsEnabled; + bool m_GravityEnabled; + + // Callback pour mettre à jour la position (sera connecté au TransformComponent) + std::function m_UpdatePositionCallback; +}; + +} // namespace ecs diff --git a/enginecustom/src/inc/system/ecs/components/render_component.h b/enginecustom/src/inc/system/ecs/components/render_component.h new file mode 100644 index 0000000..dfb909d --- /dev/null +++ b/enginecustom/src/inc/system/ecs/components/render_component.h @@ -0,0 +1,124 @@ +#pragma once +#include "../component.h" +#include "model_class.h" +#include +#include +#include +#include + +// Déclaration externe de la variable globale définie dans application_class.h +extern std::map> g_model_cache; + +namespace ecs { + +enum class TextureType +{ + Diffuse, + Normal, + Specular, + Alpha, + Reflection +}; + +class RenderComponent : public Component { +public: + RenderComponent() : m_model(nullptr), m_isVisible(true) {} + ~RenderComponent() = default; + + void Initialize() override {} + void Update(float deltaTime) override {} + + // Initialisation avec un modèle existant + bool InitializeWithModel(std::shared_ptr model) { + if (!model) return false; + m_model = model; + return true; + } + + // Initialisation avec un chemin de fichier + bool InitializeFromFile(ID3D11Device* device, ID3D11DeviceContext* deviceContext, + const char* modelFilename, TextureContainer& textureContainer) { + // Vérifier si le modèle existe déjà dans le cache + std::string filename(modelFilename); + auto it = g_model_cache.find(filename); + if (it != g_model_cache.end()) { + m_model = it->second; + } else { + // Créer un nouveau modèle + auto new_model = std::make_shared(); + if (!new_model->Initialize(device, deviceContext, const_cast(modelFilename), textureContainer)) { + return false; + } + g_model_cache[filename] = new_model; + m_model = new_model; + } + + m_modelFilePath = modelFilename; + return true; + } + + // Charger des textures depuis un chemin + bool LoadTexturesFromPath(std::vector& texturePaths, TextureContainer& texturesContainer, + ID3D11Device* device, ID3D11DeviceContext* deviceContext) { + HRESULT result; + + int i = 0; + for (const auto& texturePath : texturePaths) { + ID3D11ShaderResourceView* texture = nullptr; + result = DirectX::CreateWICTextureFromFile(device, deviceContext, texturePath.c_str(), nullptr, &texture); + if (FAILED(result)) { + return false; + } + texturesContainer.AssignTexture(texturesContainer, texture, texturePath, i); + i++; + } + + return true; + } + + // Getters et setters + std::shared_ptr GetModel() const { return m_model; } + void SetModel(std::shared_ptr model) { m_model = model; } + + const std::string& GetModelFilePath() const { return m_modelFilePath; } + void SetModelFilePath(const std::string& path) { m_modelFilePath = path; } + + bool IsVisible() const { return m_isVisible; } + void SetVisible(bool visible) { m_isVisible = visible; } + + // Accès aux textures + ID3D11ShaderResourceView* GetTexture(TextureType type, int index = 0) { + if (!m_model) return nullptr; + + switch (type) { + case TextureType::Diffuse: + return m_model->GetTexture(::TextureType::Diffuse, index); + case TextureType::Normal: + return m_model->GetTexture(::TextureType::Normal, index); + case TextureType::Specular: + return m_model->GetTexture(::TextureType::Specular, index); + case TextureType::Alpha: + return m_model->GetTexture(::TextureType::Alpha, index); + default: + return nullptr; + } + } + + // Pour le rendu + int GetIndexCount() const { + return m_model ? m_model->GetIndexCount() : 0; + } + + void Render(ID3D11DeviceContext* deviceContext) { + if (m_model && m_isVisible) { + m_model->Render(deviceContext); + } + } + +private: + std::shared_ptr m_model; + std::string m_modelFilePath; + bool m_isVisible; +}; + +} // namespace ecs diff --git a/enginecustom/src/inc/system/ecs/components/shader_component.h b/enginecustom/src/inc/system/ecs/components/shader_component.h new file mode 100644 index 0000000..3b343bf --- /dev/null +++ b/enginecustom/src/inc/system/ecs/components/shader_component.h @@ -0,0 +1,67 @@ +#pragma once +#include "../component.h" + +namespace ecs { + +enum class ShaderType +{ + CEL_SHADING, + LIGHTING, + NORMAL_MAPPING, + SPECULAR_MAPPING, + REFLECTION, + REFRACTION, + TEXTURE, + SKYBOX, + SUNLIGHT, + ALPHA_MAPPING +}; + +class ShaderComponent : public Component { +public: + ShaderComponent() : m_activeShader(ShaderType::LIGHTING) {} + ~ShaderComponent() = default; + + void Initialize() override {} + void Update(float deltaTime) override {} + + // Getters et setters + ShaderType GetActiveShader() const { return m_activeShader; } + void SetActiveShader(ShaderType shader) { m_activeShader = shader; } + + // Conversions utiles + static ShaderType StringToShaderType(const std::string& str) { + if (str == "ALPHA_MAPPING") return ShaderType::ALPHA_MAPPING; + if (str == "CEL_SHADING") return ShaderType::CEL_SHADING; + if (str == "NORMAL_MAPPING") return ShaderType::NORMAL_MAPPING; + if (str == "SPECULAR_MAPPING") return ShaderType::SPECULAR_MAPPING; + if (str == "TEXTURE") return ShaderType::TEXTURE; + if (str == "LIGHTING") return ShaderType::LIGHTING; + if (str == "SUNLIGHT") return ShaderType::SUNLIGHT; + if (str == "SKYBOX") return ShaderType::SKYBOX; + if (str == "REFLECTION") return ShaderType::REFLECTION; + if (str == "REFRACTION") return ShaderType::REFRACTION; + return ShaderType::TEXTURE; + } + + static std::string ShaderTypeToString(ShaderType type) { + switch (type) { + case ShaderType::ALPHA_MAPPING: return "ALPHA_MAPPING"; + case ShaderType::CEL_SHADING: return "CEL_SHADING"; + case ShaderType::NORMAL_MAPPING: return "NORMAL_MAPPING"; + case ShaderType::SPECULAR_MAPPING: return "SPECULAR_MAPPING"; + case ShaderType::TEXTURE: return "TEXTURE"; + case ShaderType::LIGHTING: return "LIGHTING"; + case ShaderType::SUNLIGHT: return "SUNLIGHT"; + case ShaderType::SKYBOX: return "SKYBOX"; + case ShaderType::REFLECTION: return "REFLECTION"; + case ShaderType::REFRACTION: return "REFRACTION"; + default: return "TEXTURE"; + } + } + +private: + ShaderType m_activeShader; +}; + +} // namespace ecs diff --git a/enginecustom/src/inc/system/ecs/components/transform_component.h b/enginecustom/src/inc/system/ecs/components/transform_component.h new file mode 100644 index 0000000..dd896f7 --- /dev/null +++ b/enginecustom/src/inc/system/ecs/components/transform_component.h @@ -0,0 +1,101 @@ +#pragma once +#include "../component.h" +#include + +using namespace DirectX; + +namespace ecs { + +class TransformComponent : public Component { +public: + TransformComponent() { + m_ScaleMatrix = XMMatrixIdentity(); + m_RotateMatrix = XMMatrixIdentity(); + m_TranslateMatrix = XMMatrixIdentity(); + m_WorldMatrix = XMMatrixIdentity(); + } + + ~TransformComponent() = default; + + // Méthodes pour les matrices + void SetPosition(XMVECTOR position) { + XMFLOAT4X4 matrix; + XMStoreFloat4x4(&matrix, m_TranslateMatrix); + matrix._41 = XMVectorGetX(position); + matrix._42 = XMVectorGetY(position); + matrix._43 = XMVectorGetZ(position); + m_TranslateMatrix = XMLoadFloat4x4(&matrix); + UpdateWorldMatrix(); + } + + void SetRotation(XMVECTOR rotation) { + m_RotateMatrix = XMMatrixRotationRollPitchYawFromVector(rotation); + UpdateWorldMatrix(); + } + + void SetScale(XMVECTOR scale) { + XMFLOAT4X4 matrix; + XMStoreFloat4x4(&matrix, m_ScaleMatrix); + matrix._11 = XMVectorGetX(scale); + matrix._22 = XMVectorGetY(scale); + matrix._33 = XMVectorGetZ(scale); + m_ScaleMatrix = XMLoadFloat4x4(&matrix); + UpdateWorldMatrix(); + } + + XMVECTOR GetPosition() const { + XMFLOAT4X4 matrix; + XMStoreFloat4x4(&matrix, m_TranslateMatrix); + return XMVectorSet(matrix._41, matrix._42, matrix._43, 0.0f); + } + + XMVECTOR GetRotation() const { + XMFLOAT4X4 matrix; + XMStoreFloat4x4(&matrix, m_RotateMatrix); + float rotationX = atan2f(matrix._32, matrix._33); + float rotationY = atan2f(-matrix._31, sqrtf(matrix._32 * matrix._32 + matrix._33 * matrix._33)); + float rotationZ = atan2f(matrix._21, matrix._11); + return XMVectorSet(rotationX, rotationY, rotationZ, 0.0f); + } + + XMVECTOR GetScale() const { + XMFLOAT4X4 matrix; + XMStoreFloat4x4(&matrix, m_ScaleMatrix); + + XMVECTOR row1 = XMLoadFloat3(reinterpret_cast(&matrix._11)); + XMVECTOR row2 = XMLoadFloat3(reinterpret_cast(&matrix._21)); + XMVECTOR row3 = XMLoadFloat3(reinterpret_cast(&matrix._31)); + + XMVECTOR scale = XMVectorSet( + XMVectorGetX(XMVector3Length(row1)), + XMVectorGetX(XMVector3Length(row2)), + XMVectorGetX(XMVector3Length(row3)), + 0.0f + ); + + return scale; + } + + void UpdateWorldMatrix() { + m_WorldMatrix = m_ScaleMatrix * m_RotateMatrix * m_TranslateMatrix; + } + + // Getters pour les matrices + XMMATRIX GetScaleMatrix() const { return m_ScaleMatrix; } + XMMATRIX GetRotateMatrix() const { return m_RotateMatrix; } + XMMATRIX GetTranslateMatrix() const { return m_TranslateMatrix; } + XMMATRIX GetWorldMatrix() const { return m_WorldMatrix; } + + // Setters pour les matrices + void SetScaleMatrix(XMMATRIX matrix) { m_ScaleMatrix = matrix; UpdateWorldMatrix(); } + void SetRotateMatrix(XMMATRIX matrix) { m_RotateMatrix = matrix; UpdateWorldMatrix(); } + void SetTranslateMatrix(XMMATRIX matrix) { m_TranslateMatrix = matrix; UpdateWorldMatrix(); } + +private: + XMMATRIX m_ScaleMatrix; + XMMATRIX m_RotateMatrix; + XMMATRIX m_TranslateMatrix; + XMMATRIX m_WorldMatrix; +}; + +} // namespace ecs diff --git a/enginecustom/src/inc/system/ecs/entity.h b/enginecustom/src/inc/system/ecs/entity.h new file mode 100644 index 0000000..6b16769 --- /dev/null +++ b/enginecustom/src/inc/system/ecs/entity.h @@ -0,0 +1,101 @@ +#pragma once +#include "component.h" +#include +#include +#include +#include +#include + +namespace ecs { + +// Identifiant unique pour les entités +using EntityID = uint32_t; + +class Entity { +public: + explicit Entity(EntityID id) : m_ID(id) {} + ~Entity() = default; + + // Empêcher la copie + Entity(const Entity&) = delete; + Entity& operator=(const Entity&) = delete; + + // Permettre le déplacement + Entity(Entity&&) = default; + Entity& operator=(Entity&&) = default; + + // Getter pour l'ID + EntityID GetID() const { return m_ID; } + + // Ajouter un composant + template + std::shared_ptr AddComponent(Args&&... args) { + static_assert(std::is_base_of::value, "T must derive from Component"); + + ComponentTypeID typeID = GetComponentTypeID(); + + // Vérifier si le composant existe déjà + if (m_Components.find(typeID) != m_Components.end()) { + return std::static_pointer_cast(m_Components[typeID]); + } + + // Créer et ajouter le composant + auto component = std::make_shared(std::forward(args)...); + m_Components[typeID] = component; + + // Initialiser le composant + component->Initialize(); + + return component; + } + + // Récupérer un composant + template + std::shared_ptr GetComponent() { + static_assert(std::is_base_of::value, "T must derive from Component"); + + ComponentTypeID typeID = GetComponentTypeID(); + + auto it = m_Components.find(typeID); + if (it != m_Components.end()) { + return std::static_pointer_cast(it->second); + } + + return nullptr; + } + + // Vérifier si l'entité possède un composant + template + bool HasComponent() const { + static_assert(std::is_base_of::value, "T must derive from Component"); + + ComponentTypeID typeID = GetComponentTypeID(); + return m_Components.find(typeID) != m_Components.end(); + } + + // Supprimer un composant + template + void RemoveComponent() { + static_assert(std::is_base_of::value, "T must derive from Component"); + + ComponentTypeID typeID = GetComponentTypeID(); + auto it = m_Components.find(typeID); + + if (it != m_Components.end()) { + m_Components.erase(it); + } + } + + // Mettre à jour tous les composants + void UpdateComponents(float deltaTime) { + for (auto& [typeID, component] : m_Components) { + component->Update(deltaTime); + } + } + +private: + EntityID m_ID; + std::unordered_map m_Components; +}; + +} // namespace ecs diff --git a/enginecustom/src/inc/system/ecs/entity_manager.h b/enginecustom/src/inc/system/ecs/entity_manager.h new file mode 100644 index 0000000..1ff1686 --- /dev/null +++ b/enginecustom/src/inc/system/ecs/entity_manager.h @@ -0,0 +1,95 @@ +#pragma once +#include "entity.h" +#include +#include +#include + +namespace ecs { + +class EntityManager { +public: + EntityManager() : m_NextEntityID(0) {} + ~EntityManager() = default; + + // Créer une nouvelle entité + std::shared_ptr CreateEntity() { + EntityID id; + + // Réutiliser les IDs des entités supprimées si possible + if (!m_FreeIDs.empty()) { + id = m_FreeIDs.front(); + m_FreeIDs.pop(); + } else { + id = m_NextEntityID++; + } + + auto entity = std::make_shared(id); + m_Entities[id] = entity; + + return entity; + } + + // Supprimer une entité + void DestroyEntity(EntityID id) { + auto it = m_Entities.find(id); + if (it != m_Entities.end()) { + m_Entities.erase(it); + m_FreeIDs.push(id); // Recycler l'ID + } + } + + // Obtenir une entité par son ID + std::shared_ptr GetEntity(EntityID id) { + auto it = m_Entities.find(id); + if (it != m_Entities.end()) { + return it->second; + } + return nullptr; + } + + // Mettre à jour toutes les entités + void UpdateEntities(float deltaTime) { + for (auto& [id, entity] : m_Entities) { + entity->UpdateComponents(deltaTime); + } + } + + // Obtenir toutes les entités qui ont un composant spécifique + template + std::vector> GetEntitiesWithComponent() { + static_assert(std::is_base_of::value, "T must derive from Component"); + + std::vector> result; + + for (auto& [id, entity] : m_Entities) { + if (entity->HasComponent()) { + result.push_back(entity); + } + } + + return result; + } + + // Obtenir le nombre d'entités + size_t GetEntityCount() const { + return m_Entities.size(); + } + + // Vider toutes les entités + void Clear() { + m_Entities.clear(); + + // Vider la file des IDs libres + std::queue empty; + std::swap(m_FreeIDs, empty); + + m_NextEntityID = 0; + } + +private: + EntityID m_NextEntityID; + std::unordered_map> m_Entities; + std::queue m_FreeIDs; // IDs à réutiliser +}; + +} // namespace ecs diff --git a/enginecustom/src/inc/system/ecs/systems/render_system.h b/enginecustom/src/inc/system/ecs/systems/render_system.h new file mode 100644 index 0000000..ba9245c --- /dev/null +++ b/enginecustom/src/inc/system/ecs/systems/render_system.h @@ -0,0 +1,222 @@ +#pragma once +#include "../entity_manager.h" +#include "../components/render_component.h" +#include "../components/transform_component.h" +#include "../components/shader_component.h" +#include "shader_manager_class.h" +#include + +namespace ecs { + +class RenderSystem { +public: + RenderSystem(ID3D11DeviceContext* deviceContext, shader_manager_class* shaderManager) + : m_deviceContext(deviceContext), m_shaderManager(shaderManager) {} + + // Rendu d'une entité spécifique + bool RenderEntity(std::shared_ptr entity, + const DirectX::XMMATRIX& viewMatrix, + const DirectX::XMMATRIX& projectionMatrix, + const DirectX::XMFLOAT4* diffuseColors, + const DirectX::XMFLOAT4* lightPositions, + const DirectX::XMFLOAT4* ambientColors, + const DirectX::XMFLOAT3& cameraPosition, + const DirectX::XMFLOAT4& sunlightDiffuse, + const DirectX::XMFLOAT4& sunlightAmbient, + const DirectX::XMFLOAT3& sunlightDirection, + float sunlightIntensity) { + + // Vérifier si l'entité a tous les composants nécessaires + auto transform = entity->GetComponent(); + auto render = entity->GetComponent(); + auto shader = entity->GetComponent(); + + if (!transform || !render || !shader || !render->GetModel()) + return false; + + // Calculer la matrice monde + XMMATRIX scaleMatrix = transform->GetScaleMatrix(); + XMMATRIX rotateMatrix = transform->GetRotateMatrix(); + XMMATRIX translateMatrix = transform->GetTranslateMatrix(); + + XMMATRIX worldMatrix = XMMatrixMultiply( + XMMatrixMultiply(scaleMatrix, rotateMatrix), + translateMatrix + ); + + // Rendre le modèle + render->Render(m_deviceContext); + + // Sélectionner le shader approprié + switch (shader->GetActiveShader()) { + case ShaderType::ALPHA_MAPPING: + return m_shaderManager->render_alpha_map_shader( + m_deviceContext, + render->GetIndexCount(), + worldMatrix, + viewMatrix, + projectionMatrix, + render->GetTexture(TextureType::Diffuse, 0), + render->GetTexture(TextureType::Diffuse, 1), + render->GetTexture(TextureType::Alpha, 0) + ); + + case ShaderType::CEL_SHADING: + return m_shaderManager->render_cel_shading_shader( + m_deviceContext, + render->GetIndexCount(), + worldMatrix, + viewMatrix, + projectionMatrix, + render->GetTexture(TextureType::Diffuse, 0), + sunlightDiffuse, + sunlightAmbient, + sunlightDirection, + sunlightIntensity + ); + + case ShaderType::NORMAL_MAPPING: + return m_shaderManager->render_normal_map_shader( + m_deviceContext, + render->GetIndexCount(), + worldMatrix, + viewMatrix, + projectionMatrix, + render->GetTexture(TextureType::Diffuse, 0), + render->GetTexture(TextureType::Normal, 0), + sunlightDirection, + sunlightDiffuse + ); + + case ShaderType::SPECULAR_MAPPING: + + return m_shaderManager->render_spec_map_shader( + m_deviceContext, + render->GetIndexCount(), + worldMatrix, + viewMatrix, + projectionMatrix, + render->GetTexture(TextureType::Diffuse, 0), + render->GetTexture(TextureType::Normal, 0), + render->GetTexture(TextureType::Specular, 0), + sunlightDirection, + sunlightDiffuse, + cameraPosition, + sunlightDiffuse, // Couleur speculaire (à ajuster) + 16.0f // Puissance speculaire (à ajuster) + ); + + case ShaderType::LIGHTING: + { + // Créer des copies locales non constantes des tableaux + DirectX::XMFLOAT4 localDiffuseColors[4]; + DirectX::XMFLOAT4 localLightPositions[4]; + DirectX::XMFLOAT4 localAmbientColors[4]; + + // Copier les données + for (int i = 0; i < 4; i++) { + localDiffuseColors[i] = diffuseColors[i]; + localLightPositions[i] = lightPositions[i]; + localAmbientColors[i] = ambientColors[i]; + } + + return m_shaderManager->renderlight_shader( + m_deviceContext, + render->GetIndexCount(), + worldMatrix, + viewMatrix, + projectionMatrix, + render->GetTexture(TextureType::Diffuse, 0), + localDiffuseColors, + localLightPositions, + localAmbientColors + ); + } + + case ShaderType::SUNLIGHT: + return m_shaderManager->render_sunlight_shader( + m_deviceContext, + render->GetIndexCount(), + worldMatrix, + viewMatrix, + projectionMatrix, + render->GetTexture(TextureType::Diffuse, 0), + sunlightDiffuse, + sunlightAmbient, + sunlightDirection, + sunlightIntensity + ); + + case ShaderType::SKYBOX: + return m_shaderManager->render_skybox_shader( + m_deviceContext, + render->GetIndexCount(), + worldMatrix, + viewMatrix, + projectionMatrix, + render->GetTexture(TextureType::Diffuse, 0), + sunlightDiffuse, + sunlightAmbient, + sunlightDirection, + sunlightIntensity + ); + + case ShaderType::TEXTURE: + default: + return m_shaderManager->render_texture_shader( + m_deviceContext, + render->GetIndexCount(), + worldMatrix, + viewMatrix, + projectionMatrix, + render->GetTexture(TextureType::Diffuse, 0) + ); + } + } + + // Rendu de toutes les entités avec les composants nécessaires + int RenderAllEntities(EntityManager* entityManager, + const DirectX::XMMATRIX& viewMatrix, + const DirectX::XMMATRIX& projectionMatrix, + const DirectX::XMFLOAT4* diffuseColors, + const DirectX::XMFLOAT4* lightPositions, + const DirectX::XMFLOAT4* ambientColors, + const DirectX::XMFLOAT3& cameraPos, + const DirectX::XMFLOAT4& sunlightDiffuse, + const DirectX::XMFLOAT4& sunlightAmbient, + const DirectX::XMFLOAT3& sunlightDirection, + float sunlightIntensity) { + + int renderCount = 0; + + // Récupérer toutes les entités qui ont les composants RenderComponent et TransformComponent + auto entities = entityManager->GetEntitiesWithComponent(); + + for (auto& entity : entities) { + auto render = entity->GetComponent(); + + // Vérifier si l'entité a un TransformComponent + auto transform = entity->GetComponent(); + if (!transform) continue; + + // Vérifier si le modèle est visible + if (!render->IsVisible()) continue; + + // Effectuer le rendu + if (RenderEntity(entity, viewMatrix, projectionMatrix, + diffuseColors, lightPositions, ambientColors,cameraPos, + sunlightDiffuse, sunlightAmbient, sunlightDirection, + sunlightIntensity)) { + renderCount++; + } + } + + return renderCount; + } + +private: + ID3D11DeviceContext* m_deviceContext; + shader_manager_class* m_shaderManager; +}; + +} // namespace ecs diff --git a/enginecustom/src/src/system/application_class.cpp b/enginecustom/src/src/system/application_class.cpp index 9137546..c3a2564 100644 --- a/enginecustom/src/src/system/application_class.cpp +++ b/enginecustom/src/src/system/application_class.cpp @@ -91,6 +91,9 @@ bool application_class::initialize(int screenWidth, int screenHeight, HWND hwnd, render_queues_.push_back(std::ref(cubes_)); render_queues_.push_back(std::ref(terrain_chunk_)); + // create entity manager + entity_manager_ = std::make_unique(); + screen_width_ = screenWidth; screen_height_ = screenHeight; @@ -1725,271 +1728,100 @@ void application_class::culling_thread_function() bool application_class::render_pass(const std::vector>>& RenderQueues, XMFLOAT4* diffuse, XMFLOAT4* position, XMFLOAT4* ambient, XMMATRIX view, XMMATRIX projection) { std::lock_guard lock(objects_mutex_); - XMMATRIX scaleMatrix, rotateMatrix, translateMatrix ; + XMMATRIX scaleMatrix, rotateMatrix, translateMatrix; bool result; int renderCount = 0; int i; - if (RenderQueues.empty()) + // render skybox + for (auto& skyboxObject : skybox_) { - Logger::Get().Log("RenderQueues is empty", __FILE__, __LINE__, Logger::LogLevel::Error); - return false; + if (skyboxObject == nullptr) + { + Logger::Get().Log("skyboxObject is null", __FILE__, __LINE__, Logger::LogLevel::Error); + return false; + } + + if (!skyboxObject->IsVisible()) + { + continue; + } + + direct_3d_->turn_z_buffer_off(); + + scaleMatrix = skyboxObject->GetScaleMatrix(); + rotateMatrix = skyboxObject->GetRotateMatrix(); + translateMatrix = skyboxObject->GetTranslateMatrix(); + + XMMATRIX worldMatrix = XMMatrixMultiply( + XMMatrixMultiply(scaleMatrix, rotateMatrix), + translateMatrix + ); + + renderCount++; + + skyboxObject->get_model()->Render(direct_3d_->get_device_context()); + + result = shader_manager_->render_skybox_shader( + direct_3d_->get_device_context(), + skyboxObject->get_model()->GetIndexCount(), + worldMatrix, + view, + projection, + skyboxObject->get_model()->GetTexture(TextureType::Diffuse,0), + sun_light_->GetDiffuseColor(), + sun_light_->GetAmbientColor(), + sun_light_->GetDirection(), + sun_light_->GetIntensity() + ); + if (!result) + { + Logger::Get().Log("Could not render the object model using the skybox shader", __FILE__, __LINE__, Logger::LogLevel::Error); + return false; + } + direct_3d_->turn_z_buffer_on(); // Réactiver le Z-buffer après le rendu de la skybox + + break; + } + // Rendu des entités du système ECS s'il est disponible + if (entity_manager_) { + // Créer le système de rendu pour les entités + ecs::RenderSystem renderSystem(direct_3d_->get_device_context(), shader_manager_); + + // Données pour le système de rendu + XMFLOAT4 sunlightDiffuse = sun_light_->GetDiffuseColor(); + XMFLOAT4 sunlightAmbient = sun_light_->GetAmbientColor(); + XMFLOAT3 sunlightDirection = sun_light_->GetDirection(); + float sunlightIntensity = sun_light_->GetIntensity(); + + // Effectuer le rendu de toutes les entités + int entitiesRendered = renderSystem.RenderAllEntities( + entity_manager_.get(), + view, + projection, + diffuse, + position, + ambient, + camera_->get_position(), + sunlightDiffuse, + sunlightAmbient, + sunlightDirection, + sunlightIntensity + ); + + renderCount += entitiesRendered; + } + + // Rendu des objets traditionnels comme avant // if (active_camera_ == sun_camera_) // { // shadow_map_->set_render_target(direct_3d_->get_device_context()); // shadow_map_->clear_render_target(direct_3d_->get_device_context()); // } - for (const auto& RenderQueue : RenderQueues) - { - // Désactiver le Z-buffer si la RenderQueue est skybox_ - bool isSkybox = (&RenderQueue.get() == &skybox_); - if (isSkybox) - { - direct_3d_->turn_z_buffer_off(); - } - - for (auto& object : RenderQueue.get()) - { - if (object == nullptr) - { - Logger::Get().Log("object is null", __FILE__, __LINE__, Logger::LogLevel::Error); - return false; - } - - // Check if the object has physics enabled - if (object->IsPhysicsEnabled()) - { - object->UpdatePosition(timer_->GetTime()); - } - - if (!object->IsVisible()) - { - continue; - } - - renderCount++; - - scaleMatrix = object->GetScaleMatrix(); - rotateMatrix = object->GetRotateMatrix(); - translateMatrix = object->GetTranslateMatrix(); - - XMMATRIX worldMatrix = XMMatrixMultiply( - XMMatrixMultiply(scaleMatrix, rotateMatrix), - translateMatrix - ); - - object->get_model()->Render(direct_3d_->get_device_context()); - - if (active_camera_ == sun_camera_) - { - result = shader_manager_->render_depth_shader( - direct_3d_->get_device_context(), - object->get_model()->GetIndexCount(), - worldMatrix, - view, - projection, - object->get_model()->GetTexture(TextureType::Diffuse,0) - ); - } - - // Utiliser l'enum ShaderType pour déterminer quel shader utiliser - switch (object->GetActiveShader()) - { - - case ShaderType::ALPHA_MAPPING: - - // Enable alpha blending for transparency. - direct_3d_->enable_alpha_blending(); - - result = shader_manager_->render_alpha_map_shader( - direct_3d_->get_device_context(), - object->get_model()->GetIndexCount(), - worldMatrix, - view, - projection, - object->get_model()->GetTexture(TextureType::Diffuse,0), - object->get_model()->GetTexture(TextureType::Diffuse,1), - object->get_model()->GetTexture(TextureType::Alpha,0) - ); - if (!result) - { - Logger::Get().Log("Could not render the model using the alpha map shader", __FILE__, __LINE__, Logger::LogLevel::Error); - direct_3d_->disable_alpha_blending(); - return false; - } - direct_3d_->disable_alpha_blending(); - break; - - case ShaderType::CEL_SHADING: - result = shader_manager_->render_cel_shading_shader( - direct_3d_->get_device_context(), - object->get_model()->GetIndexCount(), - worldMatrix, - view, - projection, - object->get_model()->GetTexture(TextureType::Diffuse,0), - sun_light_->GetDiffuseColor(), - sun_light_->GetAmbientColor(), - sun_light_->GetDirection(), - sun_light_->GetIntensity() - ); - if (!result) - { - Logger::Get().Log("Could not render the model using the cel shader", __FILE__, __LINE__, Logger::LogLevel::Error); - return false; - } - break; - - case ShaderType::NORMAL_MAPPING: - result = shader_manager_->render_normal_map_shader( - direct_3d_->get_device_context(), - object->get_model()->GetIndexCount(), - worldMatrix, - view, - projection, - object->get_model()->GetTexture(TextureType::Diffuse,0), - object->get_model()->GetTexture(TextureType::Normal,0), - lights_[0]->GetDirection(), - lights_[0]->GetDiffuseColor() - ); - if (!result) - { - Logger::Get().Log("Could not render the model using the normal map shader", __FILE__, __LINE__, Logger::LogLevel::Error); - return false; - } - break; - - case ShaderType::SPECULAR_MAPPING: - result = shader_manager_->render_spec_map_shader( - direct_3d_->get_device_context(), - object->get_model()->GetIndexCount(), - worldMatrix, - view, - projection, - object->get_model()->GetTexture(TextureType::Diffuse,0), - object->get_model()->GetTexture(TextureType::Normal,0), - object->get_model()->GetTexture(TextureType::Specular,0), - lights_[0]->GetDirection(), - lights_[0]->GetDiffuseColor(), - camera_->get_position(), - lights_[0]->GetSpecularColor(), - lights_[0]->GetSpecularPower() - ); - if (!result) - { - Logger::Get().Log("Could not render the model using the specular map shader", __FILE__, __LINE__, Logger::LogLevel::Error); - return false; - } - break; - - case ShaderType::TEXTURE: - result = shader_manager_->render_texture_shader( - direct_3d_->get_device_context(), - object->get_model()->GetIndexCount(), - worldMatrix, - view, - projection, - object->get_model()->GetTexture(TextureType::Diffuse,0) - ); - if (!result) - { - Logger::Get().Log("Could not render the model using the texture shader", __FILE__, __LINE__, Logger::LogLevel::Error); - return false; - } - break; - - case ShaderType::LIGHTING: - result = shader_manager_->renderlight_shader( - direct_3d_->get_device_context(), - object->get_model()->GetIndexCount(), - worldMatrix, - view, - projection, - object->get_model()->GetTexture(TextureType::Diffuse,0), - diffuse, - position, - ambient - ); - if (!result) - { - Logger::Get().Log("Could not render the object model using the light shader", __FILE__, __LINE__, Logger::LogLevel::Error); - return false; - } - break; - - case ShaderType::SKYBOX: - result = shader_manager_->render_skybox_shader( - direct_3d_->get_device_context(), - object->get_model()->GetIndexCount(), - worldMatrix, - view, - projection, - object->get_model()->GetTexture(TextureType::Diffuse,0), - sun_light_->GetDiffuseColor(), - sun_light_->GetAmbientColor(), - sun_light_->GetDirection(), - sun_light_->GetIntensity() - ); - if (!result) - { - Logger::Get().Log("Could not render the object model using the skybox shader", __FILE__, __LINE__, Logger::LogLevel::Error); - return false; - } - break; - - case ShaderType::SUNLIGHT: - result = shader_manager_->render_sunlight_shader( - direct_3d_->get_device_context(), - object->get_model()->GetIndexCount(), - worldMatrix, - view, - projection, - object->get_model()->GetTexture(TextureType::Diffuse,0), - sun_light_->GetDiffuseColor(), - sun_light_->GetAmbientColor(), - sun_light_->GetDirection(), - sun_light_->GetIntensity() - //shadow_map_srv_ - ); - if (!result) - { - Logger::Get().Log("Could not render the object model using the sunlight shader", __FILE__, __LINE__, Logger::LogLevel::Error); - return false; - } - break; - default: - result = shader_manager_->renderlight_shader( - direct_3d_->get_device_context(), - object->get_model()->GetIndexCount(), - worldMatrix, - view, - projection, - object->get_model()->GetTexture(TextureType::Diffuse,0), - diffuse, - position, - ambient - ); - if (!result) - { - Logger::Get().Log("Could not render the object model using the light shader", __FILE__, __LINE__, Logger::LogLevel::Error); - return false; - } - break; - } - - stats_->increment_draw_call_count(); - } - - if (isSkybox) - { - direct_3d_->turn_z_buffer_on(); - } - } - // if (active_camera_ == sun_camera_) // { // direct_3d_->set_back_buffer_render_target(); @@ -2161,29 +1993,57 @@ bool application_class::create_big_cube(int side_count) sharedModel = newModel; } - // Créer temporairement les cubes dans un vecteur local - std::vector tempCubes; - tempCubes.reserve(side_count * side_count * side_count); - - // Générer side_count³ cubes - for (int x = 0; x < side_count; x++) - { - for (int y = 0; y < side_count; y++) - { - for (int z = 0; z < side_count; z++) - { - object* cubePart = new object(*this); - cubePart->SetModel(sharedModel); - cubePart->SetTranslateMatrix(XMMatrixTranslation(static_cast(x),static_cast(y),static_cast(z))); - tempCubes.push_back(cubePart); + // Version ECS - Créer les entités pour le cube + if (entity_manager_) { + for (int x = 0; x < side_count; x++) { + for (int y = 0; y < side_count; y++) { + for (int z = 0; z < side_count; z++) { + // Créer une entité + auto entity = entity_manager_->CreateEntity(); + + // Ajouter un composant d'identité + auto identity = entity->AddComponent(object_id_++); + identity->SetName("CubePart_" + std::to_string(x) + "_" + std::to_string(y) + "_" + std::to_string(z)); + identity->SetType(ecs::ObjectType::Cube); + + // Ajouter un composant de transformation + auto transform = entity->AddComponent(); + transform->SetPosition(XMVectorSet(static_cast(x), static_cast(y), static_cast(z), 0.0f)); + transform->SetScale(XMVectorSet(1.0f, 1.0f, 1.0f, 0.0f)); + transform->UpdateWorldMatrix(); + + // Ajouter un composant de rendu + auto render = entity->AddComponent(); + render->InitializeWithModel(sharedModel); + + // Ajouter un composant de shader + auto shader = entity->AddComponent(); + shader->SetActiveShader(ecs::ShaderType::LIGHTING); + } } } - } - // Transférer les cubes du vecteur temporaire au vecteur membre - cubes_ = std::move(tempCubes); + } else { + // Ancien système - Créer temporairement les cubes dans un vecteur local + std::vector tempCubes; + tempCubes.reserve(side_count * side_count * side_count); - update_stats_after_modification(); - + // Générer side_count³ cubes + for (int x = 0; x < side_count; x++) { + for (int y = 0; y < side_count; y++) { + for (int z = 0; z < side_count; z++) { + object* cubePart = new object(*this); + cubePart->SetModel(sharedModel); + cubePart->SetTranslateMatrix(XMMatrixTranslation(static_cast(x), static_cast(y), static_cast(z))); + tempCubes.push_back(cubePart); + } + } + } + // Transférer les cubes du vecteur temporaire au vecteur membre + cubes_ = std::move(tempCubes); + } + + update_stats_after_modification(); + return true; }