# Khaotic Engine Reborn: enginecustom/src/src/system/application_class.cpp Source File

Loading...
Searching...
No Matches
application_class.cpp
#include "application_class.h"
#include "depth_shader_class.h"
#include "system_class.h"
application_class::application_class() : should_quit_(false)
{
direct_3d_ = nullptr;
camera_ = nullptr;
model_ = nullptr;
bitmap_ = nullptr;
sprite_ = nullptr;
timer_ = nullptr;
mouse_strings_ = nullptr;
font_shader_ = nullptr;
font_ = nullptr;
fps_ = nullptr;
fps_string_ = nullptr;
shader_manager_ = nullptr;
render_count_string_ = nullptr;
model_list_ = nullptr;
position_ = nullptr;
display_plane_ = nullptr;
bath_model_ = nullptr;
water_model_ = nullptr;
m_light_ = nullptr;
refraction_texture_ = nullptr;
reflection_texture_ = nullptr;
scene_texture_ = nullptr;
physics_ = nullptr;
skybox_.clear();
lights_.clear();
sun_light_ = nullptr;
swap_chain_ = nullptr;
ground_model_ = nullptr;
wall_model_ = nullptr;
hwnd_ = nullptr;
base_view_matrix_ = XMMatrixIdentity();
render_texture_ = nullptr;
screen_width_ = 0;
screen_height_ = 0;
num_lights_ = 0;
water_height_ = 0.0f;
water_translation_ = 0.0f;
true_light_position_ = XMFLOAT3(0.0f, 0.0f, 0.0f);
light_model_ = nullptr;
render_count_ = 0;
tab_was_pressed_ = false;
}
application_class::~application_class()
{
should_quit_ = true;
culling_active_ = false;
// Joindre les threads pour s'assurer qu'ils se terminent correctement
if (physics_thread_.joinable())
{
physics_thread_.join();
}
if (culling_thread_.joinable())
{
culling_thread_.join();
}
}
bool application_class::initialize(int screenWidth, int screenHeight, HWND hwnd, bool is_vulkan)
{
Logger::Get().Log("Initializing application class", __FILE__, __LINE__, Logger::LogLevel::Initialize);
try
{
char mouseString1[32], mouseString2[32], mouseString3[32];
char modelFilename[128], renderString[32];
char bitmapFilename[128];
char spriteFilename[128];
char fpsString[32];
bool result;
HRESULT Hresult;
// create entity manager
entity_manager_ = std::make_unique<ecs::EntityManager>();
screen_width_ = screenWidth;
screen_height_ = screenHeight;
set_hwnd(hwnd);
set_windowed(full_screen);
set_screen_height(screenHeight);
set_screen_width(screenWidth);
// Create the Direct3D object.
direct_3d_ = new d_3d_class;
if (!direct_3d_)
{
Logger::Get().Log("Could not create the Direct3D object", __FILE__, __LINE__, Logger::LogLevel::Error);
return false;
}
result = direct_3d_->initialize(screen_width_, screen_height_, vsync_enabled_, hwnd, full_screen, screen_depth, screen_near);
if (!result)
{
Logger::Get().Log("Could not initialize Direct3D", __FILE__, __LINE__, Logger::LogLevel::Error);
return false;
}
// Create the camera object.
camera_ = new camera_class;
if (!camera_)
{
Logger::Get().Log("Could not create the camera object", __FILE__, __LINE__, Logger::LogLevel::Error);
return false;
}
sun_camera_ = new camera_class;
if (!sun_camera_)
{
Logger::Get().Log("Could not create the sun camera object", __FILE__, __LINE__, Logger::LogLevel::Error);
return false;
}
sun_camera_->set_position(0.0f,0.0f,0.0f);
sun_camera_->set_rotation(0.0f, 0.0f, 0.0f);
sun_camera_->render();
sun_camera_->get_view_matrix(base_view_matrix_);
// Set the initial position of the camera.
camera_->set_position(0.0f, 0.0f, -12.0f);
camera_->set_rotation(0.0f, 0.0f, 0.0f);
camera_->render();
camera_->get_view_matrix(base_view_matrix_);
active_camera_ = camera_;
// Create and initialize the font shader object.
font_shader_ = new font_shader_class;
result = font_shader_->initialize(direct_3d_->get_device(), hwnd);
if (!result)
{
Logger::Get().Log("Could not initialize the font shader object", __FILE__, __LINE__, Logger::LogLevel::Error);
return false;
}
// Create and initialize the font object.
font_ = new font_class;
result = font_->Initialize(direct_3d_->get_device(), direct_3d_->get_device_context(), 0);
if (!result)
{
Logger::Get().Log("Could not initialize the font object", __FILE__, __LINE__, Logger::LogLevel::Error);
return false;
}
// Create and initialize the render to texture object.
render_texture_ = new render_texture_class;
result = render_texture_->Initialize(direct_3d_->get_device(), 256, 256, screen_depth, screen_near, 1);
if (!result)
{
Logger::Get().Log("Could not initialize the render texture object", __FILE__, __LINE__, Logger::LogLevel::Error);
return false;
}
//ImVec2 availableSize = ImGui::GetContentRegionAvail();
// Create and initialize the scene render to texture object.
scene_texture_ = new render_texture_class();
result = scene_texture_->Initialize(direct_3d_->get_device(), 256, 256, screen_depth, screen_near, 1);
if (!result)
{
Logger::Get().Log("Could not initialize the render texture object", __FILE__, __LINE__, Logger::LogLevel::Error);
return false;
}
// Create and initialize the display plane object.
display_plane_ = new display_plane_class;
result = display_plane_->Initialize(direct_3d_->get_device(), 1.0f, 1.0f);
if (!result)
{
Logger::Get().Log("Could not initialize the display plane object", __FILE__, __LINE__, Logger::LogLevel::Error);
return false;
}
// Set the sprite info file we will be using.
//
strcpy_s(spriteFilename, "sprite_data_01.txt");
// Create and initialize the sprite object.
sprite_ = new sprite_class;
result = sprite_->Initialize(direct_3d_->get_device(), direct_3d_->get_device_context(), screenWidth, screenHeight, spriteFilename, 50, 50);
if (!result)
{
Logger::Get().Log("Could not initialize the sprite object", __FILE__, __LINE__, Logger::LogLevel::Error);
return false;
}
// Set the initial mouse strings.
strcpy_s(mouseString1, "Mouse X: 0");
strcpy_s(mouseString2, "Mouse Y: 0");
strcpy_s(mouseString3, "Mouse Button: No");
// Create and initialize the text objects for the mouse strings.
mouse_strings_ = new text_class[3];
for (int i = 0; i < 3; i++)
{
int y = 10 + (i * 25);
result = mouse_strings_[i].Initialize(direct_3d_->get_device(), direct_3d_->get_device_context(), screenWidth, screenHeight, 32, font_, mouseString1, 10, y, 1.0f, 1.0f, 1.0f);
if (!result)
{
Logger::Get().Log("Could not initialize the mouse strings", __FILE__, __LINE__, Logger::LogLevel::Error);
return false;
}
}
// Set the file name of the bitmap file.
strcpy_s(bitmapFilename, "assets/Texture/stone01.tga");
// Create and initialize the bitmap object.
bitmap_ = new bitmap_class;
result = bitmap_->initialize(direct_3d_->get_device(), direct_3d_->get_device_context(), screenWidth, screenHeight, bitmapFilename, 50, 50);
if (!result)
{
Logger::Get().Log("Could not initialize the bitmap object", __FILE__, __LINE__, Logger::LogLevel::Error);
return false;
}
// Set the file name of the model.
strcpy_s(modelFilename, "assets/Model/TXT/cube.txt");
// Charger les textures_
std::vector<std::wstring> textureFilenames = {
L"assets/Texture/stone01.png"
};
TextureContainer CubeTextures;
for (const auto& textureFilename : textureFilenames)
{
ID3D11ShaderResourceView* texture = nullptr;
Hresult = DirectX::CreateWICTextureFromFile(direct_3d_->get_device(), direct_3d_->get_device_context(), textureFilename.c_str(), nullptr, &texture);
if (FAILED(Hresult))
{
Logger::Get().Log("Failed to load texture: " + std::string(textureFilename.begin(), textureFilename.end()), __FILE__, __LINE__, Logger::LogLevel::Error);
return false;
}
CubeTextures.diffuse.push_back(texture);
}
// Create and initialize the model object.
model_ = new model_class;
result = model_->Initialize(direct_3d_->get_device(), direct_3d_->get_device_context(), modelFilename, CubeTextures);
if (!result)
{
Logger::Get().Log("Could not initialize the model object", __FILE__, __LINE__, Logger::LogLevel::Error);
return false;
}
// Create and initialize the light object.
m_light_ = new light_class;
m_light_->SetDiffuseColor(1.0f, 1.0f, 1.0f, 1.0f);
m_light_->SetDirection(0.0f, 0.0f, -1.0f);
m_light_->SetAmbientColor(0.15f, 0.15f, 0.15f, 1.0f);
m_light_->SetSpecularColor(1.0f, 1.0f, 1.0f, 1.0f);
m_light_->SetSpecularPower(16.0f);
// Set the number of lights we will use.
num_lights_ = 4;
// Create and initialize the light objects array.
lights_.resize(num_lights_);
lights_[0] = new light_class;
lights_[0]->SetDiffuseColor(1.0f, 1.0f, 1.0f, 1.0f); // White
lights_[0]->SetDirection(0.0f, 0.0f, -1.0f);
lights_[0]->SetAmbientColor(0.15f, 0.15f, 0.15f, 1.0f);
lights_[0]->SetSpecularColor(1.0f, 1.0f, 1.0f, 1.0f);
lights_[0]->SetSpecularPower(16.0f);
lights_[0]->SetPosition(10.0f, 7.0f, -5.0f);
lights_[1] = new light_class;
lights_[1]->SetDiffuseColor(1.0f, 0.0f, 0.0f, 1.0f); // Red
lights_[1]->SetDirection(0.0f, 0.0f, -1.0f);
lights_[1]->SetAmbientColor(0.15f, 0.15f, 0.15f, 1.0f);
lights_[1]->SetSpecularColor(1.0f, 0.0f, 0.0f, 1.0f);
lights_[1]->SetSpecularPower(16.0f);
lights_[1]->SetPosition(-10.0f, 7.0f, -5.0f);
lights_[2] = new light_class;
lights_[2]->SetDiffuseColor(0.0f, 1.0f, 0.0f, 1.0f); // Green
lights_[2]->SetDirection(0.0f, 0.0f, -1.0f);
lights_[2]->SetAmbientColor(0.15f, 0.15f, 0.15f, 1.0f);
lights_[2]->SetSpecularColor(0.0f, 1.0f, 0.0f, 1.0f);
lights_[2]->SetSpecularPower(16.0f);
lights_[2]->SetPosition(10.0f, 7.0f, 5.0f);
lights_[3] = new light_class;
lights_[3]->SetDiffuseColor(0.0f, 0.0f, 1.0f, 1.0f); // Blue
lights_[3]->SetDirection(0.0f, 0.0f, -1.0f);
lights_[3]->SetAmbientColor(0.15f, 0.15f, 0.15f, 1.0f);
lights_[3]->SetSpecularColor(0.0f, 0.0f, 1.0f, 1.0f);
lights_[3]->SetSpecularPower(16.0f);
lights_[3]->SetPosition(-10.0f, 7.0f, 5.0f);
// ------------------------------------------------------------- //
// ----------------------- || THE SUN || ----------------------- //
// ------------------------------------------------------------- //
sun_light_ = new light_class;
sun_light_->SetDiffuseColor(1.0f, 1.0f, 1.0f, 1.0f); // White
sun_light_->SetDirection(0.0f, -1.0f, 0.0f);
sun_light_->SetAmbientColor(0.15f, 0.15f, 0.15f, 1.0f);
sun_light_->SetPosition(0.0f, 100.0f, 0.0f);
sun_light_->SetIntensity(1.0f);
sun_camera_->set_position(sun_light_->GetPosition().x, sun_light_->GetPosition().y, sun_light_->GetPosition().z);
sun_camera_->set_rotation(0.0f, 0.0f, 0.0f);
sun_camera_->render();
// Create and initialize the normal map shader object.
shader_manager_ = new shader_manager_class;
result = shader_manager_->initialize(direct_3d_->get_device(), hwnd);
if (!result)
{
Logger::Get().Log("Could not initialize the shader manager object", __FILE__, __LINE__, Logger::LogLevel::Error);
return false;
}
// Set the initial render count string.
strcpy_s(renderString, "render Count: 0");
// Create and initialize the text object for the render count string.
render_count_string_ = new text_class;
result = render_count_string_->Initialize(direct_3d_->get_device(), direct_3d_->get_device_context(), screenWidth, screenHeight, 32, font_, renderString, 10, 10, 1.0f, 1.0f, 1.0f);
if (!result)
{
Logger::Get().Log("Could not initialize the render count string", __FILE__, __LINE__, Logger::LogLevel::Error);
return false;
}
// Create and initialize the model list object.
model_list_ = new ModelListClass;
model_list_->Initialize(25);
// Charger les textures_ initiales pour bath_model_
std::vector<std::wstring> bathTextures = {
L"assets/Texture/marble01.png"
};
TextureContainer BathTextures;
textures.clear();
for (const auto& textureFilename : bathTextures)
{
ID3D11ShaderResourceView* texture = nullptr;
Hresult = DirectX::CreateWICTextureFromFile(direct_3d_->get_device(), direct_3d_->get_device_context(), textureFilename.c_str(), nullptr, &texture);
if (FAILED(Hresult))
{
Logger::Get().Log("Failed to load texture: " + std::string(textureFilename.begin(), textureFilename.end()), __FILE__, __LINE__, Logger::LogLevel::Error);
return false;
}
BathTextures.diffuse.push_back(texture);
}
// Set the file name of the bath model.
strcpy_s(modelFilename, "assets/Model/TXT/bath.txt");
// Create and initialize the bath model object.
bath_model_ = new model_class;
result = bath_model_->Initialize(direct_3d_->get_device(), direct_3d_->get_device_context(), modelFilename, BathTextures);
if (!result)
{
MessageBox(hwnd, L"Could not initialize the bath model object.", L"Error", MB_OK);
return false;
}
// Set the file names of the water model.
strcpy_s(modelFilename, "assets/Model/TXT/water.txt");
// replace first element with the new filename
std::vector<std::wstring> waterTextures = {
L"assets/Texture/water01.png"
};
TextureContainer WaterTextures;
textures.clear();
for (const auto& textureFilename : waterTextures)
{
ID3D11ShaderResourceView* texture = nullptr;
Hresult = DirectX::CreateWICTextureFromFile(direct_3d_->get_device(), direct_3d_->get_device_context(), textureFilename.c_str(), nullptr, &texture);
if (FAILED(Hresult))
{
Logger::Get().Log("Failed to load texture: " + std::string(textureFilename.begin(), textureFilename.end()), __FILE__, __LINE__, Logger::LogLevel::Error);
return false;
}
WaterTextures.diffuse.push_back(texture);
}
// Create and initialize the water model object.
water_model_ = new model_class;
result = water_model_->Initialize(direct_3d_->get_device(), direct_3d_->get_device_context(), modelFilename, WaterTextures);
if (!result)
{
MessageBox(hwnd, L"Could not initialize the water model object.", L"Error", MB_OK);
return false;
}
// Create and initialize the refraction render to texture object.
refraction_texture_ = new render_texture_class;
result = refraction_texture_->Initialize(direct_3d_->get_device(), screenWidth, screenHeight, screen_depth, screen_near, 1);
if (!result)
{
MessageBox(hwnd, L"Could not initialize the refraction render texture object.", L"Error", MB_OK);
return false;
}
// Create and initialize the reflection render to texture object.
reflection_texture_ = new render_texture_class;
result = reflection_texture_->Initialize(direct_3d_->get_device(), screenWidth, screenHeight, screen_depth, screen_near, 1);
if (!result)
{
MessageBox(hwnd, L"Could not initialize the reflection render texture object.", L"Error", MB_OK);
return false;
}
// Set the height of the water.
water_height_ = -9.25f;
// initialize the position of the water.
water_translation_ = 100.0f;
// Create and initialize the timer object.
timer_ = new timer_class;
result = timer_->Initialize();
if (!result)
{
Logger::Get().Log("Could not initialize the timer object", __FILE__, __LINE__, Logger::LogLevel::Error);
return false;
}
// Create the position class object.
position_ = new position_class;
// Create and initialize the fps object.
fps_ = new fps_class();
fps_->Initialize();
// Set the initial fps and fps string.
previous_fps_ = -1;
strcpy_s(fpsString, "Fps: 0");
// Create and initialize the text object for the fps string.
fps_string_ = new text_class;
result = fps_string_->Initialize(direct_3d_->get_device(), direct_3d_->get_device_context(), screenWidth, screenHeight, 32, font_, fpsString, 10, 10, 0.0f, 1.0f, 0.0f);
if (!result)
{
Logger::Get().Log("Could not initialize the fps string", __FILE__, __LINE__, Logger::LogLevel::Error);
return false;
}
shadow_map_ = new shadow_map();
if (!shadow_map_->initialize(direct_3d_->get_device(), 2048, 2048))
{
Logger::Get().Log("Could not initialize the shadow map object", __FILE__, __LINE__, Logger::LogLevel::Error);
return false;
}
stats_ = new stats();
if (!stats_->initialize(this))
{
Logger::Get().Log("Could not initialize the stats object", __FILE__, __LINE__, Logger::LogLevel::Error);
return false;
}
physics_ = new physics;
physics_thread_ = std::thread(&application_class::physics_thread_function, this);
//ConstructSkyboxWithPlanes();
Skybox* skybox = new Skybox;
skybox->Initialize(direct_3d_);
skybox_.push_back(skybox->ConstructSkybox(this));
culling_active_ = true;
culling_thread_ = std::thread(&application_class::culling_thread_function, this);
}
catch (const std::exception& e)
{
Logger::Get().Log(std::string("Exception caught during initialization: ") + e.what(), __FILE__, __LINE__, Logger::LogLevel::Error);
return false;
}
Logger::Get().Log("Application class initialized", __FILE__, __LINE__, Logger::LogLevel::Initialize);
return true;
}
void application_class::shutdown()
{
Logger::Get().Log("Shutting down application class", __FILE__, __LINE__, Logger::LogLevel::Shutdown);
// Release the shader manager object.
if (shader_manager_)
{
Logger::Get().Log("Releasing the shader manager object", __FILE__, __LINE__, Logger::LogLevel::Shutdown);
shader_manager_->shutdown();
delete shader_manager_;
shader_manager_ = 0;
Logger::Get().Log("Shader manager object released", __FILE__, __LINE__, Logger::LogLevel::Shutdown);
}
// Release the reflection render texture object.
if (reflection_texture_)
{
reflection_texture_->Shutdown();
delete reflection_texture_;
reflection_texture_ = 0;
}
// Release the refraction render texture object.
if (refraction_texture_)
{
refraction_texture_->Shutdown();
delete refraction_texture_;
refraction_texture_ = 0;
}
// Release the water model object.
if (water_model_)
{
water_model_->Shutdown();
delete water_model_;
water_model_ = 0;
}
// Release the bath model object.
if (bath_model_)
{
bath_model_->Shutdown();
delete bath_model_;
bath_model_ = 0;
}
// Release the physics object.
if (physics_)
{
delete physics_;
physics_ = 0;
}
// Release the display plane object.
if (display_plane_)
{
Logger::Get().Log("Releasing the display plane object", __FILE__, __LINE__, Logger::LogLevel::Shutdown);
display_plane_->Shutdown();
delete display_plane_;
display_plane_ = 0;
Logger::Get().Log("Display plane object released", __FILE__, __LINE__, Logger::LogLevel::Shutdown);
}
// Release the position object.
if (position_)
{
Logger::Get().Log("Releasing the position object", __FILE__, __LINE__, Logger::LogLevel::Shutdown);
delete position_;
position_ = 0;
Logger::Get().Log("Position object released", __FILE__, __LINE__, Logger::LogLevel::Shutdown);
}
// Release the model list object.
if (model_list_)
{
Logger::Get().Log("Releasing the model list object", __FILE__, __LINE__, Logger::LogLevel::Shutdown);
model_list_->Shutdown();
delete model_list_;
model_list_ = 0;
Logger::Get().Log("Model list object released", __FILE__, __LINE__, Logger::LogLevel::Shutdown);
}
// Release the text objects for the render count string.
if (render_count_string_)
{
Logger::Get().Log("Releasing the render count string object", __FILE__, __LINE__, Logger::LogLevel::Shutdown);
render_count_string_->Shutdown();
delete render_count_string_;
render_count_string_ = 0;
Logger::Get().Log("render count string object released", __FILE__, __LINE__, Logger::LogLevel::Shutdown);
}
// Release the text objects for the mouse strings.
if (mouse_strings_)
{
Logger::Get().Log("Releasing the mouse strings", __FILE__, __LINE__, Logger::LogLevel::Shutdown);
mouse_strings_[0].Shutdown();
mouse_strings_[1].Shutdown();
mouse_strings_[2].Shutdown();
delete[] mouse_strings_;
mouse_strings_ = 0;
Logger::Get().Log("Mouse strings released", __FILE__, __LINE__, Logger::LogLevel::Shutdown);
}
// Release the text object for the fps string.
if (fps_string_)
{
Logger::Get().Log("Releasing the fps string object", __FILE__, __LINE__, Logger::LogLevel::Shutdown);
fps_string_->Shutdown();
delete fps_string_;
fps_string_ = 0;
Logger::Get().Log("Fps string object released", __FILE__, __LINE__, Logger::LogLevel::Shutdown);
}
// Release the fps object.
if (fps_)
{
Logger::Get().Log("Releasing the fps object", __FILE__, __LINE__, Logger::LogLevel::Shutdown);
delete fps_;
fps_ = 0;
Logger::Get().Log("Fps object released", __FILE__, __LINE__, Logger::LogLevel::Shutdown);
}
// Release the font object.
if (font_)
{
Logger::Get().Log("Releasing the font object", __FILE__, __LINE__, Logger::LogLevel::Shutdown);
font_->Shutdown();
delete font_;
font_ = 0;
Logger::Get().Log("Font object released", __FILE__, __LINE__, Logger::LogLevel::Shutdown);
}
// Release the font shader object.
if (font_shader_)
{
Logger::Get().Log("Releasing the font shader object", __FILE__, __LINE__, Logger::LogLevel::Shutdown);
font_shader_->shutdown();
delete font_shader_;
font_shader_ = 0;
Logger::Get().Log("Font shader object released", __FILE__, __LINE__, Logger::LogLevel::Shutdown);
}
// Release the timer object.
if (timer_)
{
Logger::Get().Log("Releasing the timer object", __FILE__, __LINE__, Logger::LogLevel::Shutdown);
delete timer_;
timer_ = 0;
Logger::Get().Log("Timer object released", __FILE__, __LINE__, Logger::LogLevel::Shutdown);
}
// Release the sprite object.
if (sprite_)
{
Logger::Get().Log("Releasing the sprite object", __FILE__, __LINE__, Logger::LogLevel::Shutdown);
sprite_->Shutdown();
delete sprite_;
sprite_ = 0;
Logger::Get().Log("Sprite object released", __FILE__, __LINE__, Logger::LogLevel::Shutdown);
}
for (auto light : lights_)
{
Logger::Get().Log("Releasing the light object", __FILE__, __LINE__, Logger::LogLevel::Shutdown);
if (light)
{
delete light;
light = 0;
}
Logger::Get().Log("Light object released", __FILE__, __LINE__, Logger::LogLevel::Shutdown);
}
// Release the light object.
if (m_light_)
{
Logger::Get().Log("Releasing the light object", __FILE__, __LINE__, Logger::LogLevel::Shutdown);
delete m_light_;
m_light_ = 0;
Logger::Get().Log("Light object released", __FILE__, __LINE__, Logger::LogLevel::Shutdown);
}
// Release the model object.
if (model_)
{
Logger::Get().Log("Releasing the model object", __FILE__, __LINE__, Logger::LogLevel::Shutdown);
model_->Shutdown();
delete model_;
model_ = 0;
Logger::Get().Log("Model object released", __FILE__, __LINE__, Logger::LogLevel::Shutdown);
}
if (scene_texture_)
{
scene_texture_->Shutdown();
delete scene_texture_;
scene_texture_ = nullptr;
}
if (sun_camera_)
{
Logger::Get().Log("Releasing the sun camera object", __FILE__, __LINE__, Logger::LogLevel::Shutdown);
delete sun_camera_;
sun_camera_ = nullptr;
Logger::Get().Log("Sun camera object released", __FILE__, __LINE__, Logger::LogLevel::Shutdown);
}
if (shadow_map_) {
shadow_map_->shutdown();
delete shadow_map_;
shadow_map_ = nullptr;
}
Logger::Get().Log("Application class shut down", __FILE__, __LINE__, Logger::LogLevel::Shutdown);
}
bool application_class::frame(input_class* Input)
{
stats_->reset_draw_call_count();
int mouseX, mouseY, currentMouseX, currentMouseY;
bool result, leftMouseDown, rightMouseDown, buttonQ, buttonD, buttonZ, buttonS, buttonA, buttonE, scrollUp, scrollDown;
float rotationY, rotationX, positionX, positionY, positionZ;
static float textureTranslation = 0.0f;
float frameTime;
static int lastMouseX = 0, lastMouseY = 0;
static float rotation = 360.0f;
static float x = 0.0f;
static float y = 3.0f;
static float z = 0.0f;
// Update the system stats.
timer_->Frame();
// Get the current frame time.
frameTime = timer_->GetTime();
// Check if the user pressed escape and wants to exit the application.
if (Input->IsEscapePressed())
{
Logger::Get().Log("User pressed escape, exiting application", __FILE__, __LINE__, Logger::LogLevel::Input);
should_quit_ = true;
}
// Get the location of the mouse from the input object,
Input->GetMouseLocation(mouseX, mouseY);
// Check if the mouse has been pressed.
leftMouseDown = Input->IsLeftMousePressed();
rightMouseDown = Input->IsRightMousePressed();
currentMouseX = mouseX;
int deltaX = currentMouseX - lastMouseX; // Calculate the mouse movement.
lastMouseX = currentMouseX; // Update the last mouse position for the next frame
currentMouseY = mouseY;
int deltaY = currentMouseY - lastMouseY; // Calculate the mouse movement.
lastMouseY = currentMouseY; // Update the last mouse position for the next frame
// Set the frame time for calculating the updated position.
position_->SetFrameTime(timer_->GetTime());
position_->TurnMouse((float)deltaX, (float)deltaY, 0.1f, rightMouseDown);
// Get the current view point rotation.
position_->GetRotation(rotationY, rotationX);
scrollUp = Input->IsScrollUp();
scrollDown = Input->IsScrollDown();
// Check if the a(q), d, w(z), s, q(a), e have been pressed, if so move the camera accordingly.
buttonQ = Input->IsAPressed();
buttonD = Input->IsDPressed();
buttonZ = Input->IsWPressed();
buttonS = Input->IsSPressed();
buttonA = Input->IsQPressed();
buttonE = Input->IsEPressed();
position_->MoveCamera(buttonZ, buttonS, buttonQ, buttonD, buttonE, buttonA, scrollUp, scrollDown, rightMouseDown);
position_->GetPosition(positionX, positionY, positionZ);
XMFLOAT3 dir = sun_light_->GetDirection();
float pitch = asinf(-dir.y) * (180.0f / XM_PI); // en degrés
float yaw = atan2f(dir.x, dir.z) * (180.0f / XM_PI); // en degrés
float roll = 0.0f;
if (Input->is_key_pressed(DIK_TAB)) {
if (!tab_was_pressed_) {
// Alterner la caméra active
if (active_camera_ == camera_)
active_camera_ = sun_camera_;
else
active_camera_ = camera_;
tab_was_pressed_ = true;
}
} else {
tab_was_pressed_ = false;
}
if (active_camera_ == camera_) {
// Update the camera position and rotation based on the position class.
camera_->set_position(positionX, positionY, positionZ);
camera_->set_rotation(rotationX, rotationY, 0.0f);
} else {
// Update the sun camera position and rotation based on the light position.
sun_camera_->set_position(sun_light_->GetPosition().x, sun_light_->GetPosition().y, sun_light_->GetPosition().z);
sun_camera_->set_rotation(pitch, yaw, roll);
// sun_camera_->set_position(positionX, positionY, positionZ);
// sun_camera_->set_rotation(rotationX, rotationY, 0.0f);
}
active_camera_->render();
// render the static graphics scene.
result = render(rotation, x, y, z, textureTranslation);
if (!result)
{
Logger::Get().Log("Could not render the graphics scene", __FILE__, __LINE__, Logger::LogLevel::Error);
return false;
}
// Update the frames per second each frame.
result = update_fps();
if (!result)
{
Logger::Get().Log("Could not update the frames per second", __FILE__, __LINE__, Logger::LogLevel::Error);
return false;
}
// Update the rotation variable each frame.
rotation -= 0.0174532925f * speed_;
if (rotation < 0.0f)
{
rotation += 360.0f;
}
// Update the position of the water to simulate motion.
water_translation_ += 0.001f;
if (water_translation_ > 1.0f)
{
water_translation_ -= 1.0f;
}
// render the refraction of the scene to a texture.
result = render_refraction_to_texture();
if (!result)
{
return false;
}
// render the reflection of the scene to a texture.
result = render_reflection_to_texture();
if (!result)
{
return false;
}
inputs_.key_left = Input->IsLeftArrowPressed();
inputs_.key_right = Input->IsRightArrowPressed();
inputs_.key_up = Input->IsUpArrowPressed();
inputs_.key_down = Input->IsDownArrowPressed();
// render the scene to a render texture.
result = render_scene_to_texture(rotation);
if (!result)
{
Logger::Get().Log("Could not render the scene to the render texture", __FILE__, __LINE__, Logger::LogLevel::Error);
return false;
}
// Update the mouse strings each frame.
result = update_mouse_strings(mouseX, mouseY, leftMouseDown);
if (!result)
{
Logger::Get().Log("Could not update the mouse strings", __FILE__, __LINE__, Logger::LogLevel::Error);
return false;
}
// Update the sprite object using the frame time.
sprite_->Update(frameTime);
// Increment the texture translation.
textureTranslation += 0.01f;
if (textureTranslation > 1.0f)
{
textureTranslation -= 1.0f;
}
return true;
}
bool application_class::render_refraction_to_texture()
{
XMMATRIX worldMatrix, viewMatrix, projectionMatrix;
XMFLOAT4 diffuseColor[4], lightPosition[4], ambientColor[4];
XMFLOAT4 clipPlane;
int i;
bool result;
// Setup a clipping plane based on the height of the water to clip everything above it.
clipPlane = XMFLOAT4(0.0f, -1.0f, 0.0f, water_height_ + 0.1f);
// Set the render target to be the refraction render to texture and clear it.
refraction_texture_->SetRenderTarget(direct_3d_->get_device_context());
refraction_texture_->ClearRenderTarget(direct_3d_->get_device_context(), 0.0f, 0.0f, 0.0f, 1.0f);
// Generate the view matrix based on the camera's position.
camera_->render();
camera_->get_view_matrix(viewMatrix);
projectionMatrix = direct_3d_->get_projection_matrix();
// Get the light properties.
for (i = 0; i < num_lights_; i++)
{
// Create the diffuse color array from the four light colors.
diffuseColor[i] = lights_[i]->GetDiffuseColor();
// Create the light position array from the four light positions.
lightPosition[i] = lights_[i]->GetPosition();
// Create the light position array from the four light positions.
ambientColor[i] = lights_[i]->GetAmbientColor();
}
// Translate to where the bath model will be rendered.
worldMatrix = XMMatrixTranslation(0.0f, -10.0f, 0.0f);
// render the bath model using the refraction shader.
bath_model_->Render(direct_3d_->get_device_context());
result = shader_manager_->render_refraction_shader(direct_3d_->get_device_context(), bath_model_->GetIndexCount(), worldMatrix, viewMatrix, projectionMatrix,
bath_model_->GetTexture(TextureType::Diffuse,0), lights_[0]->GetDirection(), ambientColor, diffuseColor, lightPosition, clipPlane);
if (!result)
{
return false;
}
// Reset the render target back to the original back buffer and not the render to texture anymore. And reset the viewport back to the original.
direct_3d_->set_back_buffer_render_target();
direct_3d_->reset_viewport();
return true;
}
bool application_class::render_reflection_to_texture()
{
XMMATRIX reflectionViewMatrix;
// Set the render target to be the reflection render to texture and clear it.
reflection_texture_->SetRenderTarget(direct_3d_->get_device_context());
reflection_texture_->ClearRenderTarget(direct_3d_->get_device_context(), 0.0f, 0.0f, 0.0f, 1.0f);
// Use the camera to render the reflection and create a reflection view matrix.
camera_->render_reflection(water_height_);
// Get the camera reflection view matrix instead of the normal view matrix.
camera_->get_reflection_view_matrix(reflectionViewMatrix);
// Reset the render target back to the original back buffer and not the render to texture anymore. And reset the viewport back to the original.
direct_3d_->set_back_buffer_render_target();
direct_3d_->reset_viewport();
return true;
}
bool application_class::render_scene_to_texture(float rotation)
{
XMMATRIX worldMatrix, viewMatrix, projectionMatrix;
bool result;
// Set the render target to be the render texture and clear it.
render_texture_->SetRenderTarget(direct_3d_->get_device_context());
render_texture_->ClearRenderTarget(direct_3d_->get_device_context(), 0.0f, 0.5f, 1.0f, 1.0f);
// Set the position of the camera for viewing the cube.
camera_->render();
camera_->get_view_matrix(viewMatrix);
render_texture_->GetProjectionMatrix(projectionMatrix);
// Rotate the world matrix by the rotation value so that the cube will spin.
worldMatrix = XMMatrixRotationY(rotation);
// render the model using the texture shader.
model_->Render(direct_3d_->get_device_context());
result = shader_manager_->render_texture_shader(direct_3d_->get_device_context(), model_->GetIndexCount(), worldMatrix, viewMatrix, projectionMatrix,
model_->GetTexture(TextureType::Diffuse,0));
if (!result)
{
return false;
}
// Reset the render target back to the original back buffer and not the render to texture anymore. And reset the viewport back to the original.
direct_3d_->set_back_buffer_render_target();
direct_3d_->reset_viewport();
return true;
}
bool application_class::render(float rotation, float x, float y, float z, float textureTranslation)
{
XMMATRIX worldMatrix, viewMatrix, orthoMatrix, projectionMatrix, rotateMatrix, translateMatrix, scaleMatrix, srMatrix, reflectionMatrix;
XMFLOAT4 diffuseColor[4], lightPosition[4], ambientColor[4];
int i;
bool result;
float blendAmount;
// Set the blending amount to 10%.
blendAmount = 0.1f;
// Generate the view matrix based on the camera's position.
active_camera_->render();
// Get the world, view, and projection matrices from the camera and d3d objects.
worldMatrix = direct_3d_->get_world_matrix();
active_camera_->get_view_matrix(viewMatrix);
projectionMatrix = direct_3d_->get_projection_matrix();
orthoMatrix = direct_3d_->get_ortho_matrix();
//render Sky box
//RenderSkybox(viewMatrix, projectionMatrix);
// Get the light properties.
for (i = 0; i < num_lights_; i++)
{
// Create the diffuse color array from the four light colors.
diffuseColor[i] = lights_[i]->GetDiffuseColor();
// Create the light position array from the four light positions.
lightPosition[i] = lights_[i]->GetPosition();
// Create the light position array from the four light positions.
ambientColor[i] = lights_[i]->GetPosition();
}
// Redimensionner la texture de rendu si nécessaire
if (DEBUG_MODE)
{
if ((float)scene_texture_->GetTextureWidth() != window_size_.x || (float)scene_texture_->GetTextureHeight() != window_size_.y)
{
scene_texture_->Shutdown();
scene_texture_->Initialize(direct_3d_->get_device(), (int)window_size_.x, (int)window_size_.y, screen_depth, screen_near, 1);
}
direct_3d_->set_back_buffer_render_target();
direct_3d_->reset_viewport();
}
//scene_texture_->SetRenderTarget(direct_3d_->get_device_context());
//scene_texture_->ClearRenderTarget(direct_3d_->get_device_context(), 0.0f, 0.0f, 0.0f, 0.0f);
scaleMatrix = XMMatrixScaling(0.5f, 0.5f, 0.5f); // Build the scaling matrix.
rotateMatrix = XMMatrixRotationY(rotation); // Build the rotation matrix.
translateMatrix = XMMatrixTranslation(x, y, z); // Build the translation matrix.
// Multiply the scale, rotation, and translation matrices together to create the final world transformation matrix.
srMatrix = XMMatrixMultiply(scaleMatrix, rotateMatrix);
worldMatrix = XMMatrixMultiply(srMatrix, translateMatrix);
// Put the model vertex and index buffers on the graphics pipeline to prepare them for drawing.
model_->Render(direct_3d_->get_device_context());
// render the model using the light shader.
result = shader_manager_->renderlight_shader(direct_3d_->get_device_context(), model_->GetIndexCount(), worldMatrix, viewMatrix, projectionMatrix, model_->GetTexture(TextureType::Diffuse,0),
diffuseColor, lightPosition, ambientColor);
update_skybox_position(); // Update the position of the skybox to match the camera position.
direct_3d_->turn_z_buffer_on(); // Enable the Z buffer after rendering the skybox.
// -------------------------------------------------------- //
// ------------ render the object in the queue ------------ //
// -------------------------------------------------------- //
// set the active camera to the sun camera for rendering the shadow map.
// active_camera_ = sun_camera_;
// active_camera_->render();
// // Render the objects in the render queues. with depth only pass.
// active_camera_->get_view_matrix(viewMatrix);
result = render_pass(diffuseColor, lightPosition, ambientColor, viewMatrix, projectionMatrix);
if (!result)
{
Logger::Get().Log("Could not render the model using any shader", __FILE__, __LINE__, Logger::LogLevel::Error);
return false;
}
// Reset the active camera to the main camera.
// active_camera_ = camera_;
// active_camera_->render();
// active_camera_->get_view_matrix(viewMatrix);
//
// // render the objects in the render queues. with standard pass.
// result = render_pass(render_queues_, diffuseColor, lightPosition, ambientColor, viewMatrix, projectionMatrix);
// if (!result)
// {
// Logger::Get().Log("Could not render the model using any shader", __FILE__, __LINE__, Logger::LogLevel::Error);
// return false;
// }
// stats_->update_geometric_stats();
// Update the render count text.
result = update_render_count_string(get_render_count());
if (!result)
{
Logger::Get().Log("Could not update the render count string", __FILE__, __LINE__, Logger::LogLevel::Error);
return false;
}
// Translate to where the bath model will be rendered.
worldMatrix = XMMatrixTranslation(0.0f, -10.0f, 0.0f);
// Put the bath model vertex and index buffers on the graphics pipeline to prepare them for drawing.
bath_model_->Render(direct_3d_->get_device_context());
// render the bath model using the light shader.
result = shader_manager_->renderlight_shader(direct_3d_->get_device_context(), bath_model_->GetIndexCount(), worldMatrix, viewMatrix, projectionMatrix,
bath_model_->GetTexture(TextureType::Diffuse,0), diffuseColor, lightPosition, ambientColor);
if (!result)
{
return false;
}
// Reset the world matrix.
worldMatrix = direct_3d_->get_world_matrix();
// Get the camera reflection view matrix.
camera_->get_reflection_view_matrix(reflectionMatrix);
// Translate to where the water model will be rendered.
worldMatrix = XMMatrixTranslation(0.0f, water_height_, 0.0f);
// Put the water model vertex and index buffers on the graphics pipeline to prepare them for drawing.
water_model_->Render(direct_3d_->get_device_context());
// render the water model using the water shader.
result = shader_manager_->render_water_shader(direct_3d_->get_device_context(), water_model_->GetIndexCount(), worldMatrix, viewMatrix, projectionMatrix, reflectionMatrix,
reflection_texture_->GetShaderResourceView(), refraction_texture_->GetShaderResourceView(), water_model_->GetTexture(TextureType::Diffuse,0),
water_translation_, 0.01f);
if (!result)
{
return false;
}
// Disable the Z buffer and enable alpha blending for 2D rendering.
direct_3d_->turn_z_buffer_off();
direct_3d_->enable_alpha_blending();
// Reset the world matrix.
worldMatrix = direct_3d_->get_world_matrix();
// render the render count text string using the font shader.
render_count_string_->Render(direct_3d_->get_device_context());
result = font_shader_->render(direct_3d_->get_device_context(), render_count_string_->GetIndexCount(), worldMatrix, base_view_matrix_, orthoMatrix,
font_->GetTexture(), render_count_string_->GetPixelColor());
if (!result)
{
Logger::Get().Log("Could not render the render count text string using the font shader", __FILE__, __LINE__, Logger::LogLevel::Error);
return false;
}
// render the fps text string using the font shader.
fps_string_->Render(direct_3d_->get_device_context());
result = font_shader_->render(direct_3d_->get_device_context(), fps_string_->GetIndexCount(), worldMatrix, base_view_matrix_, orthoMatrix,
font_->GetTexture(), fps_string_->GetPixelColor());
if (!result)
{
Logger::Get().Log("Could not render the fps text string using the font shader", __FILE__, __LINE__, Logger::LogLevel::Error);
return false;
}
// render the mouse text strings using the font shader.
for (i = 0; i < 3; i++)
{
mouse_strings_[i].Render(direct_3d_->get_device_context());
result = font_shader_->render(direct_3d_->get_device_context(), mouse_strings_[i].GetIndexCount(), worldMatrix, base_view_matrix_, orthoMatrix,
font_->GetTexture(), mouse_strings_[i].GetPixelColor());
if (!result)
{
Logger::Get().Log("Could not render the mouse text strings using the font shader", __FILE__, __LINE__, Logger::LogLevel::Error);
return false;
}
}
// Put the sprite vertex and index buffers on the graphics pipeline to prepare them for drawing.
result = sprite_->Render(direct_3d_->get_device_context());
if (!result)
{
return false;
}
// render the sprite with the texture shader.
result = shader_manager_->render_texture_shader(direct_3d_->get_device_context(), model_->GetIndexCount(), worldMatrix, viewMatrix, orthoMatrix,
sprite_->GetTexture());
if (!result)
{
Logger::Get().Log("Could not render the sprite using the texture shader", __FILE__, __LINE__, Logger::LogLevel::Error);
return false;
}
// Turn off alpha blending after rendering the 2D text.
direct_3d_->disable_alpha_blending();
// turn on the Z buffer
direct_3d_->turn_z_buffer_on();
// Get the light properties.
for (i = 0; i < num_lights_; i++)
{
// Create the diffuse color array from the four light colors.
diffuseColor[i] = lights_[i]->GetDiffuseColor();
// Create the light position array from the four light positions.
lightPosition[i] = lights_[i]->GetPosition();
}
// Réinitialiser la cible de rendu au back buffer.
direct_3d_->set_back_buffer_render_target();
return true;
}
d_3d_class* application_class::get_direct_3d()
{
return direct_3d_;
}
int application_class::get_screen_width() const
{
return GetSystemMetrics(SM_CXSCREEN);
}
int application_class::get_screen_height() const
{
return GetSystemMetrics(SM_CYSCREEN);
}
void application_class::generate_terrain()
{
Logger::Get().Log("Génération du terrain avec ECS", __FILE__, __LINE__, Logger::LogLevel::Info);
// delete previous terrain if it exists
delete_terrain();
// Dimensions du terrain
float scaleX = 10.0f;
float scaleY = 1.0f;
float scaleZ = 10.0f;
int gridSizeX = 20;
int gridSizeZ = 20;
// Vérifier si le modèle existe déjà dans le cache
std::string modelName = "assets/Model/OBJ/plane.obj";
std::shared_ptr<model_class> sharedModel;
auto it = g_model_cache.find(modelName);
if (it != g_model_cache.end()) {
// Utiliser le modèle existant du cache
Logger::Get().Log("Using cached model for terrain: " + modelName, __FILE__, __LINE__);
sharedModel = it->second;
}
else {
// Créer un conteneur de textures partagé
TextureContainer textureContainer;
textureContainer.diffusePaths.push_back(L"assets/Texture/Bricks2K.png");
textureContainer.normalPaths.push_back(L"assets/Texture/BricksNRM2K.png");
textureContainer.specularPaths.push_back(L"assets/Texture/BricksGLOSS2K.png");
// Créer et initialiser le modèle si non trouvé
char modelFilename[128];
strcpy_s(modelFilename, modelName.c_str());
auto newModel = std::make_shared<model_class>();
newModel->PreloadTextures(direct_3d_->get_device(), direct_3d_->get_device_context(), textureContainer);
if (!newModel->Initialize(direct_3d_->get_device(), direct_3d_->get_device_context(), modelFilename, textureContainer)) {
Logger::Get().Log("Impossible d'initialiser le modèle du terrain", __FILE__, __LINE__, Logger::LogLevel::Error);
return;
}
// Ajouter le modèle au cache
g_model_cache[modelName] = newModel;
sharedModel = newModel;
Logger::Get().Log("Added terrain model to cache: " + modelName, __FILE__, __LINE__);
}
// Vérifier si l'entity manager est disponible
if (entity_manager_) {
// Générer les tuiles de terrain avec le système ECS
for (int i = 0; i < gridSizeX; i++) {
for (int j = 0; j < gridSizeZ; j++) {
// Créer une entité
auto entity = entity_manager_->CreateEntity();
// Ajouter un composant d'identité
auto identity = entity->AddComponent<ecs::IdentityComponent>(object_id_++);
identity->SetName("TerrainTile_" + std::to_string(i) + "_" + std::to_string(j));
identity->SetType(ecs::ObjectType::Terrain);
// Ajouter un composant de transformation
auto transform = entity->AddComponent<ecs::TransformComponent>();
transform->SetPosition(XMVectorSet(i * scaleX, -12.0f, j * scaleZ, 0.0f));
transform->SetScale(XMVectorSet(scaleX, scaleY, scaleZ, 0.0f));
transform->UpdateWorldMatrix();
// Ajouter un composant de rendu
auto render = entity->AddComponent<ecs::RenderComponent>();
render->InitializeWithModel(sharedModel);
// Ajouter un composant de shader
auto shader = entity->AddComponent<ecs::ShaderComponent>();
shader->SetActiveShader(ecs::ShaderType::SUNLIGHT);
}
}
}
update_stats_after_modification();
int totalTiles = gridSizeX * gridSizeZ;
Logger::Get().Log("Terrain généré avec " + std::to_string(totalTiles) + " tuiles", __FILE__, __LINE__, Logger::LogLevel::Info);
}
void application_class::add_kobject(std::wstring& filepath)
{
std::lock_guard<std::mutex> lock(objects_mutex_);
Logger::Get().Log("Adding object", __FILE__, __LINE__);
char modelFilename[128];
TextureContainer KobjectsTextures;
filesystem::path p(filepath);
string filename = p.stem().string();
size_t convertedChars = 0;
(void)wcstombs_s(&convertedChars, modelFilename, sizeof(modelFilename), filepath.c_str(), _TRUNCATE);
filesystem::current_path(w_folder_);
// Liste des fichiers de texture
std::vector<std::wstring> kobjTexture = {
L"assets/Texture/Bricks2K.png",
L"assets/Texture/BricksNRM2K.png",
L"assets/Texture/BricksGLOSS2K.png"
};
// Configurer les chemins des textures dans le conteneur
KobjectsTextures.diffusePaths.push_back(kobjTexture[0]);
if (kobjTexture.size() > 1) KobjectsTextures.normalPaths.push_back(kobjTexture[1]);
if (kobjTexture.size() > 2) KobjectsTextures.specularPaths.push_back(kobjTexture[2]);
// Vérifier si le modèle existe déjà dans le cache
std::string modelKey = std::string(modelFilename);
std::shared_ptr<model_class> sharedModel;
auto it = g_model_cache.find(modelKey);
if (it != g_model_cache.end()) {
// Utiliser le modèle existant du cache
Logger::Get().Log("Using cached model for " + modelKey, __FILE__, __LINE__);
sharedModel = it->second;
}
else {
// Créer un nouveau modèle
sharedModel = std::make_shared<model_class>();
// Précharger les textures
sharedModel->PreloadTextures(direct_3d_->get_device(), direct_3d_->get_device_context(), KobjectsTextures);
// Initialiser le modèle
if (!sharedModel->Initialize(direct_3d_->get_device(), direct_3d_->get_device_context(), modelFilename, KobjectsTextures)) {
Logger::Get().Log("Failed to initialize model for object: " + modelKey, __FILE__, __LINE__, Logger::LogLevel::Error);
return;
}
// Ajouter le modèle au cache
g_model_cache[modelKey] = sharedModel;
Logger::Get().Log("Added model to cache: " + modelKey, __FILE__, __LINE__);
}
// Créer une nouvelle entité
auto entity = entity_manager_->CreateEntity();
// Ajouter un composant d'identité
auto identity = entity->AddComponent<ecs::IdentityComponent>(object_id_++);
identity->SetName(filename);
identity->SetType(ecs::ObjectType::Unknown);
// Ajouter un composant de transformation
auto transform = entity->AddComponent<ecs::TransformComponent>();
transform->SetPosition(XMVectorSet(0.0f, 50.0f, 0.0f, 0.0f));
transform->SetScale(XMVectorSet(1.0f, 1.0f, 1.0f, 0.0f));
transform->UpdateWorldMatrix();
// Ajouter un composant de rendu avec le modèle partagé
auto render = entity->AddComponent<ecs::RenderComponent>();
render->InitializeWithModel(sharedModel);
// Ajouter un composant de shader
auto shader = entity->AddComponent<ecs::ShaderComponent>();
shader->SetActiveShader(ecs::ShaderType::LIGHTING);
// Stocker le chemin du modèle
auto modelPath = entity->AddComponent<ecs::ModelPathComponent>();
modelPath->SetPath(filepath);
Logger::Get().Log("ECS entity created with ID: " + std::to_string(identity->GetId()), __FILE__, __LINE__);
update_stats_after_modification();
}
void application_class::add_cube()
{
std::lock_guard<std::mutex> lock(objects_mutex_);
Logger::Get().Log("Adding cube", __FILE__, __LINE__);
std::string model_name = "assets/Model/TXT/cube.txt";
std::shared_ptr<model_class> sharedModel;
auto it = g_model_cache.find(model_name);
if (it != g_model_cache.end())
{
Logger::Get().Log("Using cached model: " + model_name, __FILE__, __LINE__);
sharedModel = it->second;
}
else
{
TextureContainer cube_textures;
cube_textures.diffusePaths.push_back(L"assets/Texture/Bricks2K.png");
cube_textures.normalPaths.push_back(L"assets/Texture/BricksNRM2K.png");
cube_textures.specularPaths.push_back(L"assets/Texture/BricksGLOSS2K.png");
char model_filename[128];
strcpy_s(model_filename, model_name.c_str());
auto newModel = std::make_shared<model_class>();
newModel->PreloadTextures(direct_3d_->get_device(), direct_3d_->get_device_context(), cube_textures);
if (!newModel->Initialize(direct_3d_->get_device(), direct_3d_->get_device_context(), model_filename, cube_textures)) {
Logger::Get().Log("Failed to initialize cube model", __FILE__, __LINE__, Logger::LogLevel::Error);
return;
}
g_model_cache[model_name] = newModel;
sharedModel = newModel;
Logger::Get().Log("Added cube model to cache: " + model_name, __FILE__, __LINE__);
if (entity_manager_)
{
auto entity = entity_manager_->CreateEntity();
auto identity = entity->AddComponent<ecs::IdentityComponent>(object_id_++);
identity->SetName("Cube");
identity->SetType(ecs::ObjectType::Cube);
auto transform = entity->AddComponent<ecs::TransformComponent>();
transform->SetPosition(XMVectorSet(0.0f, 10.0f, 0.0f, 0.0f));
transform->SetScale(XMVectorSet(1.0f, 1.0f, 1.0f, 0.0f));
transform->UpdateWorldMatrix();
auto render = entity->AddComponent<ecs::RenderComponent>();
render->InitializeWithModel(sharedModel);
auto shader = entity->AddComponent<ecs::ShaderComponent>();
shader->SetActiveShader(ecs::ShaderType::TEXTURE);
}
}
update_stats_after_modification();
Logger::Get().Log("Cube added successfully", __FILE__, __LINE__, Logger::LogLevel::Info);
}
void application_class::delete_entity_by_id(int entity_id)
{
std::lock_guard<std::mutex> lock(objects_mutex_);
Logger::Get().Log("Deleting entity with ID: " + std::to_string(entity_id), __FILE__, __LINE__, Logger::LogLevel::Info);
if (entity_manager_) {
// Rechercher l'entité avec l'ID spécifié via le composant IdentityComponent
auto entities_with_identity = entity_manager_->GetEntitiesWithComponent<ecs::IdentityComponent>();
for (auto& entity : entities_with_identity) {
auto identity = entity->GetComponent<ecs::IdentityComponent>();
if (identity && identity->GetId() == entity_id) {
// Supprimer l'entité
entity_manager_->DestroyEntity(entity->GetID());
Logger::Get().Log("Entity with ID " + std::to_string(entity_id) + " successfully deleted", __FILE__, __LINE__, Logger::LogLevel::Info);
break;
}
}
}
update_stats_after_modification();
}
void application_class::delete_terrain()
{
std::lock_guard<std::mutex> lock(objects_mutex_);
Logger::Get().Log("Deleting terrain", __FILE__, __LINE__, Logger::LogLevel::Info);
// Get all entities with the Terrain type
auto entities_with_terrain = entity_manager_->GetEntitiesWithComponent<ecs::IdentityComponent>();
for (auto& entity : entities_with_terrain) {
auto identity = entity->GetComponent<ecs::IdentityComponent>();
if (identity && identity->GetType() == ecs::ObjectType::Terrain) {
// Destroy the entity
entity_manager_->DestroyEntity(entity->GetID());
Logger::Get().Log("Terrain entity with ID " + std::to_string(identity->GetId()) + " successfully deleted", __FILE__, __LINE__, Logger::LogLevel::Info);
}
}
update_stats_after_modification();
}
bool application_class::update_mouse_strings(int mouseX, int mouseY, bool mouseDown)
{
char tempString[16], finalString[32];
bool result;
// Convert the mouse X integer to string format.
sprintf_s(tempString, "%d", mouseX);
// Setup the mouse X string.
strcpy_s(finalString, "Mouse X: ");
strcat_s(finalString, tempString);
// Update the sentence vertex buffer with the new string information.
result = mouse_strings_[0].UpdateText(direct_3d_->get_device_context(), font_, finalString, 10, 50, 1.0f, 1.0f, 1.0f);
if (!result)
{
Logger::Get().Log("Could not update the mouse X string", __FILE__, __LINE__, Logger::LogLevel::Error);
return false;
}
// Convert the mouse Y integer to string format.
sprintf_s(tempString, "%d", mouseY);
// Setup the mouse Y string.
strcpy_s(finalString, "Mouse Y: ");
strcat_s(finalString, tempString);
// Update the sentence vertex buffer with the new string information.
result = mouse_strings_[1].UpdateText(direct_3d_->get_device_context(), font_, finalString, 10, 75, 1.0f, 1.0f, 1.0f);
if (!result)
{
Logger::Get().Log("Could not update the mouse Y string", __FILE__, __LINE__, Logger::LogLevel::Error);
return false;
}
// Setup the mouse button string.
if (mouseDown)
{
strcpy_s(finalString, "Mouse Button: Yes");
}
else
{
strcpy_s(finalString, "Mouse Button: No");
}
// Update the sentence vertex buffer with the new string information.
result = mouse_strings_[2].UpdateText(direct_3d_->get_device_context(), font_, finalString, 10, 100, 1.0f, 1.0f, 1.0f);
if (!result)
{
Logger::Get().Log("Could not update the mouse button string", __FILE__, __LINE__, Logger::LogLevel::Error);
return false;
}
return true;
}
bool application_class::update_fps()
{
int fps;
char tempString[16], finalString[16];
float red, green, blue;
bool result;
// Update the fps each frame.
fps_->Frame();
stats_->update_display_stats(); // Update the stats display with the latest information from fps class.
// Get the current fps.
fps = fps_->GetFps();
// Check if the fps from the previous frame was the same, if so don't need to update the text string.
if (previous_fps_ == fps)
{
return true;
}
// Store the fps for checking next frame.
previous_fps_ = fps;
// Truncate the fps to below 100,000.
if (fps > 99999)
{
fps = 99999;
}
// Convert the fps integer to string format.
sprintf_s(tempString, "%d", fps);
// Setup the fps string.
strcpy_s(finalString, "Fps: ");
strcat_s(finalString, tempString);
// If fps is 60 or above set the fps color to green.
if (fps >= 60)
{
red = 0.0f;
green = 1.0f;
blue = 0.0f;
}
// If fps is below 60 set the fps color to yellow.
if (fps < 60)
{
red = 1.0f;
green = 1.0f;
blue = 0.0f;
}
// If fps is below 30 set the fps color to red.
if (fps < 30)
{
red = 1.0f;
green = 0.0f;
blue = 0.0f;
}
// Update the sentence vertex buffer with the new string information.
result = fps_string_->UpdateText(direct_3d_->get_device_context(), font_, finalString, 10, 10, red, green, blue);
if (!result)
{
Logger::Get().Log("Could not update the fps string", __FILE__, __LINE__, Logger::LogLevel::Error);
return false;
}
return true;
}
bool application_class::update_render_count_string(int renderCount)
{
char tempString[16], finalString[32];
bool result;
// Convert the render count integer to string format.
sprintf_s(tempString, "%d", renderCount);
// Setup the render count string.
strcpy_s(finalString, "render Count: ");
strcat_s(finalString, tempString);
// Update the sentence vertex buffer with the new string information.
result = render_count_string_->UpdateText(direct_3d_->get_device_context(), font_, finalString, 10, 30, 1.0f, 1.0f, 1.0f);
if (!result)
{
Logger::Get().Log("Could not update the render count string", __FILE__, __LINE__, Logger::LogLevel::Error);
return false;
}
return true;
}
XMVECTOR application_class::get_light_color(int index)
{
//convert to XMVECTOR
XMVECTOR lightColor = XMVectorSet(lights_[index]->GetDiffuseColor().x, lights_[index]->GetDiffuseColor().y, lights_[index]->GetDiffuseColor().z, 1.0f);
return lightColor;
}
XMVECTOR application_class::get_light_position(int index)
{
//convert to XMVECTOR
XMVECTOR lightPosition = XMVectorSet(lights_[index]->GetPosition().x, lights_[index]->GetPosition().y, lights_[index]->GetPosition().z, 1.0f);
return lightPosition;
}
void application_class::set_light_color(int index, XMVECTOR color)
{
//convert to XMFLOAT4
XMFLOAT4 lightColor;
XMStoreFloat4(&lightColor, color);
//set the color
lights_[index]->SetDiffuseColor(lightColor.x, lightColor.y, lightColor.z, 1.0f);
}
void application_class::set_light_position(int index, XMVECTOR position)
{
//convert to XMFLOAT4
XMFLOAT4 lightPosition;
XMStoreFloat4(&lightPosition, position);
//set the position
lights_[index]->SetPosition(lightPosition.x, lightPosition.y, lightPosition.z);
}
void application_class::set_screen_height(int height)
{
// log the new screen height
Logger::Get().Log("Setting screen height to " + std::to_string(height), __FILE__, __LINE__);
screen_height_ = height;
}
void application_class::set_screen_width(int width)
{
// log the new screen width
Logger::Get().Log("Setting screen width to " + std::to_string(width), __FILE__, __LINE__);
screen_width_ = width;
}
void application_class::culling_thread_function()
{
Logger::Get().Log("Thread de culling démarré", __FILE__, __LINE__, Logger::LogLevel::Info);
while (culling_active_)
{
// Construction du frustum une fois par cycle de culling
construct_frustum();
// S'assurer que la skybox est toujours visible
{
std::lock_guard<std::mutex> lock(objects_mutex_);
for (auto* skyboxObject : skybox_)
{
if (skyboxObject)
{
skyboxObject->SetVisible(true);
}
}
}
// Traitement des files d'objets normaux (sans la skybox)
auto all_entity = entity_manager_->GetAllEntities();
for (auto& entity : all_entity)
{
std::lock_guard<std::mutex> lock(objects_mutex_);
auto renderComponent = entity->GetComponent<ecs::RenderComponent>();
if (renderComponent && renderComponent->GetModel())
{
// Extraction des données de position via le composant TransformComponent
auto transformComponent = entity->GetComponent<ecs::TransformComponent>();
if (transformComponent)
{
XMVECTOR transformPosition = transformComponent->GetPosition();
float x = XMVectorGetX(transformPosition);
float y = XMVectorGetY(transformPosition);
float z = XMVectorGetZ(transformPosition);
// Calcul du rayon approximatif
XMVECTOR scale = transformComponent->GetScale();
float radius = max(max(XMVectorGetX(scale), XMVectorGetY(scale)), XMVectorGetZ(scale));
// verification du frustum
bool visible = frustum_culling_.CheckCube(x, y, z, radius, get_frustum_tolerance());
renderComponent->SetVisible(visible);
}
}
}
// Pause pour éviter de surcharger le CPU
std::this_thread::sleep_for(std::chrono::milliseconds(16)); // ~60 Hz
}
Logger::Get().Log("Thread de culling terminé", __FILE__, __LINE__, Logger::LogLevel::Info);
}
bool application_class::render_pass(XMFLOAT4* diffuse, XMFLOAT4* position, XMFLOAT4* ambient, XMMATRIX view, XMMATRIX projection)
{
std::lock_guard<std::mutex> lock(objects_mutex_);
XMMATRIX scaleMatrix, rotateMatrix, translateMatrix;
bool result;
int renderCount = 0;
int i;
// render skybox
for (auto& skyboxObject : skybox_)
{
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());
// }
// if (active_camera_ == sun_camera_)
// {
// direct_3d_->set_back_buffer_render_target();
// direct_3d_->reset_viewport();
// }
set_render_count(renderCount);
return true;
}
void application_class::construct_frustum()
{
XMMATRIX projectionMatrix = direct_3d_->get_projection_matrix();
XMMATRIX viewMatrix;
active_camera_->get_view_matrix(viewMatrix);
frustum_culling_.ConstructFrustum(screen_depth, projectionMatrix, viewMatrix);
}
// Update the position of the skybox based on the camera position
void application_class::update_skybox_position()
{
if (skybox_.empty())
{
Logger::Get().Log("Skybox is empty", __FILE__, __LINE__, Logger::LogLevel::Error);
return;
}
skybox_[0]->SetTranslateMatrix(XMMatrixTranslation(active_camera_->get_position().x, active_camera_->get_position().y, active_camera_->get_position().z));
}
bool application_class::render_physics(float delta_time) {
// update the physical entity if they have the physics component
auto entities_with_physics = entity_manager_->GetEntitiesWithComponent<ecs::PhysicsComponent>();
for (auto& entity : entities_with_physics) {
auto physicsComponent = entity->GetComponent<ecs::PhysicsComponent>();
if (physicsComponent) {
// Update the physics component with the input keys and delta time
physicsComponent->Update(delta_time);
}
}
return true;
}
void application_class::physics_thread_function()
{
auto fixedUpdateInterval = std::chrono::milliseconds(1000 / physics_tick_rate_);
auto lastTime = std::chrono::steady_clock::now();
while (!should_quit_)
{
auto now = std::chrono::steady_clock::now();
if (now - lastTime >= fixedUpdateInterval)
{
lastTime = now;
float deltaTime = 1.0f / static_cast<float>(physics_tick_rate_);
bool result = render_physics(deltaTime);
if (!result)
{
Logger::Get().Log("Could not render the physics scene", __FILE__, __LINE__, Logger::LogLevel::Error);
return;
}
}
// Attendre un peu pour éviter de surcharger le CPU
std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
}
bool application_class::create_big_cube(int side_count)
{
std::string modelName = "assets/Model/TXT/cube.txt";
std::shared_ptr<model_class> sharedModel;
// Vérifier si le modèle existe déjà
auto it = g_model_cache.find(modelName);
if (it != g_model_cache.end()) {
sharedModel = it->second;
} else {
// copy le string en char*
char model_file[128];
size_t convertedChars = 0;
(void)wcstombs_s(&convertedChars, model_file, sizeof(model_file), std::wstring(modelName.begin(), modelName.end()).c_str(), _TRUNCATE);
// Créer et initialiser le modèle si non trouvé
auto newModel = std::make_shared<model_class>();
TextureContainer textures;
textures.diffusePaths.push_back(L"assets/Texture/Bricks2K.png");
textures.normalPaths.push_back(L"assets/Texture/BricksNRM2K.png");
textures.specularPaths.push_back(L"assets/Texture/BricksGLOSS2K.png");
newModel->PreloadTextures(direct_3d_->get_device(), direct_3d_->get_device_context(), textures);
if (!newModel->Initialize(direct_3d_->get_device(), direct_3d_->get_device_context(),model_file, textures)) {
Logger::Get().Log("Impossible d'initialiser le modèle du gros cube", __FILE__, __LINE__, Logger::LogLevel::Error);
return false;
}
g_model_cache[modelName] = newModel;
sharedModel = newModel;
}
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<ecs::IdentityComponent>(object_id_++);
identity->SetName("CubePart_" + std::to_string(x) + "_" + std::to_string(y) + "_" + std::to_string(z));
identity->SetType(ecs::ObjectType::Terrain);
// Ajouter un composant de transformation
auto transform = entity->AddComponent<ecs::TransformComponent>();
transform->SetPosition(XMVectorSet(static_cast<float>(x), static_cast<float>(y), static_cast<float>(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<ecs::RenderComponent>();
render->InitializeWithModel(sharedModel);
// Ajouter un composant de shader
auto shader = entity->AddComponent<ecs::ShaderComponent>();
shader->SetActiveShader(ecs::ShaderType::LIGHTING);
}
}
}
update_stats_after_modification();
return true;
}
void application_class::update_stats_after_modification()
{
if (stats_)
{
stats_ -> update_geometric_stats();
}
}
int application_class::get_terrain_entity_count()
{
std::lock_guard<std::mutex> lock(objects_mutex_);
int terrainCount = 0;
// Get all entities with the Terrain type
auto entities_with_terrain = entity_manager_->GetEntitiesWithComponent<ecs::IdentityComponent>();
for (auto& entity : entities_with_terrain) {
auto identity = entity->GetComponent<ecs::IdentityComponent>();
if (identity && identity->GetType() == ecs::ObjectType::Terrain) {
terrainCount++;
}
}
return terrainCount;
}
ModelListClass
Definition Modellistclass.h:16
Skybox
Definition Skybox.h:8
application_class::frame
virtual bool frame(input_class *)
Run the main loop of the application. This function will handle the main loop, including rendering an...
Definition application_class.cpp:760
application_class::set_light_position
void set_light_position(int index, XMVECTOR position)
Definition application_class.cpp:1748
application_class::set_render_count
void set_render_count(const int render_count)
Definition application_class.h:393
application_class::initialize
virtual bool initialize(int screen_width, int screen_height, HWND hwdn, bool is_vulkan)
Definition application_class.cpp:70
application_class::set_hwnd
void set_hwnd(HWND hwnd)
Definition application_class.h:326
application_class::get_screen_height
int get_screen_height() const
Definition application_class.cpp:1288
application_class::get_light_position
XMVECTOR get_light_position(int index)
Definition application_class.cpp:1730
application_class::delete_entity_by_id
void delete_entity_by_id(int entity_id)
Definition application_class.cpp:1526
application_class::delete_terrain
void delete_terrain()
Definition application_class.cpp:1548
application_class::set_light_color
void set_light_color(int index, XMVECTOR color)
Definition application_class.cpp:1738
application_class::create_big_cube
bool create_big_cube(int side_count)
Create a big cube with a specified number of little cube per sides.
Definition application_class.cpp:2003
application_class::construct_frustum
void construct_frustum()
Definition application_class.cpp:1940
application_class::set_windowed
void set_windowed(bool windowed)
Definition application_class.h:337
application_class::get_light_color
XMVECTOR get_light_color(int index)
Definition application_class.cpp:1722
application_class::add_kobject
void add_kobject(std::wstring &filepath)
Definition application_class.cpp:1378
application_class::get_frustum_tolerance
float get_frustum_tolerance() const
Definition application_class.h:399
application_class::update_stats_after_modification
void update_stats_after_modification()
Definition application_class.cpp:2066
application_class::physics_thread_function
void physics_thread_function()
Thread function for handling physics updates. this function will run in a separate thread to handle p...
Definition application_class.cpp:1978
application_class::add_cube
void add_cube()
Definition application_class.cpp:1464
application_class::application_class
application_class()
Constructor for the application class. Initializes member variables and sets up the application.
Definition application_class.cpp:6
application_class::generate_terrain
void generate_terrain()
Definition application_class.cpp:1293
application_class::set_screen_width
void set_screen_width(int screen_width)
Definition application_class.cpp:1765
application_class::get_render_count
int get_render_count() const
Definition application_class.h:388
application_class::get_screen_width
int get_screen_width() const
Definition application_class.cpp:1283
application_class::set_screen_height
void set_screen_height(int screen_height)
Definition application_class.cpp:1758
application_class::shutdown
void shutdown()
Definition application_class.cpp:520
application_class::get_terrain_entity_count
int get_terrain_entity_count()
Definition application_class.cpp:2074
bitmap_class
Definition bitmap_class.h:22
camera_class
Definition camera_class.h:19
d_3d_class
Definition d_3d_class.h:31
display_plane_class
Definition display_plane_class.h:15
ecs::IdentityComponent
Definition identity_component.h:18
ecs::IdentityComponent::SetName
void SetName(const std::string &name)
Definition identity_component.h:56
ecs::ModelPathComponent
Definition model_path_component.h:7
ecs::ModelPathComponent::SetPath
void SetPath(const std::wstring &path)
Definition model_path_component.h:25
ecs::PhysicsComponent
Definition physics_component.h:9
ecs::RenderComponent
Definition render_component.h:29
ecs::RenderSystem
Definition render_system.h:11
ecs::ShaderComponent
Definition shader_component.h:24
ecs::ShaderComponent::SetActiveShader
void SetActiveShader(ShaderType shader)
Definition shader_component.h:47
ecs::TransformComponent
Definition transform_component.h:9
ecs::TransformComponent::SetPosition
void SetPosition(XMVECTOR position)
Definition transform_component.h:29
font_class
Definition font_class.h:23
font_shader_class
Definition font_shader_class.h:21
fps_class
Definition fps_class.h:21
input_class
Definition input_class.h:25
light_class
Definition light_class.h:20
model_class
Definition model_class.h:151
physics
Definition physics.h:8
position_class
Definition position_class.h:15
render_texture_class
Definition render_texture_class.h:21
shader_manager_class
Definition shader_manager_class.h:28
shadow_map
Definition shadow_map.h:5
sprite_class
Definition sprite_class.h:23
stats
Definition stats.h:13
text_class
Definition text_class.h:13
timer_class
Definition timer_class.h:16
TextureContainer
Definition model_class.h:34