diff --git a/.gitignore b/.gitignore index a938b0fa..a0f662ca 100644 --- a/.gitignore +++ b/.gitignore @@ -4,4 +4,8 @@ .vs build build-debug -build-release \ No newline at end of file +build-release +debug +release +editor_debug +editor_release \ No newline at end of file diff --git a/.gitmodules b/.gitmodules index e74b17ea..faad5c32 100644 --- a/.gitmodules +++ b/.gitmodules @@ -32,3 +32,9 @@ [submodule "docs/css/doxygen-awesome-css"] path = docs/css/doxygen-awesome-css url = https://github.com/jothepro/doxygen-awesome-css.git +[submodule "engine/thirdparty/imgui"] + path = engine/thirdparty/imgui + url = https://github.com/ocornut/imgui.git +[submodule "engine/thirdparty/ImGuizmo"] + path = engine/thirdparty/ImGuizmo + url = https://github.com/CedricGuillemet/ImGuizmo.git diff --git a/CMakeLists.txt b/CMakeLists.txt index c3a095d4..1eb6ec8b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,14 +5,8 @@ project(XPE-Engine) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17 -O3") -# Add Loader -add_subdirectory(loader) - # Add Engine add_subdirectory(engine) # Add Samples -add_subdirectory(samples) - -# Add cEditor -# add_subdirectory(editor) \ No newline at end of file +add_subdirectory(samples) \ No newline at end of file diff --git a/editor/CMakeLists.txt b/editor/CMakeLists.txt deleted file mode 100644 index 4c2fe7c5..00000000 --- a/editor/CMakeLists.txt +++ /dev/null @@ -1,37 +0,0 @@ -cmake_minimum_required(VERSION 3.2) - -project(Focus) - -include(../engine/cmake_tools/CMakeLists.txt) -include(../loader/cmake_tools/CMakeLists.txt) - -set(CMAKE_CXX_STANDARD 17) -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17 -O3") - -file(GLOB_RECURSE SOURCE_FILES src/*.c src/*.cpp) - -include_directories(src) -include_engine(../engine) -include_loader(../loader) - -add_engine_definitions() -add_executable(${PROJECT_NAME} ${SOURCE_FILES}) - -link_engine(${PROJECT_NAME} ../engine) -link_loader(${PROJECT_NAME} ../loader) - -# move resources, shaders, configs into bin folder -copy_build_dir(editor/config config) -copy_build_dir(editor/res res) -copy_build_dir(editor/shaders shaders) -copy_build_dir(editor/templates templates) -copy_build_dir(editor/workspace workspace) -#copy_build_dir(engine engine) -foreach(CONFIG ${CMAKE_CONFIGURATION_TYPES}) - copy_build_dir(editor/config ${CONFIG}/config) - copy_build_dir(editor/res ${CONFIG}/res) - copy_build_dir(editor/shaders ${CONFIG}/shaders) - copy_build_dir(editor/templates ${CONFIG}/templates) - copy_build_dir(editor/workspace ${CONFIG}/workspace) -# copy_build_dir(engine ${CONFIG}/engine) -endforeach() \ No newline at end of file diff --git a/editor/config/editor_config.json b/editor/config/editor_config.json deleted file mode 100644 index 9fd04760..00000000 --- a/editor/config/editor_config.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - - "EditorConfig": { - "WinTitle": "Focus", - "WinWidth": 800, - "WinHeight": 600, - "WinX": 400, - "WinY": 300, - "VSync": false, - "Gamma": 2.2, - "Exposure": 2, - - "LogTitle": "Focus", - "LogBacktrace": 32, - - "EnableGPUInfoLog": false, - "EnableGPUWarnLog": false, - "EnableGPUErrorLog": true, - - "FPS": 165, - "LockOnFps": false, - "LogTimeDelaySeconds": 5, - - "HotReloadShaders": true, - - "MsaaSampleCount": 1 - } - -} \ No newline at end of file diff --git a/editor/res/fonts/Roboto-Bold.ttf b/editor/res/fonts/Roboto-Bold.ttf deleted file mode 100644 index 43da14d8..00000000 Binary files a/editor/res/fonts/Roboto-Bold.ttf and /dev/null differ diff --git a/editor/res/fonts/Roboto-Italic.ttf b/editor/res/fonts/Roboto-Italic.ttf deleted file mode 100644 index 1b5eaa36..00000000 Binary files a/editor/res/fonts/Roboto-Italic.ttf and /dev/null differ diff --git a/editor/res/materials/steel/albedo.png b/editor/res/materials/steel/albedo.png deleted file mode 100644 index e05966ab..00000000 Binary files a/editor/res/materials/steel/albedo.png and /dev/null differ diff --git a/editor/res/materials/steel/ao.png b/editor/res/materials/steel/ao.png deleted file mode 100644 index 718db821..00000000 Binary files a/editor/res/materials/steel/ao.png and /dev/null differ diff --git a/editor/res/materials/steel/bump.png b/editor/res/materials/steel/bump.png deleted file mode 100644 index 19d2ad81..00000000 Binary files a/editor/res/materials/steel/bump.png and /dev/null differ diff --git a/editor/res/materials/steel/height.png b/editor/res/materials/steel/height.png deleted file mode 100644 index 75eddeba..00000000 Binary files a/editor/res/materials/steel/height.png and /dev/null differ diff --git a/editor/res/materials/steel/metallic.png b/editor/res/materials/steel/metallic.png deleted file mode 100644 index 76bedc64..00000000 Binary files a/editor/res/materials/steel/metallic.png and /dev/null differ diff --git a/editor/res/materials/steel/preview.jpg b/editor/res/materials/steel/preview.jpg deleted file mode 100644 index c1d39d58..00000000 Binary files a/editor/res/materials/steel/preview.jpg and /dev/null differ diff --git a/editor/res/materials/steel/roughness.png b/editor/res/materials/steel/roughness.png deleted file mode 100644 index 6b1c22e5..00000000 Binary files a/editor/res/materials/steel/roughness.png and /dev/null differ diff --git a/editor/res/models/cube.bin b/editor/res/models/cube.bin deleted file mode 100644 index 37aa2ed8..00000000 Binary files a/editor/res/models/cube.bin and /dev/null differ diff --git a/editor/res/models/cube.gltf b/editor/res/models/cube.gltf deleted file mode 100644 index 3c8cd0c6..00000000 --- a/editor/res/models/cube.gltf +++ /dev/null @@ -1,104 +0,0 @@ -{ - "asset":{ - "generator":"Khronos glTF Blender I/O v3.5.30", - "version":"2.0" - }, - "scene":0, - "scenes":[ - { - "name":"Scene", - "nodes":[ - 0 - ] - } - ], - "nodes":[ - { - "mesh":0, - "name":"Cube" - } - ], - "meshes":[ - { - "name":"Cube.001", - "primitives":[ - { - "attributes":{ - "POSITION":0, - "TEXCOORD_0":1, - "NORMAL":2 - }, - "indices":3 - } - ] - } - ], - "accessors":[ - { - "bufferView":0, - "componentType":5126, - "count":24, - "max":[ - 1, - 1, - 1 - ], - "min":[ - -1, - -1, - -1 - ], - "type":"VEC3" - }, - { - "bufferView":1, - "componentType":5126, - "count":24, - "type":"VEC2" - }, - { - "bufferView":2, - "componentType":5126, - "count":24, - "type":"VEC3" - }, - { - "bufferView":3, - "componentType":5123, - "count":36, - "type":"SCALAR" - } - ], - "bufferViews":[ - { - "buffer":0, - "byteLength":288, - "byteOffset":0, - "target":34962 - }, - { - "buffer":0, - "byteLength":192, - "byteOffset":288, - "target":34962 - }, - { - "buffer":0, - "byteLength":288, - "byteOffset":480, - "target":34962 - }, - { - "buffer":0, - "byteLength":72, - "byteOffset":768, - "target":34963 - } - ], - "buffers":[ - { - "byteLength":840, - "uri":"cube.bin" - } - ] -} diff --git a/editor/res/skybox/back.jpg b/editor/res/skybox/back.jpg deleted file mode 100644 index 470a6797..00000000 Binary files a/editor/res/skybox/back.jpg and /dev/null differ diff --git a/editor/res/skybox/bottom.jpg b/editor/res/skybox/bottom.jpg deleted file mode 100644 index 893f3947..00000000 Binary files a/editor/res/skybox/bottom.jpg and /dev/null differ diff --git a/editor/res/skybox/front.jpg b/editor/res/skybox/front.jpg deleted file mode 100644 index 4e17b779..00000000 Binary files a/editor/res/skybox/front.jpg and /dev/null differ diff --git a/editor/res/skybox/left.jpg b/editor/res/skybox/left.jpg deleted file mode 100644 index 5750b91a..00000000 Binary files a/editor/res/skybox/left.jpg and /dev/null differ diff --git a/editor/res/skybox/right.jpg b/editor/res/skybox/right.jpg deleted file mode 100644 index 89630371..00000000 Binary files a/editor/res/skybox/right.jpg and /dev/null differ diff --git a/editor/res/skybox/top.jpg b/editor/res/skybox/top.jpg deleted file mode 100644 index 4db3c2a3..00000000 Binary files a/editor/res/skybox/top.jpg and /dev/null differ diff --git a/editor/shaders/window.ps b/editor/shaders/window.ps deleted file mode 100644 index c4a90f4f..00000000 Binary files a/editor/shaders/window.ps and /dev/null differ diff --git a/editor/shaders/window.vs b/editor/shaders/window.vs deleted file mode 100644 index 595e6f5d..00000000 --- a/editor/shaders/window.vs +++ /dev/null @@ -1,56 +0,0 @@ -#include ../engine_shaders/types.shader -#include ../engine_shaders/batching.shader -#include ../engine_shaders/transforming.shader -#include ../engine_shaders/controls/camera.shader - -struct VSIn -{ - float3 positionLocal : XPE_POSITION; - float2 uv : XPE_UV; - float3 normal : XPE_NORMAL; // normalized - float3 tangent : XPE_TANGENT; // normalized - uint instanceIndex : SV_InstanceID; -}; - -struct VSOut -{ - float3 positionWorld : XPE_POSITION_WORLD; - float2 uv : XPE_UV2; - float3 normal : XPE_NORMAL_WORLD; - float4 positionClip : SV_POSITION; - float3 viewPosition : XPE_VIEW_POSITION; - uint materialIndex : XPE_MATERIAL_INDEX; - float3x3 tbn : XPE_TBN; - float gamma : XPE_GAMMA; -}; - -VSOut vs_main(VSIn vsIn) -{ - VSOut vsOut = (VSOut)0; - - RenderInstance instance = Instances[vsIn.instanceIndex]; - float4x4 worldMatrix = Transforms[instance.TransformIndex].ModelMatrix; - float4x4 worldNormalMatrix = Transforms[instance.TransformIndex].NormalMatrix; - Camera camera = Cameras[instance.CameraIndex]; - - float4 positionWorld = mul(worldMatrix, float4(vsIn.positionLocal, 1.0)); - float4 positionView = mul(camera.View, positionWorld); - float4 positionClip = mul(camera.Projection, positionView); - - float3 normalWorld = mul(worldNormalMatrix, float4(vsIn.normal, 1.0)).xyz; - float3 tangentWorld = mul(worldNormalMatrix, float4(vsIn.tangent, 1.0)).xyz; - normalWorld = normalize(normalWorld); - tangentWorld = normalize(tangentWorld); - float3 bitangentWorld = -cross(normalWorld, tangentWorld); - - vsOut.positionWorld = positionWorld.xyz; - vsOut.uv = vsIn.uv; - vsOut.normal = normalWorld.xyz; - vsOut.positionClip = positionClip; - vsOut.viewPosition = camera.Position; - vsOut.materialIndex = instance.MaterialIndex; - vsOut.tbn = float3x3(tangentWorld, bitangentWorld, normalWorld); - vsOut.gamma = camera.Gamma; - - return vsOut; -} \ No newline at end of file diff --git a/editor/shaders/window2d.ps b/editor/shaders/window2d.ps deleted file mode 100644 index fc156915..00000000 Binary files a/editor/shaders/window2d.ps and /dev/null differ diff --git a/editor/shaders/window2d.vs b/editor/shaders/window2d.vs deleted file mode 100644 index fe59f1e3..00000000 --- a/editor/shaders/window2d.vs +++ /dev/null @@ -1,40 +0,0 @@ -#include ../engine_shaders/types.shader -#include ../engine_shaders/batching.shader -#include ../engine_shaders/transforming.shader -#include ../engine_shaders/controls/camera.shader - -struct VSIn -{ - float2 positionLocal : XPE_POSITION_2D; - float2 uv : XPE_UV; - uint instanceIndex : SV_InstanceID; -}; - -struct VSOut -{ - float2 positionWorld : XPE_POSITION_WORLD; - float2 uv : XPE_UV2; - float4 positionClip : SV_POSITION; - float2 viewPosition : XPE_VIEW_POSITION; -}; - -VSOut vs_main(VSIn vsIn) -{ - VSOut vsOut = (VSOut)0; - RenderInstance2D instance = Instances2D[vsIn.instanceIndex]; - float3x3 worldMatrix = Transforms2D[instance.TransformIndex].ModelMatrix; - Camera camera = Cameras[instance.CameraIndex]; - - float4 positionWorld = float4(mul(worldMatrix, float3(vsIn.positionLocal, 1.0)), 1.0); - float4 positionView = mul(camera.View, positionWorld); - positionView.z = 1.0; - positionView.w = 1.0; - float4 positionClip = mul(camera.Projection, positionView); - - vsOut.positionWorld = positionWorld.xy; - vsOut.viewPosition = camera.Position.xy; - vsOut.uv = vsIn.uv; - vsOut.positionClip = positionClip; - - return vsOut; -} \ No newline at end of file diff --git a/editor/src/core/file_watcher.cpp b/editor/src/core/file_watcher.cpp deleted file mode 100644 index 032e5c54..00000000 --- a/editor/src/core/file_watcher.cpp +++ /dev/null @@ -1,184 +0,0 @@ -#include - -namespace focus { - - namespace core { - - void cFileWatcher::Notify(sFileWatch& watch, const string &watchpath, const string &filepath, cFileWatcher::eAction action) - { - switch (action) { - - case cFileWatcher::eAction::OLD_NAME: - watch.FileOldNameEvents.NotifyAll(watchpath, filepath); - break; - - case cFileWatcher::eAction::NEW_NAME: - watch.FileNewNameEvents.NotifyAll(watchpath, filepath); - break; - - case cFileWatcher::eAction::ADDED: - watch.FileAddedEvents.NotifyAll(watchpath, filepath); - break; - - case cFileWatcher::eAction::DELETED: - watch.FileDeletedEvents.NotifyAll(watchpath, filepath); - break; - - case cFileWatcher::eAction::MODIFIED: - watch.FileModifiedEvents.NotifyAll(watchpath, filepath); - break; - - } - } - - sFileWatch& cMultiFileWatcher::AddWatch(const char* path) - { - m_Paths[path].Timestamp = std::filesystem::last_write_time(path); - return m_Paths[path]; - } - - void cMultiFileWatcher::RemoveWatch(const char* path) - { - m_Paths.erase(path); - } - - bool cMultiFileWatcher::Exists(const string &path) - { - return m_Paths.find(path) != m_Paths.end(); - } - - void cMultiFileWatcher::Start() - { - m_Running = true; - cTaskManager::SubmitTask({[this]() { - while (m_Running) { - Update(); - } - }}); - } - - void cMultiFileWatcher::Stop() - { - m_Running = false; - } - - void cMultiFileWatcher::Update() - { - for (auto& watchpath : m_Paths) - { - auto& filepath = (string&)(watchpath.first); - sFileWatch& filewatch = m_Paths[filepath]; - - // check if file was deleted - if (!std::filesystem::exists(filepath)) { - if (!filewatch.DeleteNotified) { - Notify(filewatch, filepath, filepath, eAction::DELETED); - filewatch.DeleteNotified = true; - } - // we don't want to remove watch path even if it's deleted. - // because it could be deleted for a short time or replaced. - // so we want to continue watching. - continue; - } - - filewatch.DeleteNotified = false; - auto currentFileLastWriteTime = std::filesystem::last_write_time(filepath.c_str()); - - // check if file was added - if (!Exists(filepath)) { - filewatch.Timestamp = currentFileLastWriteTime; - Notify(filewatch, filepath, filepath, eAction::ADDED); - } - - // check if file was modified - else if (filewatch.Timestamp != currentFileLastWriteTime) { - filewatch.Timestamp = currentFileLastWriteTime; - Notify(filewatch, filepath, filepath, eAction::MODIFIED); - } - } - } - - sFileWatch& cDirectoryWatcher::AddWatch(const char* path) - { - m_Paths[path] = {}; - - for (auto &file : std::filesystem::recursive_directory_iterator(path)) - { - m_Paths[path][file.path().string().c_str()] = std::filesystem::last_write_time(file); - } - - return m_Watches[path]; - } - - void cDirectoryWatcher::RemoveWatch(const char* path) - { - m_Paths.erase(path); - } - - bool cDirectoryWatcher::Exists(const string &watchpath) - { - return m_Paths.find(watchpath) != m_Paths.end(); - } - - bool cDirectoryWatcher::Exists(const string &watchpath, const string& filepath) - { - auto& files = m_Paths[watchpath]; - return files.find(filepath) != files.end(); - } - - void cDirectoryWatcher::Start() - { - m_Running = true; - cTaskManager::SubmitTask({[this]() { - while (m_Running) { - for (auto& watchpath : m_Paths) - { - auto& watch = m_Watches[watchpath.first]; - for (auto& filepath : watchpath.second) { - Update(watchpath.first, filepath.first, watch); - } - } - } - }}); - } - - void cDirectoryWatcher::Stop() - { - m_Running = false; - } - - void cDirectoryWatcher::Update(const string& watchpath, const string& filepath, sFileWatch& watch) - { - auto& files = m_Paths[watchpath]; - - // check if a file was deleted - if (!std::filesystem::exists(filepath)) { - Notify(watch, watchpath, filepath, eAction::DELETED); - files.erase(filepath); - } - - // check if a file was added or modified - for (auto &file : std::filesystem::recursive_directory_iterator(watchpath)) - { - auto currentFileLastWriteTime = std::filesystem::last_write_time(file); - string fsfilepath = file.path().string().c_str(); - - // check if file was added - if (!Exists(watchpath, fsfilepath)) { - files.insert({ fsfilepath, currentFileLastWriteTime }); - Notify(watch, watchpath, fsfilepath, eAction::ADDED); - continue; - } - - // check if file was modified - auto& timestamp = files[fsfilepath]; - if (timestamp != currentFileLastWriteTime) { - timestamp = currentFileLastWriteTime; - Notify(watch, watchpath, fsfilepath, eAction::MODIFIED); - } - } - } - - } - -} \ No newline at end of file diff --git a/editor/src/core/project_manager.cpp b/editor/src/core/project_manager.cpp deleted file mode 100644 index 08c2ed13..00000000 --- a/editor/src/core/project_manager.cpp +++ /dev/null @@ -1,458 +0,0 @@ -#include -#include - -#include - -namespace focus { - - namespace core { - - using namespace xpe::render; - - sProjectStorage* cProjectManager::s_Storage = nullptr; - sProjectManagerCallback* cProjectManager::Callback = nullptr; - - static const std::unordered_map s_BinPathTable = { - {sProject::eBuildType::DEBUG_VS, "build/bin/Debug" }, - {sProject::eBuildType::RELEASE_VS, "build/bin/Release" }, - {sProject::eBuildType::DEBUG_CLION, "build-debug/bin" }, - {sProject::eBuildType::RELEASE_CLION, "build-release/bin" }, - }; - - void cProjectManager::Init() - { - s_Storage = new sProjectStorage(); - } - - void cProjectManager::Free() - { - for (auto& project : s_Storage->Projects) { - StopWatching(project.first); - delete project.second.FilesWatcher; - delete project.second.DirsWatcher; - } - delete s_Storage; - } - - sProject* cProjectManager::CreateProject(const string& title) - { - // create path to project - hstringstream ss; - ss << "workspace" << "/" << title; - hstring projectPath = ss.str(); - - if (s_Storage->Projects.find(title) != s_Storage->Projects.end() || cFileManager::Exists(projectPath.c_str())) - { - LogError("Failed to create project {}. Project already exists.", title); - SetupProject(title); - return &s_Storage->Projects[title]; - } - - // create project folder - cFileManager::CreateDir(projectPath.c_str()); - - // copy all from template to new project folder - cFileManager::CopyDirs("templates/Game", projectPath.c_str()); - - // copy engine into new project folder - ss = {}; - ss << projectPath << "/" << "engine"; - hstring enginePath = ss.str(); - cFileManager::CopyDirs("engine", enginePath.c_str()); - - // create path to cmake Launcher - ss = {}; - ss << projectPath << "/" << "Launcher" << "/" << "CMakeLists.txt"; - hstring cmakeLauncherPath = ss.str(); - - // create path to cmake Code - ss = {}; - ss << projectPath << "/" << "Code" << "/" << "CMakeLists.txt"; - hstring cmakeCodePath = ss.str(); - - // create path to cmake Project - ss = {}; - ss << projectPath << "/" << "CMakeLists.txt"; - hstring cmakeProjectPath = ss.str(); - - // create path to main file of Launcher project - ss = {}; - ss << projectPath << "/Launcher/" << "main.cpp"; - hstring cppLauncherPath = ss.str(); - - // create path to main file of Code project - ss = {}; - ss << projectPath << "/Code/cpp/game.cpp"; - hstring cppCodePath = ss.str(); - ss = {}; - ss << projectPath << "/Code/include/game.h"; - hstring headerCodePath = ss.str(); - - // update Launcher CMakeLists file - string cmakeLauncher = cFileManager::ReadFile(cmakeLauncherPath.c_str()); - cmakeLauncher = std::regex_replace(cmakeLauncher, std::regex("\\Game"), title); - cFileManager::WriteFile(cmakeLauncherPath.c_str(), cmakeLauncher); - - // update Launcher cpp file - string cppLauncher = cFileManager::ReadFile(cppLauncherPath.c_str()); - cppLauncher = std::regex_replace(cppLauncher, std::regex("\\TemplateGame"), title); - cppLauncher = std::regex_replace(cppLauncher, std::regex("\\Template"), title); - cFileManager::WriteFile(cppLauncherPath.c_str(), cppLauncher); - - // update Code CMakeLists file - string cmakeCode = cFileManager::ReadFile(cmakeCodePath.c_str()); - cmakeCode = std::regex_replace(cmakeCode, std::regex("\\Game"), title); - cFileManager::WriteFile(cmakeCodePath.c_str(), cmakeCode); - - // update Code cpp file - string cppCode = cFileManager::ReadFile(cppCodePath.c_str()); - cppCode = std::regex_replace(cppCode, std::regex("\\TemplateGame"), title); - cFileManager::WriteFile(cppCodePath.c_str(), cppCode); - - // update Code header file - string headerCode = cFileManager::ReadFile(headerCodePath.c_str()); - headerCode = std::regex_replace(headerCode, std::regex("\\TemplateGame"), title); - cFileManager::WriteFile(headerCodePath.c_str(), headerCode); - - // update Project CMakeLists file - string cmakeProject = cFileManager::ReadFile(cmakeProjectPath.c_str()); - cmakeProject = std::regex_replace(cmakeProject, std::regex("\\Game"), title); - cFileManager::WriteFile(cmakeProjectPath.c_str(), cmakeProject); - - SetupProject(title); - - return &s_Storage->Projects[title]; - } - - void cProjectManager::SetupProject(const string &title) - { - sProject project; - project.Title = title; - project.FilesWatcher = new cMultiFileWatcher(title); - project.DirsWatcher = new cDirectoryWatcher(title); - - s_Storage->Projects[title] = project; - - hstring projectPath = GetProjectPath(title); - - // create build dirs for Visual Studio - hstringstream ss; - ss << projectPath << "/build"; - cFileManager::CreateDir(ss.str().c_str()); - ss = {}; - ss << projectPath << "/build/bin"; - cFileManager::CreateDir(ss.str().c_str()); - ss = {}; - ss << projectPath << "/build/bin/Debug"; - cFileManager::CreateDir(ss.str().c_str()); - ss << "/" << title << "Code_Edit.dll"; - cFileManager::WriteFile(ss.str().c_str(), ""); - ss = {}; - ss << projectPath << "/build/bin/Release"; - cFileManager::CreateDir(ss.str().c_str()); - ss << "/" << title << "Code_Edit.dll"; - cFileManager::WriteFile(ss.str().c_str(), ""); - - // create build dirs for CLion - ss = {}; - ss << projectPath << "/build-debug"; - cFileManager::CreateDir(ss.str().c_str()); - ss = {}; - ss << projectPath << "/build-debug/bin"; - cFileManager::CreateDir(ss.str().c_str()); - ss << "/" << title << "Code_Edit.dll"; - cFileManager::WriteFile(ss.str().c_str(), ""); - ss = {}; - ss << projectPath << "/build-release"; - cFileManager::CreateDir(ss.str().c_str()); - ss = {}; - ss << projectPath << "/build-release/bin"; - cFileManager::CreateDir(ss.str().c_str()); - ss << "/" << title << "Code_Edit.dll"; - cFileManager::WriteFile(ss.str().c_str(), ""); - - // watch for Visual Studio build - WatchProjectGameCodeDLL(*project.FilesWatcher, project.Title, "build/bin/Debug"); - WatchProjectGameCodeDLL(*project.FilesWatcher, project.Title, "build/bin/Release"); - - // watch for CLion build - WatchProjectGameCodeDLL(*project.FilesWatcher, project.Title, "build-debug/bin"); - WatchProjectGameCodeDLL(*project.FilesWatcher, project.Title, "build-release/bin"); - - // watch for game project source folders - WatchProjectShaders(*project.DirsWatcher, project.Title); - WatchProjectResources(*project.DirsWatcher, project.Title); - } - - static void GameCodeDLLModified( - void* thiz, - const string& watchpath, - const string& filepath - ) { - LogInfo("cProjectManager: Game code of {} has been changed!", filepath); - cProjectManager::LoadGameCode(filepath); - } - - static void ShaderFileModified( - void* thiz, - const string& watchpath, - const string& filepath - ) { - LogInfo("cProjectManager: sShader file {} has been changed!", filepath); - cShaderManager::ReloadStage(filepath.c_str()); - } - - static void ModelFileModified( - void* thiz, - const string& watchpath, - const string& filepath - ) { - LogInfo("cProjectManager: sModel file {} has been changed!", filepath); - } - - static void FontFileModified( - void* thiz, - const string& watchpath, - const string& filepath - ) { - LogInfo("cProjectManager: sFont file {} has been changed!", filepath); - } - - static void MaterialFileModified( - void* thiz, - const string& watchpath, - const string& filepath - ) { - LogInfo("cProjectManager: Material file {} has been changed!", filepath); - } - - static void SkyboxFileModified( - void* thiz, - const string& watchpath, - const string& filepath - ) { - LogInfo("cProjectManager: sSkybox file {} has been changed!", filepath); - } - - void cProjectManager::WatchProjectGameCodeDLL(cMultiFileWatcher& watcher, const string &title, const char* buildPath) - { - hstringstream ss; - ss << "workspace/" << title << "/" << buildPath << "/" << title << "Code_Edit.dll"; - hstring gameCodeDllPath = ss.str(); - - auto& watch = watcher.AddWatch(gameCodeDllPath.c_str()); - watch.FileModifiedEvents.AddEvent(nullptr, GameCodeDLLModified, 1); - } - - void cProjectManager::WatchProjectShaders(cDirectoryWatcher& watcher, const string &title) - { - hstringstream ss; - ss << "workspace/" << title << "/" << "shaders"; - hstring shadersPath = ss.str(); - - auto& watch = watcher.AddWatch(shadersPath.c_str()); - watch.FileModifiedEvents.AddEvent(nullptr, ShaderFileModified, 1); - watch.FileAddedEvents.AddEvent(nullptr, ShaderFileModified, 1); - watch.FileDeletedEvents.AddEvent(nullptr, ShaderFileModified, 1); - } - - void cProjectManager::WatchProjectResources(cDirectoryWatcher& watcher, const string &title) - { - hstringstream ss; - ss << "workspace/" << title << "/res/" << "models"; - hstring modelsPath = ss.str(); - - { - auto& watch = watcher.AddWatch(modelsPath.c_str()); - watch.FileModifiedEvents.AddEvent(nullptr, ModelFileModified, 1); - watch.FileAddedEvents.AddEvent(nullptr, ModelFileModified, 1); - watch.FileDeletedEvents.AddEvent(nullptr, ModelFileModified, 1); - } - - ss = {}; - ss << "workspace/" << title << "/res/" << "fonts"; - hstring fontsPath = ss.str(); - - { - auto& watch = watcher.AddWatch(fontsPath.c_str()); - watch.FileModifiedEvents.AddEvent(nullptr, FontFileModified, 1); - watch.FileAddedEvents.AddEvent(nullptr, FontFileModified, 1); - watch.FileDeletedEvents.AddEvent(nullptr, FontFileModified, 1); - } - - ss = {}; - ss << "workspace/" << title << "/res/" << "materials"; - hstring materialsPath = ss.str(); - - { - auto& watch = watcher.AddWatch(materialsPath.c_str()); - watch.FileModifiedEvents.AddEvent(nullptr, MaterialFileModified, 1); - watch.FileAddedEvents.AddEvent(nullptr, MaterialFileModified, 1); - watch.FileDeletedEvents.AddEvent(nullptr, MaterialFileModified, 1); - } - - ss = {}; - ss << "workspace/" << title << "/res/" << "skybox"; - hstring skyboxPath = ss.str(); - - { - auto& watch = watcher.AddWatch(skyboxPath.c_str()); - watch.FileModifiedEvents.AddEvent(nullptr, SkyboxFileModified, 1); - watch.FileAddedEvents.AddEvent(nullptr, SkyboxFileModified, 1); - watch.FileDeletedEvents.AddEvent(nullptr, SkyboxFileModified, 1); - } - } - - hstring cProjectManager::GetProjectPath(const string &title) - { - hstringstream ss; - ss << "workspace/" << title; - return ss.str(); - } - - hstring cProjectManager::GetVSBuildPath(const string &title) - { - hstringstream ss; - ss << "workspace/" << title << "/build"; - return ss.str(); - } - - hstring cProjectManager::GetLaunchPath(const string &title, sProject::eBuildType buildType) - { - hstringstream ss; - ss << "workspace/" << title << "/" << s_BinPathTable.at(buildType); - return ss.str(); - } - - void cProjectManager::LoadGameCode(const string &dllpath) - { - cApp* game = cProcessManager::LoadObjectFromDLL(dllpath.c_str(), "CreateGame"); - if (game == nullptr) { - LogError("Failed to load game code from DLL {}", dllpath); - return; - } - // dispatch Game object with atomic thread-safe approach - if (Callback != nullptr) { - Callback->GameReloaded.store(game); - } - } - - void cProjectManager::OpenInСMake(const string &title) - { - std::thread thread([title]() { - hstringstream ss; - - hstring projectPath = GetProjectPath(title); - hstring buildPath = GetVSBuildPath(title); - if (!cFileManager::Exists(projectPath.c_str())) { - LogError("Failed to open in CMake GUI for a game project {}. Path {} not found", title, projectPath); - return; - } - - ss << "cmake-gui"; - ss << " -B " << cFileManager::GetAbsolutePath(buildPath.c_str()); - ss << " -S " << cFileManager::GetAbsolutePath(projectPath.c_str()); - system(ss.str().c_str()); - }); - thread.detach(); - } - - void cProjectManager::OpenInCLion(const string &title) - { - std::thread thread([title]() { - hstringstream ss; - - hstring projectPath = GetProjectPath(title); - if (!cFileManager::Exists(projectPath.c_str())) { - LogError("Failed to open in CLion IDE a game project {}. Path {} not found", title, projectPath); - return; - } - - ss << "clion64.exe " << cFileManager::GetAbsolutePath(projectPath.c_str()); - system(ss.str().c_str()); - }); - thread.detach(); - } - - void cProjectManager::OpenInVS(const string &title) - { - std::thread thread([title]() { - hstringstream ss; - - hstring projectPath = GetProjectPath(title); - if (!cFileManager::Exists(projectPath.c_str())) { - LogError("Failed to open in Visual Studio IDE a game project {}. Path {} not found", title, projectPath); - return; - } - - ss << "start devenv " << cFileManager::GetAbsolutePath(projectPath.c_str()); - system(ss.str().c_str()); - }); - thread.detach(); - } - - void cProjectManager::OpenInVSCode(const string &title) - { - std::thread thread([title]() { - hstringstream ss; - - hstring projectPath = GetProjectPath(title); - if (!cFileManager::Exists(projectPath.c_str())) { - LogError("Failed to open in VS Code a game project {}. Path {} not found", title, projectPath); - return; - } - - ss << "code " << cFileManager::GetAbsolutePath(projectPath.c_str()); - system(ss.str().c_str()); - }); - thread.detach(); - } - - void cProjectManager::LaunchGame(const string &title, sProject::eBuildType buildType) - { - std::thread thread([title, buildType]() { - hstringstream ss; - - hstring launchPath = GetLaunchPath(title, buildType); - ss << launchPath << "/" << title << ".exe"; - hstring exePath = ss.str(); - - if (!cFileManager::Exists(exePath.c_str())) { - LogError("Failed to launch a game executable of {}. Path {} not found", title, exePath); - return; - } - - cProcessManager::StartExe(cFileManager::GetAbsolutePath(exePath.c_str()).c_str()); - }); - thread.detach(); - } - - void cProjectManager::StartWatching(const string& title) - { - auto project = s_Storage->Projects.find(title); - - if (project == s_Storage->Projects.end()) { - LogError("Failed to start watching for game project {}. Project is absent!", title); - return; - } - - project->second.FilesWatcher->Start(); - project->second.DirsWatcher->Start(); - } - - void cProjectManager::StopWatching(const string& title) - { - auto project = s_Storage->Projects.find(title); - - if (project == s_Storage->Projects.end()) { - LogError("Failed to stop watching for game project {}. Project is absent!", title); - return; - } - - project->second.FilesWatcher->Stop(); - project->second.DirsWatcher->Stop(); - } - - } - -} \ No newline at end of file diff --git a/editor/src/core/project_manager.hpp b/editor/src/core/project_manager.hpp deleted file mode 100644 index 035bc9cb..00000000 --- a/editor/src/core/project_manager.hpp +++ /dev/null @@ -1,79 +0,0 @@ -#pragma once - -#include - -namespace xpe::core { - class cApp; -} - -namespace focus { - - using namespace xpe::core; - - namespace core { - - struct sProject final { - - enum class eBuildType - { - DEBUG_VS, - RELEASE_VS, - DEBUG_CLION, - RELEASE_CLION - }; - - string Title; - cMultiFileWatcher* FilesWatcher = nullptr; - cDirectoryWatcher* DirsWatcher = nullptr; - }; - - struct sProjectStorage : public cObject { - unordered_map Projects; - }; - - struct sProjectManagerCallback { - std::atomic GameReloaded; - }; - - class cProjectManager final { - - public: - static sProjectManagerCallback* Callback; - - public: - static void Init(); - static void Free(); - - static sProject* CreateProject(const string& title); - - static void StartWatching(const string& title); - static void StopWatching(const string& title); - - static void LoadGameCode(const string& dllpath); - - static void OpenInСMake(const string& title); - static void OpenInCLion(const string& title); - static void OpenInVS(const string& title); - static void OpenInVSCode(const string& title); - - static void LaunchGame(const string& title, sProject::eBuildType buildType); - - private: - static hstring GetProjectPath(const string& title); - static hstring GetVSBuildPath(const string& title); - static hstring GetLaunchPath(const string& title, sProject::eBuildType buildType); - - static void SetupProject(const string& title); - - static void WatchProjectGameCodeDLL(cMultiFileWatcher& watcher, const string& title, const char* buildPath); - static void WatchProjectShaders(cDirectoryWatcher& watcher, const string& title); - static void WatchProjectResources(cDirectoryWatcher& watcher, const string& title); - - private: - static sProjectStorage* s_Storage; - - }; - - } - -} \ No newline at end of file diff --git a/editor/src/editor.cpp b/editor/src/editor.cpp deleted file mode 100644 index 46721513..00000000 --- a/editor/src/editor.cpp +++ /dev/null @@ -1,54 +0,0 @@ -#include -#include - -namespace focus { - - namespace core { - - void cEditor::Init() - { - LogInfo("cEditor::Init()"); - cProjectManager::Init(); - cProjectManager::CreateProject("Chess"); - cProjectManager::Callback = this; - cProjectManager::StartWatching("Chess"); - // todo later I will move it into Input keys and UI -// cProjectManager::OpenInCLion("Chess"); -// cProjectManager::OpenInСMake("Chess"); -// cProjectManager::OpenInVS("Chess"); -// cProjectManager::OpenInVSCode("Chess"); -// cProjectManager::LaunchGame("Chess", Project::eBuildType::DEBUG_VS); - } - - void cEditor::Update() - { - cApp* gameReload = GameReloaded.load(); - if (gameReload != nullptr) { - GameReloaded.store(nullptr); - } - } - - void cEditor::Free() - { - LogInfo("cEditor::Free()"); - cProjectManager::Free(); - } - - } - -} - -xpe::core::cApp* CreateApplication() -{ - cApp* app = new focus::core::cEditor(); - - // read app configs - // app->Config = string("EditorConfig"); todo: compilator error - if (!xpe::res::ReadJsonFile("config/editor_config.json", app->Config)) - { - FMT_ASSERT(false, "Failed to read app config from config/config.json file. Please provide config file!"); - return 0; - } - - return app; -} \ No newline at end of file diff --git a/editor/src/editor.hpp b/editor/src/editor.hpp deleted file mode 100644 index 035c9d9f..00000000 --- a/editor/src/editor.hpp +++ /dev/null @@ -1,32 +0,0 @@ -#pragma once - -#include -#include - -using namespace xpe::core; -using namespace xpe::render; -using namespace xpe::math; - -namespace focus { - - namespace core { - - class cEditor : public cApp, public sProjectManagerCallback - { - - public: - cEditor() {} - ~cEditor() {} - - void Init() override final; - void Update() override final; - void Free() override final; - - private: - void LoadGame(cApp* game); - - }; - - } - -} \ No newline at end of file diff --git a/editor/src/platform/win/win_process_manager.cpp b/editor/src/platform/win/win_process_manager.cpp deleted file mode 100644 index 30675140..00000000 --- a/editor/src/platform/win/win_process_manager.cpp +++ /dev/null @@ -1,78 +0,0 @@ -#ifdef WINDOWS - -#include - -#include - -namespace focus { - - namespace core { - - VOID startup(LPCTSTR lpApplicationName) - { -// // additional information -// STARTUPINFO si; -// PROCESS_INFORMATION pi; -// -// // set the size of the structures -// ZeroMemory(&si, sizeof(si)); -// si.cb = sizeof(si); -// ZeroMemory(&pi, sizeof(pi)); -// -// // start the program up -// CreateProcess(lpApplicationName, // the path -// argv[1], // Command line -// NULL, // Process handle not inheritable -// NULL, // Thread handle not inheritable -// FALSE, // Set handle inheritance to FALSE -// 0, // No creation flags -// NULL, // Use parent's environment block -// NULL, // Use parent's starting directory -// &si, // Pointer to STARTUPINFO structure -// &pi // Pointer to PROCESS_INFORMATION structure (removed extra parentheses) -// ); -// -// // Close process and thread handles. -// CloseHandle(pi.hProcess); -// CloseHandle(pi.hThread); - } - - void cProcessManager::StartExe(const char* path) - { - ShellExecute(NULL, "open", path, NULL, NULL, SW_SHOWDEFAULT); - } - - static HINSTANCE s_DLL = nullptr; - - bool cProcessManager::InitDLL(const char *dllpath) - { - if (s_DLL != nullptr) { - FreeLibrary(s_DLL); - s_DLL = nullptr; - } - - // load DLL - s_DLL = static_cast(LoadLibrary(dllpath)); - if (s_DLL == nullptr) { - LogError("Failed to load DLL library from {}", dllpath); - return false; - } - - return true; - } - - void cProcessManager::FreeDLL() { - FreeLibrary(s_DLL); - s_DLL = nullptr; - } - - DLLProc cProcessManager::LoadDLLProc(const char* signature) - { - return GetProcAddress(s_DLL, signature); - } - - } - -} - -#endif // WINDOWS \ No newline at end of file diff --git a/editor/templates/Game/CMakeLists.txt b/editor/templates/Game/CMakeLists.txt deleted file mode 100644 index 7af7c23e..00000000 --- a/editor/templates/Game/CMakeLists.txt +++ /dev/null @@ -1,15 +0,0 @@ -cmake_minimum_required(VERSION 3.20) - -project(Game-Project) - -set(CMAKE_CXX_STANDARD 17) -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17 -O3") - -# Add Engine -add_subdirectory(engine) - -# Add Code -add_subdirectory(Code) - -# Add Launcher -add_subdirectory(Launcher) \ No newline at end of file diff --git a/editor/templates/Game/Code/src/game.cpp b/editor/templates/Game/Code/src/game.cpp deleted file mode 100644 index 1810a815..00000000 --- a/editor/templates/Game/Code/src/game.cpp +++ /dev/null @@ -1,382 +0,0 @@ -#include - -extern "C" GAME_API Application* _cdecl CreateGame() { - return new TemplateGame(); -} - -void TemplateGame::Init() -{ - LogInfo("TemplateGame::Init()"); - - if (!ReadJsonFile("config/test_config.json", m_TestConfig)) - { - LogError("Failed to read test config from config/test_config.json"); - } - - AddWindowClosed(TemplateGame, 1); - AddKeyPressed(TemplateGame, 1); - AddKeyHold(TemplateGame, 1); - AddCursorMove(TemplateGame, 1); - - m_Canvas = new Canvas(WindowManager::GetWidth(), WindowManager::GetHeight(), context); - m_ECS = new ECSManager(); - m_BatchManager = new BatchManager(context); - m_BatchManager2d = new BatchManager2d(context); - - Font font = TTFManager::Get().Load("resources/fonts/Roboto-Italic.ttf", 32); - TTFManager::Get().Free(font); - - TextureCubeFile textureCubeFile; - textureCubeFile.Name = "test"; - textureCubeFile.FrontFilepath = "resources/skybox/front.jpg"; - textureCubeFile.BackFilepath = "resources/skybox/back.jpg"; - textureCubeFile.RightFilepath = "resources/skybox/right.jpg"; - textureCubeFile.LeftFilepath = "resources/skybox/left.jpg"; - textureCubeFile.TopFilepath = "resources/skybox/top.jpg"; - textureCubeFile.BottomFilepath = "resources/skybox/bottom.jpg"; - - Texture* textureCube = TextureManager::LoadTextureCubeFile(textureCubeFile, Texture::eFormat::RGBA8); - -// Model3D cubeModel; -// bool cubeImported = GLTFImporter::Import("resources/cube.gltf", cubeModel); -// Mesh& cubeMesh = cubeModel[0]; - -// Model3D cubeModel = GLTFImporter::Import("resources/cube.gltf"); -// Mesh& cubeMesh = cubeModel[0]; -// m_BatchManager->StoreGeometryIndexed("CubeMesh", cubeMesh); - - PlaneGeometry plane; - m_BatchManager->StoreGeometryIndexed("PlaneGeometry", plane); - - RenderInstance planeInstance; - TransformComponent planeTransform("PlaneTransform", 0); - planeTransform.Position = { 0, -60, 0 }; - TransformManager::AddTransform(planeTransform); - m_BatchManager->AddInstance("PlaneGeometry", planeInstance); - -// CubeGeometry cube; -// m_BatchManager->StoreGeometryIndexed("CubeGeometry", cube); -// m_BatchManager->ResizeInstances("CubeGeometry", 1000); - - SphereGeometry sphere; - m_BatchManager->StoreGeometryIndexed("SphereGeometry", sphere); -// m_BatchManager->ReserveInstances("SphereGeometry", 1000); - - Quad2d quad2D; - RenderInstance2d quad2DInstance; - Transform2DComponent quad2DTransform("Quad2DTransform", 0); - quad2DTransform.Position = { 0, -10 }; - quad2DTransform.Scale = { 5, 1 }; - TransformManager::AddTransform2D(quad2DTransform); - m_BatchManager2d->StoreGeometryIndexed("Quad2D", quad2D); - m_BatchManager2d->AddInstance("Quad2D", quad2DInstance); - - // Put instances of geometry - u32 transformIndex = 1; - u32 materialIndex = 0; - u32 textureIndex = 0; - for (f32 y = -4.0f; y < 4.0f; y += 4.0f) - { - for (f32 x = -4.0f; x < 4.0f; x += 4.0f) - { - for (f32 z = -4.0f; z < 4.0f; z += 4.0f) - { - float r = static_cast (rand()) / static_cast (RAND_MAX); - float g = static_cast (rand()) / static_cast (RAND_MAX); - float b = static_cast (rand()) / static_cast (RAND_MAX); - - TransformComponent transformComponent("Transform_" + transformIndex, transformIndex); - transformComponent.Position = { x, y, z }; - transformComponent.Rotation = { r * 360.0f, g * 360.0f, b * 360.0f }; -// transformComponent.Scale = { r, g, b }; - - TransformManager::AddTransform(transformComponent); - - RenderInstance instance; - instance.TransformIndex = transformIndex; - instance.MaterialIndex = materialIndex; - - Material* material = MaterialManager::CreateMaterial("Material_" + materialIndex); - material->Data->BaseColor = { 1, 1, 1, 1 }; - material->Data->MetallicFactor = r; - material->Data->RoughnessFactor = g; - material->Data->AOFactor = b; - -// material->Data->EnableAlbedo = false; -// material->AlbedoIndex = textureIndex; -// cMaterialManager::AddAlbedoFromFile(*material, "resources/materials/steel/albedo.png"); -// -// material->Data->EnableBumping = false; -// material->BumpingIndex = textureIndex; -// cMaterialManager::AddBumpFromFile(*material, "resources/materials/steel/bump.png"); -// -// material->Data->EnableMetallic = false; -// material->MetallicIndex = textureIndex; -// cMaterialManager::AddMetallicFromFile(*material, "resources/materials/steel/metallic.png"); -// -// material->Data->EnableRoughness = false; -// material->RoughnessIndex = textureIndex; -// cMaterialManager::AddRoughnessFromFile(*material, "resources/materials/steel/roughness.png"); -// -// material->Data->EnableAO = false; -// material->AOIndex = textureIndex; -// cMaterialManager::AddAOFromFile(*material, "resources/materials/steel/ao.png"); - - m_BatchManager->AddInstance("CubeGeometry", instance); - m_BatchManager->AddInstance("CubeMesh", instance); - m_BatchManager->AddInstance("SphereGeometry", instance); - m_BatchManager->AddInstance("sTriangle", instance); - - transformIndex++; - materialIndex++; - if (++textureIndex > 1) { - textureIndex = 0; - } - } - } - } - - m_DirectLightComponent.Position = { 0, 0, 0 }; - m_DirectLightComponent.Color = { 1, 1, 1 }; - LightManager::AddDirectLight(m_DirectLightComponent); - - // it will flush all instance data into GPU memory - m_BatchManager->FlushInstances("CubeGeometry"); - m_BatchManager->FlushInstances("CubeMesh"); - m_BatchManager->FlushInstances("SphereGeometry"); - m_BatchManager->FlushInstances("sTriangle"); - m_BatchManager->FlushInstances("PlaneGeometry"); - - // it will flush all instance 2D data into GPU memory - m_BatchManager2d->FlushInstances("Quad2D"); - - // it will flush all transform data into GPU memory - TransformManager::FlushTransforms(); - TransformManager::FlushTransforms2D(); - - // it will flush all material data into GPU memory - MaterialManager::FlushMaterials(); - - // it will flush all direct light data into GPU memory - LightManager::FlushDirectLights(); - - InitPipeline(); - InitPipeline2D(); - InitCamera(); - InitCamera2D(); -} - -void TemplateGame::Update() -{ - UpdateCamera(); - - Simulate(); - - m_Canvas->Clear(glm::vec4(1.0f)); - - context->BindPipeline(&m_Pipeline); - m_BatchManager->DrawAll(); - - context->BindPipeline(&m_Pipeline2d); - m_BatchManager2d->DrawAll(); - - m_Canvas->Draw(); -} - -void TemplateGame::Free() -{ - LogInfo("TemplateGame::Free()"); - - delete m_ECS; - delete m_Canvas; - - delete m_Camera; - delete m_BatchManager; - - delete m_Camera2D; - delete m_BatchManager2d; -} - -void TemplateGame::WindowClosed() -{ - LogWarning("TemplateGame::WindowClosed()"); -} - -void TemplateGame::KeyPressed(const eKey key) -{ - if (key == eKey::Esc) - { - WindowManager::Close(); - } - - if (key == eKey::R) - { - ShaderManager::ReloadStage("shaders/window.vs"); - ShaderManager::ReloadStage("shaders/window.ps"); - } - - MoveLight(key); -} - -void TemplateGame::KeyHold(const eKey key) -{ - MoveLight(key); -} - -void TemplateGame::CursorMoved(const double x, const double y) -{ - if (Input::MousePressed(eMouse::ButtonRight)) { - m_Camera->EnableLook = false; - Input::CaptureCursor(x, y); - auto& cursorDelta = Input::GetMouseCursor().Delta; - m_Camera->Pan(cursorDelta); - } else { - m_Camera->EnableLook = true; - } -} - -void TemplateGame::InitPipeline() -{ - // setup buffers - m_Pipeline.VSBuffers.emplace_back(CameraManager::GetBuffer()); - m_Pipeline.VSBuffers.emplace_back(TransformManager::GetBuffer()); - m_Pipeline.PSBuffers.emplace_back(MaterialManager::GetBuffer()); - m_Pipeline.PSBuffers.emplace_back(LightManager::GetDirectBuffer()); - m_Pipeline.PSBuffers.emplace_back(LightManager::GetPointBuffer()); - m_Pipeline.PSBuffers.emplace_back(LightManager::GetSpotBuffer()); - - // setup material textures, sampler - m_Pipeline.Samplers.emplace_back(&MaterialManager::GetStorage()->Textures.Sampler); - m_Pipeline.Textures.emplace_back(&MaterialManager::GetStorage()->Textures.AlbedoArray); - m_Pipeline.Textures.emplace_back(&MaterialManager::GetStorage()->Textures.BumpArray); - m_Pipeline.Textures.emplace_back(&MaterialManager::GetStorage()->Textures.ParallaxArray); - m_Pipeline.Textures.emplace_back(&MaterialManager::GetStorage()->Textures.MetallicArray); - m_Pipeline.Textures.emplace_back(&MaterialManager::GetStorage()->Textures.RoughnessArray); - m_Pipeline.Textures.emplace_back(&MaterialManager::GetStorage()->Textures.AOArray); - m_Pipeline.Textures.emplace_back(&MaterialManager::GetStorage()->Textures.EmissionArray); - - // setup shader - m_Pipeline.sShader = ShaderManager::CreateShader("window"); - ShaderManager::AddVertexStageFromFile(m_Pipeline.sShader, "shaders/window.vs"); - ShaderManager::AddPixelStageFromFile(m_Pipeline.sShader, "shaders/window.ps"); - ShaderManager::BuildShader(m_Pipeline.sShader); - - // setup input layout - m_Layout.Format = Vertex3D::Format; - m_Pipeline.sInputLayout = m_Layout; - - // setup render target - m_Pipeline.sRenderTarget = m_Canvas->GetRenderTarget(); - - // setup depth stencil testing - m_Pipeline.DepthStencilState.UseDepthTest = K_TRUE; - - // setup rasterizer - m_Pipeline.sRasterizer.CullMode = eCullMode::DEFAULT; - m_Pipeline.sRasterizer.FillMode = eFillMode::DEFAULT; - - // init pipeline - context->CreatePipeline(m_Pipeline); -} - -void TemplateGame::InitPipeline2D() -{ - // setup buffers - m_Pipeline2d.VSBuffers.emplace_back(CameraManager::GetBuffer()); - m_Pipeline2d.VSBuffers.emplace_back(TransformManager::GetBuffer2D()); - - // setup shader - m_Pipeline2d.sShader = ShaderManager::CreateShader("window2d"); - ShaderManager::AddVertexStageFromFile(m_Pipeline2d.sShader, "shaders/window2d.vs"); - ShaderManager::AddPixelStageFromFile(m_Pipeline2d.sShader, "shaders/window2d.ps"); - ShaderManager::BuildShader(m_Pipeline2d.sShader); - - // setup input layout - m_Layout2d.Format = Vertex2D::Format; - m_Pipeline2d.sInputLayout = m_Layout2d; - - // setup render target - m_Pipeline2d.sRenderTarget = m_Canvas->GetRenderTarget(); - m_Pipeline2d.DepthStencilState.UseDepthTest = K_FALSE; - - // init pipeline - context->CreatePipeline(m_Pipeline2d); -} - -void TemplateGame::InitCamera() -{ - m_PerspectiveCameraComponent.Projection.Far = m_TestConfig.CameraFar; - // todo BUG: after moving camera, the camera resets position - m_PerspectiveCameraComponent.Position = { 5, 5, 20 }; - m_Camera = new PerspectiveCamera(CameraManager::GetBuffer(), &m_PerspectiveCameraComponent); - m_Camera->MoveSpeed = m_TestConfig.CameraMoveSpeed; - m_Camera->ZoomAcceleration = m_TestConfig.CameraZoomAcceleration; - m_Camera->PanAcceleration = m_TestConfig.CameraPanAcceleration; - m_Camera->HorizontalSensitivity = m_TestConfig.CameraHorizontalSens; - m_Camera->VerticalSensitivity = m_TestConfig.CameraVerticalSens; -} - -void TemplateGame::InitCamera2D() -{ - m_OrthoCameraComponent.Position = { 0, 0, -1 }; - m_Camera2D = new OrthoCamera(CameraManager::GetBuffer2D(), &m_OrthoCameraComponent); -} - -void TemplateGame::UpdateCamera() -{ - if (Input::MousePressed(eMouse::ButtonLeft)) { - m_Camera->LookMode = Camera::eLookMode::EDITOR; - } else { - m_Camera->LookMode = Camera::eLookMode::GAME; - } - m_Camera->Move(); -} - -void TemplateGame::MoveLight(const eKey key) -{ - if (key == eKey::Up) { - glm::vec3& pos = m_DirectLightComponent.Position; - pos.y += 1; - LightManager::FlushDirectLight(m_DirectLightComponent); - } - - if (key == eKey::Down) { - glm::vec3& pos = m_DirectLightComponent.Position; - pos.y -= 1; - LightManager::FlushDirectLight(m_DirectLightComponent); - } - - if (key == eKey::Left) { - glm::vec3& pos = m_DirectLightComponent.Position; - pos.x -= 1; - LightManager::FlushDirectLight(m_DirectLightComponent); - } - - if (key == eKey::Right) { - glm::vec3& pos = m_DirectLightComponent.Position; - pos.x += 1; - LightManager::FlushDirectLight(m_DirectLightComponent); - } -} - -void TemplateGame::Simulate() -{ - if (m_TestConfig.AnimateLight) { - auto& pos = m_DirectLightComponent.Position; - - // translation light up and down every N ticks - static int tick = 1; - pos.y = 100 * sin(tick++ / 3000.0f); - - // update light color every N ticks - if (tick % 10000 == 0) { - auto& color = m_DirectLightComponent.Color; - float r = static_cast (rand()) / static_cast (RAND_MAX); - float g = static_cast (rand()) / static_cast (RAND_MAX); - float b = static_cast (rand()) / static_cast (RAND_MAX); - color = { r, g, b }; - } - - LightManager::FlushDirectLight(m_DirectLightComponent); - } -} diff --git a/editor/templates/Game/Code/src/game.hpp b/editor/templates/Game/Code/src/game.hpp deleted file mode 100644 index c41ce352..00000000 --- a/editor/templates/Game/Code/src/game.hpp +++ /dev/null @@ -1,71 +0,0 @@ -#include - -#include - -using namespace xpe::core; -using namespace xpe::render; -using namespace xpe::control; -using namespace xpe::ttf; -using namespace xpe::io; -using namespace xpe::math; -using namespace xpe::gltf; - -class GAME_API TemplateGame : public Application -{ -public: - TemplateGame() {} - ~TemplateGame() {} - - void Init() override final; - - void Update() override final; - - void Free() override final; - - void WindowClosed(); - - void KeyPressed(const eKey key); - void KeyHold(const eKey key); - - void CursorMoved(const double x, const double y); - -private: - - void InitPipeline(); - - void InitPipeline2D(); - - void InitCamera(); - - void InitCamera2D(); - - void UpdateCamera(); - - void MoveLight(const eKey key); - - void Simulate(); - -private: - Canvas* m_Canvas; - ECSManager* m_ECS; - - BatchManager* m_BatchManager; - BatchManager2d* m_BatchManager2d; - - Pipeline m_Pipeline; - Pipeline m_Pipeline2d; - - InputLayout m_Layout; - InputLayout m_Layout2d; - - PerspectiveCamera* m_Camera; - OrthoCamera* m_Camera2D; - - DirectLightComponent m_DirectLightComponent = string("DirectLight", 0); - - PerspectiveCameraComponent m_PerspectiveCameraComponent = string("cPerspectiveCamera"); - OrthoCameraComponent m_OrthoCameraComponent = string("cOrthoCamera"); - - TestConfig m_TestConfig; - -}; \ No newline at end of file diff --git a/editor/templates/Game/Code/src/test_config.hpp b/editor/templates/Game/Code/src/test_config.hpp deleted file mode 100644 index 72c26f50..00000000 --- a/editor/templates/Game/Code/src/test_config.hpp +++ /dev/null @@ -1,23 +0,0 @@ -#pragma once - -struct sTestConfig : xpe::res::JsonObject -{ - JsonClass( - TestConfig, - AnimateLight, - CameraFar, - CameraMoveSpeed, - CameraZoomAcceleration, - CameraPanAcceleration, - CameraHorizontalSens, - CameraVerticalSens - ) - - bool AnimateLight = false; - float CameraFar = 1000; - float CameraMoveSpeed = 0.05f; - float CameraZoomAcceleration = 10.0f; - float CameraPanAcceleration = 5.0f; - float CameraHorizontalSens = 0.005f; - float CameraVerticalSens = 0.005f; -}; \ No newline at end of file diff --git a/editor/templates/Game/Launcher/CMakeLists.txt b/editor/templates/Game/Launcher/CMakeLists.txt deleted file mode 100644 index 95ad3e79..00000000 --- a/editor/templates/Game/Launcher/CMakeLists.txt +++ /dev/null @@ -1,36 +0,0 @@ -cmake_minimum_required(VERSION 3.2) - -set(GAME_NAME Game) -set(ENGINE_PATH ../engine) - -project(${GAME_NAME}) - -include(${ENGINE_PATH}/cmake_tools/CMakeLists.txt) -include(../cmake_tools/CMakeLists.txt) - -set(CMAKE_CXX_STANDARD 17) -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17 -O3") - -file(GLOB_RECURSE SOURCE_FILES main.cpp) - -include_engine(${ENGINE_PATH}) -include_game(../Code) - -add_executable(${PROJECT_NAME} ${SOURCE_FILES}) -add_engine_definitions() -add_game_definitions() - -link_engine(${PROJECT_NAME} ${ENGINE_PATH}) -link_game(${PROJECT_NAME} ../Code ${GAME_NAME}Code) - -# move resources, shaders and configs into bin folder -copy_build_dir(config config) -copy_build_dir(resources resources) -copy_build_dir(shaders shaders) -copy_engine_shaders(${ENGINE_PATH}) -foreach(CONFIG ${CMAKE_CONFIGURATION_TYPES}) - copy_build_dir(config ${CONFIG}/config) - copy_build_dir(resources ${CONFIG}/resources) - copy_build_dir(shaders ${CONFIG}/shaders) - copy_engine_shaders_to_config(${ENGINE_PATH} ${CONFIG}) -endforeach() \ No newline at end of file diff --git a/editor/templates/Game/Launcher/main.cpp b/editor/templates/Game/Launcher/main.cpp deleted file mode 100644 index ac743b51..00000000 --- a/editor/templates/Game/Launcher/main.cpp +++ /dev/null @@ -1,8 +0,0 @@ -#include -#include - -using namespace xpe::core; - -Application* CreateApplication() { - return new TemplateGame(); -} \ No newline at end of file diff --git a/editor/templates/Game/cmake_tools/CMakeLists.txt b/editor/templates/Game/cmake_tools/CMakeLists.txt deleted file mode 100644 index c06c3705..00000000 --- a/editor/templates/Game/cmake_tools/CMakeLists.txt +++ /dev/null @@ -1,78 +0,0 @@ -# set all config types available in game project -macro(add_game_configs) - - # define all game build config types - set(CMAKE_CONFIGURATION_TYPES Debug;Release;) - - set(LIB_PATH ${CMAKE_BINARY_DIR}/lib) - set(BIN_PATH ${CMAKE_BINARY_DIR}/bin) - - set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${LIB_PATH}) - set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${BIN_PATH}) - set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${BIN_PATH}) - - message(STATUS "Setting configuration types : ${CMAKE_CONFIGURATION_TYPES}") - - foreach(CONFIG ${CMAKE_CONFIGURATION_TYPES}) - - message(STATUS "Configuration=${CONFIG}") - - string(TOUPPER ${CONFIG} UPPER_CONFIG) - - message(STATUS "Setting runtime output path ${BIN_PATH}/${CONFIG}") - set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_${UPPER_CONFIG} ${BIN_PATH}/${CONFIG}) - - endforeach() - -endmacro() - -# add game definitions -macro(add_game_definitions) - add_game_configs() - add_compile_definitions($<$:DEBUG>) -endmacro() - -# add DLL_BUILD macro to define game build as DLL -macro(build_game_dll) - add_definitions(-DGAME_DLL_BUILD=1) -endmacro() - -# include game and all it's dependencies and also defines game as DLL import -# provide path to game project -macro(include_game path) - add_definitions(-DGAME_DLL=1) - include_directories( - ${path}/src - ) -endmacro() - -# link target project with game -# provide your project name and path to game project -macro(link_game project path game) - get_filename_component(dir_name ${PROJECT_BINARY_DIR} NAME) - - ## ---------------- Debug --------------- - - if (EXISTS ${PROJECT_BINARY_DIR}/${path}/Debug/${game}.lib) - configure_file(${PROJECT_BINARY_DIR}/${path}/Debug/${game}.lib ${PROJECT_BINARY_DIR}/Debug/${game}.lib COPYONLY) - endif() - - if (EXISTS ${PROJECT_BINARY_DIR}/${path}/Debug/${game}.dll) - configure_file(${PROJECT_BINARY_DIR}/${path}/Debug/${game}.dll ${PROJECT_BINARY_DIR}/Debug/${game}.dll COPYONLY) - endif() - - ## ---------------- Release --------------- - - if (EXISTS ${PROJECT_BINARY_DIR}/${path}/Release/${game}.lib) - configure_file(${PROJECT_BINARY_DIR}/${path}/Release/${game}.lib ${PROJECT_BINARY_DIR}/Release/${game}.lib COPYONLY) - endif() - - if (EXISTS ${PROJECT_BINARY_DIR}/${path}/Release/${game}.dll) - configure_file(${PROJECT_BINARY_DIR}/${path}/Release/${game}.dll ${PROJECT_BINARY_DIR}/Release/${game}.dll COPYONLY) - endif() - - message(STATUS "Linking ${project} -> ${game}.lib") - message(STATUS "Linking ${project} -> ${game}.dll") - target_link_libraries(${project} PUBLIC ${game}) - -endmacro() \ No newline at end of file diff --git a/editor/templates/Game/config/config.json b/editor/templates/Game/config/config.json deleted file mode 100644 index 9d63b835..00000000 --- a/editor/templates/Game/config/config.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - - "AppConfig": { - "WinTitle": "Example Window", - "WinWidth": 800, - "WinHeight": 600, - "WinX": 400, - "WinY": 300, - "VSync": false, - - "LogTitle": "ExampleWindow", - "LogBacktrace": 32, - - "DebugErrors": true, - "DebugWarnings": false, - "DebugInfo": false, - - "FPS": 165, - "LockOnFps": false, - "LogTimeDelaySeconds": 5, - - "HotReloadShaders": true - } - -} \ No newline at end of file diff --git a/editor/templates/Game/config/memory_config.json b/editor/templates/Game/config/memory_config.json deleted file mode 100644 index 6534c890..00000000 --- a/editor/templates/Game/config/memory_config.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - - "MemoryConfig": { - "MainMemoryMB": 1024, - "MainAllocs": 1000, - "HotMemoryMB": 1024, - "HotAllocs": 1000 - } - -} \ No newline at end of file diff --git a/editor/templates/Game/config/test_config.json b/editor/templates/Game/config/test_config.json deleted file mode 100644 index a1ee08be..00000000 --- a/editor/templates/Game/config/test_config.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - - "TestConfig": { - "AnimateLight": false, - "CameraFar": 10000, - "CameraMoveSpeed": 0.005, - "CameraZoomAcceleration": 10.0, - "CameraPanAcceleration": 5.0, - "CameraHorizontalSens": 0.005, - "CameraVerticalSens": 0.005 - } - -} \ No newline at end of file diff --git a/editor/templates/Game/engine/CMakeLists.txt b/editor/templates/Game/engine/CMakeLists.txt deleted file mode 100644 index e69de29b..00000000 diff --git a/editor/templates/Game/res/fonts/Roboto-Bold.ttf b/editor/templates/Game/res/fonts/Roboto-Bold.ttf deleted file mode 100644 index 43da14d8..00000000 Binary files a/editor/templates/Game/res/fonts/Roboto-Bold.ttf and /dev/null differ diff --git a/editor/templates/Game/res/fonts/Roboto-Italic.ttf b/editor/templates/Game/res/fonts/Roboto-Italic.ttf deleted file mode 100644 index 1b5eaa36..00000000 Binary files a/editor/templates/Game/res/fonts/Roboto-Italic.ttf and /dev/null differ diff --git a/editor/templates/Game/res/materials/steel/albedo.png b/editor/templates/Game/res/materials/steel/albedo.png deleted file mode 100644 index e05966ab..00000000 Binary files a/editor/templates/Game/res/materials/steel/albedo.png and /dev/null differ diff --git a/editor/templates/Game/res/materials/steel/ao.png b/editor/templates/Game/res/materials/steel/ao.png deleted file mode 100644 index 718db821..00000000 Binary files a/editor/templates/Game/res/materials/steel/ao.png and /dev/null differ diff --git a/editor/templates/Game/res/materials/steel/bump.png b/editor/templates/Game/res/materials/steel/bump.png deleted file mode 100644 index 19d2ad81..00000000 Binary files a/editor/templates/Game/res/materials/steel/bump.png and /dev/null differ diff --git a/editor/templates/Game/res/materials/steel/height.png b/editor/templates/Game/res/materials/steel/height.png deleted file mode 100644 index 75eddeba..00000000 Binary files a/editor/templates/Game/res/materials/steel/height.png and /dev/null differ diff --git a/editor/templates/Game/res/materials/steel/metallic.png b/editor/templates/Game/res/materials/steel/metallic.png deleted file mode 100644 index 76bedc64..00000000 Binary files a/editor/templates/Game/res/materials/steel/metallic.png and /dev/null differ diff --git a/editor/templates/Game/res/materials/steel/preview.jpg b/editor/templates/Game/res/materials/steel/preview.jpg deleted file mode 100644 index c1d39d58..00000000 Binary files a/editor/templates/Game/res/materials/steel/preview.jpg and /dev/null differ diff --git a/editor/templates/Game/res/materials/steel/roughness.png b/editor/templates/Game/res/materials/steel/roughness.png deleted file mode 100644 index 6b1c22e5..00000000 Binary files a/editor/templates/Game/res/materials/steel/roughness.png and /dev/null differ diff --git a/editor/templates/Game/res/models/cube.bin b/editor/templates/Game/res/models/cube.bin deleted file mode 100644 index 37aa2ed8..00000000 Binary files a/editor/templates/Game/res/models/cube.bin and /dev/null differ diff --git a/editor/templates/Game/res/models/cube.gltf b/editor/templates/Game/res/models/cube.gltf deleted file mode 100644 index 3c8cd0c6..00000000 --- a/editor/templates/Game/res/models/cube.gltf +++ /dev/null @@ -1,104 +0,0 @@ -{ - "asset":{ - "generator":"Khronos glTF Blender I/O v3.5.30", - "version":"2.0" - }, - "scene":0, - "scenes":[ - { - "name":"Scene", - "nodes":[ - 0 - ] - } - ], - "nodes":[ - { - "mesh":0, - "name":"Cube" - } - ], - "meshes":[ - { - "name":"Cube.001", - "primitives":[ - { - "attributes":{ - "POSITION":0, - "TEXCOORD_0":1, - "NORMAL":2 - }, - "indices":3 - } - ] - } - ], - "accessors":[ - { - "bufferView":0, - "componentType":5126, - "count":24, - "max":[ - 1, - 1, - 1 - ], - "min":[ - -1, - -1, - -1 - ], - "type":"VEC3" - }, - { - "bufferView":1, - "componentType":5126, - "count":24, - "type":"VEC2" - }, - { - "bufferView":2, - "componentType":5126, - "count":24, - "type":"VEC3" - }, - { - "bufferView":3, - "componentType":5123, - "count":36, - "type":"SCALAR" - } - ], - "bufferViews":[ - { - "buffer":0, - "byteLength":288, - "byteOffset":0, - "target":34962 - }, - { - "buffer":0, - "byteLength":192, - "byteOffset":288, - "target":34962 - }, - { - "buffer":0, - "byteLength":288, - "byteOffset":480, - "target":34962 - }, - { - "buffer":0, - "byteLength":72, - "byteOffset":768, - "target":34963 - } - ], - "buffers":[ - { - "byteLength":840, - "uri":"cube.bin" - } - ] -} diff --git a/editor/templates/Game/res/skybox/back.jpg b/editor/templates/Game/res/skybox/back.jpg deleted file mode 100644 index 470a6797..00000000 Binary files a/editor/templates/Game/res/skybox/back.jpg and /dev/null differ diff --git a/editor/templates/Game/res/skybox/bottom.jpg b/editor/templates/Game/res/skybox/bottom.jpg deleted file mode 100644 index 893f3947..00000000 Binary files a/editor/templates/Game/res/skybox/bottom.jpg and /dev/null differ diff --git a/editor/templates/Game/res/skybox/front.jpg b/editor/templates/Game/res/skybox/front.jpg deleted file mode 100644 index 4e17b779..00000000 Binary files a/editor/templates/Game/res/skybox/front.jpg and /dev/null differ diff --git a/editor/templates/Game/res/skybox/left.jpg b/editor/templates/Game/res/skybox/left.jpg deleted file mode 100644 index 5750b91a..00000000 Binary files a/editor/templates/Game/res/skybox/left.jpg and /dev/null differ diff --git a/editor/templates/Game/res/skybox/right.jpg b/editor/templates/Game/res/skybox/right.jpg deleted file mode 100644 index 89630371..00000000 Binary files a/editor/templates/Game/res/skybox/right.jpg and /dev/null differ diff --git a/editor/templates/Game/res/skybox/top.jpg b/editor/templates/Game/res/skybox/top.jpg deleted file mode 100644 index 4db3c2a3..00000000 Binary files a/editor/templates/Game/res/skybox/top.jpg and /dev/null differ diff --git a/editor/templates/Game/shaders/window.ps b/editor/templates/Game/shaders/window.ps deleted file mode 100644 index c4a90f4f..00000000 Binary files a/editor/templates/Game/shaders/window.ps and /dev/null differ diff --git a/editor/templates/Game/shaders/window.vs b/editor/templates/Game/shaders/window.vs deleted file mode 100644 index 595e6f5d..00000000 --- a/editor/templates/Game/shaders/window.vs +++ /dev/null @@ -1,56 +0,0 @@ -#include ../engine_shaders/types.shader -#include ../engine_shaders/batching.shader -#include ../engine_shaders/transforming.shader -#include ../engine_shaders/controls/camera.shader - -struct VSIn -{ - float3 positionLocal : XPE_POSITION; - float2 uv : XPE_UV; - float3 normal : XPE_NORMAL; // normalized - float3 tangent : XPE_TANGENT; // normalized - uint instanceIndex : SV_InstanceID; -}; - -struct VSOut -{ - float3 positionWorld : XPE_POSITION_WORLD; - float2 uv : XPE_UV2; - float3 normal : XPE_NORMAL_WORLD; - float4 positionClip : SV_POSITION; - float3 viewPosition : XPE_VIEW_POSITION; - uint materialIndex : XPE_MATERIAL_INDEX; - float3x3 tbn : XPE_TBN; - float gamma : XPE_GAMMA; -}; - -VSOut vs_main(VSIn vsIn) -{ - VSOut vsOut = (VSOut)0; - - RenderInstance instance = Instances[vsIn.instanceIndex]; - float4x4 worldMatrix = Transforms[instance.TransformIndex].ModelMatrix; - float4x4 worldNormalMatrix = Transforms[instance.TransformIndex].NormalMatrix; - Camera camera = Cameras[instance.CameraIndex]; - - float4 positionWorld = mul(worldMatrix, float4(vsIn.positionLocal, 1.0)); - float4 positionView = mul(camera.View, positionWorld); - float4 positionClip = mul(camera.Projection, positionView); - - float3 normalWorld = mul(worldNormalMatrix, float4(vsIn.normal, 1.0)).xyz; - float3 tangentWorld = mul(worldNormalMatrix, float4(vsIn.tangent, 1.0)).xyz; - normalWorld = normalize(normalWorld); - tangentWorld = normalize(tangentWorld); - float3 bitangentWorld = -cross(normalWorld, tangentWorld); - - vsOut.positionWorld = positionWorld.xyz; - vsOut.uv = vsIn.uv; - vsOut.normal = normalWorld.xyz; - vsOut.positionClip = positionClip; - vsOut.viewPosition = camera.Position; - vsOut.materialIndex = instance.MaterialIndex; - vsOut.tbn = float3x3(tangentWorld, bitangentWorld, normalWorld); - vsOut.gamma = camera.Gamma; - - return vsOut; -} \ No newline at end of file diff --git a/editor/templates/Game/shaders/window2d.ps b/editor/templates/Game/shaders/window2d.ps deleted file mode 100644 index fc156915..00000000 Binary files a/editor/templates/Game/shaders/window2d.ps and /dev/null differ diff --git a/editor/templates/Game/shaders/window2d.vs b/editor/templates/Game/shaders/window2d.vs deleted file mode 100644 index fe59f1e3..00000000 --- a/editor/templates/Game/shaders/window2d.vs +++ /dev/null @@ -1,40 +0,0 @@ -#include ../engine_shaders/types.shader -#include ../engine_shaders/batching.shader -#include ../engine_shaders/transforming.shader -#include ../engine_shaders/controls/camera.shader - -struct VSIn -{ - float2 positionLocal : XPE_POSITION_2D; - float2 uv : XPE_UV; - uint instanceIndex : SV_InstanceID; -}; - -struct VSOut -{ - float2 positionWorld : XPE_POSITION_WORLD; - float2 uv : XPE_UV2; - float4 positionClip : SV_POSITION; - float2 viewPosition : XPE_VIEW_POSITION; -}; - -VSOut vs_main(VSIn vsIn) -{ - VSOut vsOut = (VSOut)0; - RenderInstance2D instance = Instances2D[vsIn.instanceIndex]; - float3x3 worldMatrix = Transforms2D[instance.TransformIndex].ModelMatrix; - Camera camera = Cameras[instance.CameraIndex]; - - float4 positionWorld = float4(mul(worldMatrix, float3(vsIn.positionLocal, 1.0)), 1.0); - float4 positionView = mul(camera.View, positionWorld); - positionView.z = 1.0; - positionView.w = 1.0; - float4 positionClip = mul(camera.Projection, positionView); - - vsOut.positionWorld = positionWorld.xy; - vsOut.viewPosition = camera.Position.xy; - vsOut.uv = vsIn.uv; - vsOut.positionClip = positionClip; - - return vsOut; -} \ No newline at end of file diff --git a/engine/CMakeLists.txt b/engine/CMakeLists.txt index 049b3316..091aed55 100644 --- a/engine/CMakeLists.txt +++ b/engine/CMakeLists.txt @@ -12,7 +12,24 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17 -O3") build_engine_dll() # Add engine sources -file(GLOB_RECURSE SOURCE_FILES src/*.c src/*.cpp) +file(GLOB_RECURSE SOURCE_FILES + src/*.c src/*.cpp + + thirdparty/imgui/imgui.cpp + thirdparty/imgui/imgui_draw.cpp + thirdparty/imgui/imgui_tables.cpp + thirdparty/imgui/imgui_widgets.cpp + thirdparty/imgui/imgui_demo.cpp + thirdparty/imgui/backends/imgui_impl_glfw.cpp + thirdparty/imgui/backends/imgui_impl_dx11.cpp + thirdparty/imgui/misc/cpp/imgui_stdlib.cpp + + thirdparty/ImGuizmo/ImGuizmo.cpp + thirdparty/ImGuizmo/ImGradient.cpp + thirdparty/ImGuizmo/ImSequencer.cpp + thirdparty/ImGuizmo/ImCurveEdit.cpp + thirdparty/ImGuizmo/GraphEditor.cpp +) file(GLOB_RECURSE HEADER_FILES src/*.h src/*.hpp) # Include third party dependency headers @@ -30,6 +47,10 @@ include_directories( thirdparty/stbi thirdparty/pugixml/src thirdparty/entt/src + thirdparty/Assimp142/include + thirdparty/Freetype/include + thirdparty/imgui + thirdparty/ImGuizmo ) # Create shared dynamic library @@ -52,7 +73,7 @@ add_subdirectory(thirdparty/entt) # Link libraries target_link_libraries(${PROJECT_NAME} PRIVATE gdi32 d3d11 d3dcompiler) target_link_libraries(${PROJECT_NAME} PUBLIC spdlog glfw glm nlohmann_json OpenAL sndfile pugixml EnTT) - +target_link_libraries(${PROJECT_NAME} PUBLIC ${CMAKE_BINARY_DIR}/lib/assimp-vc142-mt.lib ${CMAKE_BINARY_DIR}/lib/freetype.lib sndfile) # Link PhysX SDK target_link_libraries(${PROJECT_NAME} PUBLIC PhysX @@ -124,8 +145,22 @@ if(EXISTS ${CMAKE_BINARY_DIR}/lib/bin/win.x86_64.vc143.mt/release/PhysXFoundatio file(COPY_FILE ${CMAKE_BINARY_DIR}/lib/bin/win.x86_64.vc143.mt/release/PhysXFoundation.dll ${CMAKE_BINARY_DIR}/bin/Release/PhysXFoundation.dll) endif() +configure_file(${CMAKE_SOURCE_DIR}/engine/thirdparty/Assimp142/lib/Release/assimp-vc142-mt.lib ${CMAKE_BINARY_DIR}/lib/assimp-vc142-mt.lib COPYONLY) +configure_file(${CMAKE_SOURCE_DIR}/engine/thirdparty/Assimp142/bin/Release/assimp-vc142-mt.dll ${CMAKE_BINARY_DIR}/bin/Debug/assimp-vc142-mt.dll COPYONLY) +configure_file(${CMAKE_SOURCE_DIR}/engine/thirdparty/Assimp142/bin/Release/assimp-vc142-mt.dll ${CMAKE_BINARY_DIR}/bin/Release/assimp-vc142-mt.dll COPYONLY) + +configure_file(${CMAKE_SOURCE_DIR}/engine/thirdparty/Freetype/lib/freetype.lib ${CMAKE_BINARY_DIR}/lib/freetype.lib COPYONLY) +configure_file(${CMAKE_SOURCE_DIR}/engine/thirdparty/Freetype/bin/freetype.dll ${CMAKE_BINARY_DIR}/bin/Debug/freetype.dll COPYONLY) +configure_file(${CMAKE_SOURCE_DIR}/engine/thirdparty/Freetype/bin/freetype.dll ${CMAKE_BINARY_DIR}/bin/Release/freetype.dll COPYONLY) + # Move shaders into bin folder -copy_engine_shaders(engine) +copy_build_dir(engine/res/shaders res/shaders) +foreach(CONFIG ${CMAKE_CONFIGURATION_TYPES}) + copy_build_dir(engine/res/shaders ${CONFIG}/res/shaders) +endforeach() + +# Move editor res into bin folder +copy_build_dir(engine/editor_res editor_res) foreach(CONFIG ${CMAKE_CONFIGURATION_TYPES}) - copy_engine_shaders_to_config(engine ${CONFIG}) + copy_build_dir(engine/editor_res ${CONFIG}/editor_res) endforeach() \ No newline at end of file diff --git a/engine/cmake_tools/CMakeLists.txt b/engine/cmake_tools/CMakeLists.txt index d55b54e5..a3b3f2fd 100644 --- a/engine/cmake_tools/CMakeLists.txt +++ b/engine/cmake_tools/CMakeLists.txt @@ -2,7 +2,7 @@ macro(add_engine_configs) # define all engine build config types - set(CMAKE_CONFIGURATION_TYPES Debug;Release;) + set(CMAKE_CONFIGURATION_TYPES Debug;Release;EditorDebug;EditorRelease) set(LIB_PATH ${CMAKE_BINARY_DIR}/lib) set(BIN_PATH ${CMAKE_BINARY_DIR}/bin) @@ -22,6 +22,12 @@ macro(add_engine_configs) foreach(CONFIG ${CMAKE_CONFIGURATION_TYPES}) + if (${CONFIG} MATCHES "EditorDebug") + set(CONFIG "Debug") + elseif(${CONFIG} MATCHES "EditorRelease") + set(CONFIG "Release") + endif() + message(STATUS "Configuration=${CONFIG}") string(TOUPPER ${CONFIG} UPPER_CONFIG) @@ -36,10 +42,21 @@ endmacro() # add engine definitions macro(add_engine_definitions) add_engine_configs() - add_compile_definitions($<$:DEBUG>) + + add_compile_definitions($<$:K_EDITOR>) + add_compile_definitions($<$:K_EDITOR>) + + add_compile_definitions($<$:K_DEBUG>) add_compile_definitions($<$:PX_DEBUG>) add_compile_definitions($<$:PX_CHECKED>) add_compile_definitions($<$:PX_DEBUG_CRT>) + add_compile_definitions($<$:K_PROFILER>) + + add_compile_definitions($<$:K_DEBUG>) + add_compile_definitions($<$:PX_DEBUG>) + add_compile_definitions($<$:PX_CHECKED>) + add_compile_definitions($<$:PX_DEBUG_CRT>) + add_compile_definitions($<$:K_PROFILER>) endmacro() # copying target dir to destination dir. If destination does not exist, create it. @@ -172,11 +189,13 @@ endmacro() # add DLL_BUILD macro to define engine build as DLL macro(build_engine_dll) add_definitions(-DENGINE_DLL_BUILD=1) + add_definitions(-DASSIMP_DLL=1) endmacro() # include engine and all it's dependencies and also defines engine as DLL import # provide path to engine project macro(include_engine path) + add_definitions(-DASSIMP_DLL=1) add_definitions(-DENGINE_DLL=1) include_directories( ${path}/src @@ -192,6 +211,10 @@ macro(include_engine path) ${path}/thirdparty/stbi ${path}/thirdparty/pugixml/src ${path}/thirdparty/entt/src + ${path}/thirdparty/Assimp142/include + ${path}/thirdparty/Freetype/include + ${path}/thirdparty/imgui + ${path}/thirdparty/ImGuizmo ) endmacro() @@ -227,10 +250,79 @@ macro(link_engine project path) endmacro() -macro(copy_engine_shaders path) - copy_build_dir(${path}/engine_shaders engine_shaders) +# set all config types available in gamelib project +macro(add_gamelib_configs) + + # define all gamelib build config types + set(CMAKE_CONFIGURATION_TYPES Debug;Release;) + + set(LIB_PATH ${CMAKE_BINARY_DIR}/lib) + set(BIN_PATH ${CMAKE_BINARY_DIR}/bin) + + set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${LIB_PATH}) + set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${BIN_PATH}) + set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${BIN_PATH}) + + message(STATUS "Setting configuration types : ${CMAKE_CONFIGURATION_TYPES}") + + foreach(CONFIG ${CMAKE_CONFIGURATION_TYPES}) + + message(STATUS "Configuration=${CONFIG}") + + string(TOUPPER ${CONFIG} UPPER_CONFIG) + + message(STATUS "Setting runtime output path ${BIN_PATH}/${CONFIG}") + set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_${UPPER_CONFIG} ${BIN_PATH}/${CONFIG}) + + endforeach() + +endmacro() + +# add gamelib definitions +macro(add_gamelib_definitions) + add_gamelib_configs() + add_compile_definitions($<$:DEBUG>) endmacro() -macro(copy_engine_shaders_to_config path config) - copy_build_dir(${path}/engine_shaders ${config}/engine_shaders) +# add DLL_BUILD macro to define gamelib build as DLL +macro(build_gamelib_dll) + add_definitions(-DGAMELIB_DLL_BUILD=1) +endmacro() + +# include gamelib and all it's dependencies and also defines gamelib as DLL import +# provide path to gamelib project +macro(include_gamelib path) + add_definitions(-DGAMELIB_DLL=1) + include_directories(${path}) +endmacro() + +# link target project with gamelib +# provide your project name and path to gamelib project +macro(link_gamelib project path gamelib) + get_filename_component(dir_name ${PROJECT_BINARY_DIR} NAME) + + ## ---------------- Debug --------------- + + if (EXISTS ${PROJECT_BINARY_DIR}/${path}/Debug/${gamelib}.lib) + configure_file(${PROJECT_BINARY_DIR}/${path}/Debug/${gamelib}.lib ${PROJECT_BINARY_DIR}/Debug/${gamelib}.lib COPYONLY) + endif() + + if (EXISTS ${PROJECT_BINARY_DIR}/${path}/Debug/${gamelib}.dll) + configure_file(${PROJECT_BINARY_DIR}/${path}/Debug/${gamelib}.dll ${PROJECT_BINARY_DIR}/Debug/${gamelib}.dll COPYONLY) + endif() + + ## ---------------- Release --------------- + + if (EXISTS ${PROJECT_BINARY_DIR}/${path}/Release/${gamelib}.lib) + configure_file(${PROJECT_BINARY_DIR}/${path}/Release/${gamelib}.lib ${PROJECT_BINARY_DIR}/Release/${gamelib}.lib COPYONLY) + endif() + + if (EXISTS ${PROJECT_BINARY_DIR}/${path}/Release/${gamelib}.dll) + configure_file(${PROJECT_BINARY_DIR}/${path}/Release/${gamelib}.dll ${PROJECT_BINARY_DIR}/Release/${gamelib}.dll COPYONLY) + endif() + + message(STATUS "Linking ${project} -> ${gamelib}.lib") + message(STATUS "Linking ${project} -> ${gamelib}.dll") + target_link_libraries(${project} PUBLIC ${gamelib}) + endmacro() \ No newline at end of file diff --git a/engine/editor_res/cpp_icon.png b/engine/editor_res/cpp_icon.png new file mode 100644 index 00000000..85fef744 Binary files /dev/null and b/engine/editor_res/cpp_icon.png differ diff --git a/engine/editor_res/dir_icon.png b/engine/editor_res/dir_icon.png new file mode 100644 index 00000000..2762fc1b Binary files /dev/null and b/engine/editor_res/dir_icon.png differ diff --git a/engine/editor_res/file_icon.png b/engine/editor_res/file_icon.png new file mode 100644 index 00000000..2659e686 Binary files /dev/null and b/engine/editor_res/file_icon.png differ diff --git a/engine/editor_res/light_icon.png b/engine/editor_res/light_icon.png new file mode 100644 index 00000000..0c57b0f2 Binary files /dev/null and b/engine/editor_res/light_icon.png differ diff --git a/engine/editor_res/ttf_icon.png b/engine/editor_res/ttf_icon.png new file mode 100644 index 00000000..b9c2e30c Binary files /dev/null and b/engine/editor_res/ttf_icon.png differ diff --git a/engine/engine_shaders/camera.shader b/engine/res/shaders/camera.shader similarity index 100% rename from engine/engine_shaders/camera.shader rename to engine/res/shaders/camera.shader diff --git a/engine/engine_shaders/passes/canvas.ps b/engine/res/shaders/canvas.ps similarity index 100% rename from engine/engine_shaders/passes/canvas.ps rename to engine/res/shaders/canvas.ps diff --git a/engine/engine_shaders/passes/composite_pass_ao.ps b/engine/res/shaders/composite_ao.ps similarity index 100% rename from engine/engine_shaders/passes/composite_pass_ao.ps rename to engine/res/shaders/composite_ao.ps diff --git a/engine/engine_shaders/passes/composite_pass_transparent.ps b/engine/res/shaders/composite_transparent.ps similarity index 96% rename from engine/engine_shaders/passes/composite_pass_transparent.ps rename to engine/res/shaders/composite_transparent.ps index 24519181..a02eafbe 100644 Binary files a/engine/engine_shaders/passes/composite_pass_transparent.ps and b/engine/res/shaders/composite_transparent.ps differ diff --git a/engine/engine_shaders/passes/directional_shadow_pass.ps b/engine/res/shaders/directional_shadow.ps similarity index 72% rename from engine/engine_shaders/passes/directional_shadow_pass.ps rename to engine/res/shaders/directional_shadow.ps index 56ef4f18..2671b411 100644 Binary files a/engine/engine_shaders/passes/directional_shadow_pass.ps and b/engine/res/shaders/directional_shadow.ps differ diff --git a/engine/engine_shaders/passes/directional_shadow_pass.vs b/engine/res/shaders/directional_shadow.vs similarity index 92% rename from engine/engine_shaders/passes/directional_shadow_pass.vs rename to engine/res/shaders/directional_shadow.vs index a81129ec..16c30a32 100644 --- a/engine/engine_shaders/passes/directional_shadow_pass.vs +++ b/engine/res/shaders/directional_shadow.vs @@ -1,7 +1,7 @@ -#include ../types.shader -#include ../instancing.shader -#include ../skeleton.shader -#include ../lighting.shader +#include types.shader +#include instancing.shader +#include skeleton.shader +#include lighting.shader struct VSIn { diff --git a/engine/engine_shaders/passes/final_pass.ps b/engine/res/shaders/final.ps similarity index 95% rename from engine/engine_shaders/passes/final_pass.ps rename to engine/res/shaders/final.ps index eaee93ea..92b7d939 100644 Binary files a/engine/engine_shaders/passes/final_pass.ps and b/engine/res/shaders/final.ps differ diff --git a/engine/engine_shaders/gamma_correction.shader b/engine/res/shaders/gamma_correction.shader similarity index 100% rename from engine/engine_shaders/gamma_correction.shader rename to engine/res/shaders/gamma_correction.shader diff --git a/engine/engine_shaders/passes/geometry_pass.vs b/engine/res/shaders/geometry.vs similarity index 96% rename from engine/engine_shaders/passes/geometry_pass.vs rename to engine/res/shaders/geometry.vs index c72cd417..617ae537 100644 --- a/engine/engine_shaders/passes/geometry_pass.vs +++ b/engine/res/shaders/geometry.vs @@ -1,7 +1,7 @@ -#include ../types.shader -#include ../instancing.shader -#include ../camera.shader -#include ../skeleton.shader +#include types.shader +#include instancing.shader +#include camera.shader +#include skeleton.shader struct VSIn { diff --git a/engine/engine_shaders/instancing.shader b/engine/res/shaders/instancing.shader similarity index 100% rename from engine/engine_shaders/instancing.shader rename to engine/res/shaders/instancing.shader diff --git a/engine/engine_shaders/lighting.shader b/engine/res/shaders/lighting.shader similarity index 56% rename from engine/engine_shaders/lighting.shader rename to engine/res/shaders/lighting.shader index 2011816d..595bf218 100644 --- a/engine/engine_shaders/lighting.shader +++ b/engine/res/shaders/lighting.shader @@ -19,7 +19,8 @@ struct PointLight StructuredBuffer PointLights : K_SLOT_POINT_LIGHTS; -float Attenuation(PointLight pointLight) { +float Attenuation(PointLight pointLight) +{ float d = length(pointLight.Position - W); float q = pointLight.Quadratic; float l = pointLight.Linear; @@ -37,16 +38,22 @@ struct SpotLight float4x4 ViewProjection; float Near; float Far; + float Constant; + float Linear; + float Quadratic; }; StructuredBuffer SpotLights : K_SLOT_SPOT_LIGHTS; -float Attenuation(SpotLight spotLight) { - float3 lightDir = normalize(spotLight.Position - W); - float3 spotDir = normalize(-spotLight.Direction); - float theta = dot(lightDir, spotDir); - float cutoff = spotLight.Cutoff; - float gamma = spotLight.Outer; - float epsilon = cutoff - gamma; - return clamp((theta - gamma) / epsilon, 0.0, 1.0); -} +float Attenuation(float3 lightDir, SpotLight spotLight) +{ + float theta = dot(lightDir, normalize(-spotLight.Direction)); + float epsilon = (spotLight.InnerCutoff - spotLight.OuterCutoff); + float intensity = clamp((theta - spotLight.OuterCutoff) / epsilon, 0.0, 1.0); + float d = length(spotLight.Position - W); + float q = spotLight.Quadratic; + float l = spotLight.Linear; + float c = spotLight.Constant; + float attenuation = 1.0 / ( q * d * d + l * d + c ); + return attenuation * intensity; +} \ No newline at end of file diff --git a/engine/engine_shaders/material.shader b/engine/res/shaders/material.shader similarity index 100% rename from engine/engine_shaders/material.shader rename to engine/res/shaders/material.shader diff --git a/engine/engine_shaders/passes/msaa/composite_pass_transparent.ps b/engine/res/shaders/msaa_composite_transparent.ps similarity index 95% rename from engine/engine_shaders/passes/msaa/composite_pass_transparent.ps rename to engine/res/shaders/msaa_composite_transparent.ps index 646eb744..c79d086b 100644 Binary files a/engine/engine_shaders/passes/msaa/composite_pass_transparent.ps and b/engine/res/shaders/msaa_composite_transparent.ps differ diff --git a/engine/engine_shaders/passes/msaa/final_pass.ps b/engine/res/shaders/msaa_final.ps similarity index 93% rename from engine/engine_shaders/passes/msaa/final_pass.ps rename to engine/res/shaders/msaa_final.ps index 3ebb7058..d8734f2c 100644 Binary files a/engine/engine_shaders/passes/msaa/final_pass.ps and b/engine/res/shaders/msaa_final.ps differ diff --git a/engine/engine_shaders/passes/msaa/msaa_sampling.shader b/engine/res/shaders/msaa_sampling.shader similarity index 96% rename from engine/engine_shaders/passes/msaa/msaa_sampling.shader rename to engine/res/shaders/msaa_sampling.shader index 803280e9..7c566aa5 100644 --- a/engine/engine_shaders/passes/msaa/msaa_sampling.shader +++ b/engine/res/shaders/msaa_sampling.shader @@ -1,50 +1,50 @@ -float SampleMSAATextureFloat(Texture2DMS msaaTexture, float2 uv) -{ - uint width = 0; - uint height = 0; - uint sampleCount = 0; - msaaTexture.GetDimensions(width, height, sampleCount); - - float averageColor = 0.0; - for (int i = 0; i < int(sampleCount); i++) - { - averageColor += msaaTexture.Load(int2(uv * float2(width, height)), i); - } - averageColor *= 1.0 / float(sampleCount); - - return averageColor; -} - -float3 SampleMSAATextureFloat3(Texture2DMS msaaTexture, float2 uv) -{ - uint width = 0; - uint height = 0; - uint sampleCount = 0; - msaaTexture.GetDimensions(width, height, sampleCount); - - float3 averageColor = float3(0.0, 0.0, 0.0); - for (int i = 0; i < int(sampleCount); i++) - { - averageColor += msaaTexture.Load(int2(uv * float2(width, height)), i).xyz; - } - averageColor *= 1.0 / float(sampleCount); - - return averageColor; -} - -float4 SampleMSAATextureFloat4(Texture2DMS msaaTexture, float2 uv) -{ - uint width = 0; - uint height = 0; - uint sampleCount = 0; - msaaTexture.GetDimensions(width, height, sampleCount); - - float4 averageColor = float4(0.0, 0.0, 0.0, 0.0); - for (int i = 0; i < int(sampleCount); i++) - { - averageColor += msaaTexture.Load(int2(uv * float2(width, height)), i); - } - averageColor *= 1.0 / float(sampleCount); - - return averageColor; +float SampleMSAATextureFloat(Texture2DMS msaaTexture, float2 uv) +{ + uint width = 0; + uint height = 0; + uint sampleCount = 0; + msaaTexture.GetDimensions(width, height, sampleCount); + + float averageColor = 0.0; + for (int i = 0; i < int(sampleCount); i++) + { + averageColor += msaaTexture.Load(int2(uv * float2(width, height)), i); + } + averageColor *= 1.0 / float(sampleCount); + + return averageColor; +} + +float3 SampleMSAATextureFloat3(Texture2DMS msaaTexture, float2 uv) +{ + uint width = 0; + uint height = 0; + uint sampleCount = 0; + msaaTexture.GetDimensions(width, height, sampleCount); + + float3 averageColor = float3(0.0, 0.0, 0.0); + for (int i = 0; i < int(sampleCount); i++) + { + averageColor += msaaTexture.Load(int2(uv * float2(width, height)), i).xyz; + } + averageColor *= 1.0 / float(sampleCount); + + return averageColor; +} + +float4 SampleMSAATextureFloat4(Texture2DMS msaaTexture, float2 uv) +{ + uint width = 0; + uint height = 0; + uint sampleCount = 0; + msaaTexture.GetDimensions(width, height, sampleCount); + + float4 averageColor = float4(0.0, 0.0, 0.0, 0.0); + for (int i = 0; i < int(sampleCount); i++) + { + averageColor += msaaTexture.Load(int2(uv * float2(width, height)), i); + } + averageColor *= 1.0 / float(sampleCount); + + return averageColor; } \ No newline at end of file diff --git a/engine/engine_shaders/passes/msaa/ssao_pass.ps b/engine/res/shaders/msaa_ssao.ps similarity index 98% rename from engine/engine_shaders/passes/msaa/ssao_pass.ps rename to engine/res/shaders/msaa_ssao.ps index 8846f098..72a0d345 100644 Binary files a/engine/engine_shaders/passes/msaa/ssao_pass.ps and b/engine/res/shaders/msaa_ssao.ps differ diff --git a/engine/engine_shaders/pbr.shader b/engine/res/shaders/pbr.shader similarity index 95% rename from engine/engine_shaders/pbr.shader rename to engine/res/shaders/pbr.shader index 176f2e89..242dcc7e 100644 --- a/engine/engine_shaders/pbr.shader +++ b/engine/res/shaders/pbr.shader @@ -83,7 +83,7 @@ float3 PBR(PointLight pointLight, float3 albedo, float metallness, float roughne L = normalize(pointLight.Position - W); float3 lightColor = pointLight.Color; float A = Attenuation(pointLight); - float pointShadow = 1.0; + float pointShadow = GetPointShadow(L, ToLightSpace(W, pointLight.ViewProjection)); float radianceFactor = A * pointShadow; return PBR(lightColor, radianceFactor, albedo, metallness, roughness); @@ -93,9 +93,9 @@ float3 PBR(SpotLight spotLight, float3 albedo, float metallness, float roughness { L = normalize(spotLight.Position - W); float3 lightColor = spotLight.Color; - float A = Attenuation(spotLight); + float A = Attenuation(L, spotLight); float spotShadow = GetSpotShadow(L, ToLightSpace(W, spotLight.ViewProjection)); - float radianceFactor = A * spotShadow; + float radianceFactor = A; return PBR(lightColor, radianceFactor, albedo, metallness, roughness); } \ No newline at end of file diff --git a/engine/engine_shaders/passes/pbr_pass_opaque.ps b/engine/res/shaders/pbr_opaque.ps similarity index 93% rename from engine/engine_shaders/passes/pbr_pass_opaque.ps rename to engine/res/shaders/pbr_opaque.ps index 4c59d8d3..d7a36fa3 100644 Binary files a/engine/engine_shaders/passes/pbr_pass_opaque.ps and b/engine/res/shaders/pbr_opaque.ps differ diff --git a/engine/engine_shaders/passes/pbr_pass_transparent.ps b/engine/res/shaders/pbr_transparent.ps similarity index 93% rename from engine/engine_shaders/passes/pbr_pass_transparent.ps rename to engine/res/shaders/pbr_transparent.ps index 14bf3f87..cffd2695 100644 Binary files a/engine/engine_shaders/passes/pbr_pass_transparent.ps and b/engine/res/shaders/pbr_transparent.ps differ diff --git a/engine/res/shaders/point_shadow.ps b/engine/res/shaders/point_shadow.ps new file mode 100644 index 00000000..165771e2 Binary files /dev/null and b/engine/res/shaders/point_shadow.ps differ diff --git a/engine/res/shaders/point_shadow.vs b/engine/res/shaders/point_shadow.vs new file mode 100644 index 00000000..1273acd6 --- /dev/null +++ b/engine/res/shaders/point_shadow.vs @@ -0,0 +1,58 @@ +#include types.shader +#include instancing.shader +#include skeleton.shader +#include lighting.shader + +struct VSIn +{ + float3 positionLocal : XPE_POSITION; + int4 boneIds : XPE_BONE_IDS; // boneId = -1 - bone absent + float4 boneWeights : XPE_BONE_WEIGHTS; + uint instanceIndex : SV_InstanceID; +}; + +struct VSOut +{ + float4 positionLight : SV_POSITION; + float4 positionWorld : XPE_POSITION_WORLD; + float4 lightPositionWorld : XPE_LIGHT_POSITION_WORLD; +}; + +VSOut vs_main(VSIn vsIn) +{ + VSOut vsOut; + + float4 positionTotal = float4(0, 0, 0, 0); + float4 positionBone = float4(vsIn.positionLocal, 1.0); + int4 boneIds = vsIn.boneIds; + float4 boneWeights = vsIn.boneWeights; + RenderInstance instance = Instances[vsIn.instanceIndex]; + uint skeletonIndex = instance.SkeletonIndex; + + for (int i = 0 ; i < 4 ; i++) + { + int boneID = boneIds[i]; + float boneWeight = boneWeights[i]; + + if (boneID == -1) + continue; + + float4x4 boneTransform = Skeletons[boneID + skeletonIndex].Transform; + + positionTotal += mul(boneTransform, float4(vsIn.positionLocal, 1.0)) * boneWeight; + positionBone = positionTotal; + } + + float4x4 worldMatrix = instance.ModelMatrix; + PointLight light = PointLights[instance.LightIndex]; + float4x4 lightMatrix = light.ViewProjection; + + float4 positionWorld = mul(worldMatrix, float4(positionBone.xyz, 1.0)); + float4 positionLight = mul(lightMatrix, float4(positionWorld.xyz, 1.0)); + + vsOut.positionLight = positionLight; + vsOut.positionWorld = positionWorld; + vsOut.lightPositionWorld = float4(light.Position, 1.0); + + return vsOut; +} \ No newline at end of file diff --git a/engine/engine_shaders/passes/screen.vs b/engine/res/shaders/screen.vs similarity index 100% rename from engine/engine_shaders/passes/screen.vs rename to engine/res/shaders/screen.vs diff --git a/engine/engine_shaders/shadow.shader b/engine/res/shaders/shadow.shader similarity index 68% rename from engine/engine_shaders/shadow.shader rename to engine/res/shaders/shadow.shader index b1fe3fcc..125cfb78 100644 --- a/engine/engine_shaders/shadow.shader +++ b/engine/res/shaders/shadow.shader @@ -2,39 +2,43 @@ SamplerState ShadowSampler : K_SLOT_SHADOW_SAMPLER; Texture2D ShadowAtlas : K_SLOT_SHADOW_ATLAS; cbuffer ShadowPCF : K_SLOT_SHADOW_PCF { - int PcfFilterSize = 0; - float PcfMinBias = 0.005; - float PcfMaxBias = 0.05; + float PcfMinBias; + float PcfMaxBias; + bool EnablePCF; }; +Texture2D ShadowCircleFilter : K_SLOT_SHADOW_CIRCLE_FILTER; float ShadowMapping( float3 lightDir, float3 positionLightSpace, Texture2D shadowMap, - SamplerState shadowSampler, - int filterSize + SamplerState shadowSampler ) { float posZ = positionLightSpace.z; float bias = max(PcfMaxBias * (1.0 - dot(N, lightDir)), PcfMinBias); float shadow = 0.0; // mapping with PCF - if (filterSize > 0) { + if (EnablePCF) { + int3 offsetCoord; + float size; + int filterSize = 3; + int samplesDiv2 = filterSize * filterSize / 2; float w; float h; ShadowAtlas.GetDimensions(w, h); float2 texelSize = 1.0 / float2(w, h); [loop] - for (int x = -filterSize; x <= filterSize; x++) + for (int x = -1; x <= 1; x++) { [loop] - for (int y = -filterSize; y <= filterSize; y++) + for (int y = -1; y <= 1; y++) { float depth = shadowMap.Sample(shadowSampler, positionLightSpace.xy + float2(x, y) * texelSize).r; shadow += (depth + bias) < posZ ? 0.0 : 1.0; } } - shadow /= (filterSize * filterSize); + shadow /= 9; } // mapping without PCF else { @@ -47,10 +51,15 @@ float ShadowMapping( float GetDirectionalShadow(float3 lightDir, float3 positionLightSpace) { - return ShadowMapping(lightDir, positionLightSpace, ShadowAtlas, ShadowSampler, PcfFilterSize); + return ShadowMapping(lightDir, positionLightSpace, ShadowAtlas, ShadowSampler); +} + +float GetPointShadow(float3 lightDir, float3 lightDistance) +{ + return ShadowMapping(lightDir, lightDistance, ShadowAtlas, ShadowSampler); } float GetSpotShadow(float3 lightDir, float3 positionLightSpace) { - return ShadowMapping(lightDir, positionLightSpace, ShadowAtlas, ShadowSampler, PcfFilterSize); + return ShadowMapping(lightDir, positionLightSpace, ShadowAtlas, ShadowSampler); } \ No newline at end of file diff --git a/engine/engine_shaders/skeleton.shader b/engine/res/shaders/skeleton.shader similarity index 100% rename from engine/engine_shaders/skeleton.shader rename to engine/res/shaders/skeleton.shader diff --git a/engine/engine_shaders/passes/skybox_pass.ps b/engine/res/shaders/skybox.ps similarity index 94% rename from engine/engine_shaders/passes/skybox_pass.ps rename to engine/res/shaders/skybox.ps index 69c5086c..00b9f030 100644 Binary files a/engine/engine_shaders/passes/skybox_pass.ps and b/engine/res/shaders/skybox.ps differ diff --git a/engine/engine_shaders/passes/skybox_pass.vs b/engine/res/shaders/skybox.vs similarity index 94% rename from engine/engine_shaders/passes/skybox_pass.vs rename to engine/res/shaders/skybox.vs index eb09b466..cc709359 100644 --- a/engine/engine_shaders/passes/skybox_pass.vs +++ b/engine/res/shaders/skybox.vs @@ -1,5 +1,5 @@ -#include ../types.shader -#include ../camera.shader +#include types.shader +#include camera.shader struct VSIn { diff --git a/engine/engine_shaders/passes/spot_shadow_pass.ps b/engine/res/shaders/spot_shadow.ps similarity index 94% rename from engine/engine_shaders/passes/spot_shadow_pass.ps rename to engine/res/shaders/spot_shadow.ps index 8859f777..05fcf0f8 100644 Binary files a/engine/engine_shaders/passes/spot_shadow_pass.ps and b/engine/res/shaders/spot_shadow.ps differ diff --git a/engine/engine_shaders/passes/spot_shadow_pass.vs b/engine/res/shaders/spot_shadow.vs similarity index 93% rename from engine/engine_shaders/passes/spot_shadow_pass.vs rename to engine/res/shaders/spot_shadow.vs index 48456fc8..ced8577c 100644 --- a/engine/engine_shaders/passes/spot_shadow_pass.vs +++ b/engine/res/shaders/spot_shadow.vs @@ -1,7 +1,7 @@ -#include ../types.shader -#include ../instancing.shader -#include ../skeleton.shader -#include ../lighting.shader +#include types.shader +#include instancing.shader +#include skeleton.shader +#include lighting.shader struct VSIn { diff --git a/engine/engine_shaders/passes/ssao_pass.ps b/engine/res/shaders/ssao.ps similarity index 98% rename from engine/engine_shaders/passes/ssao_pass.ps rename to engine/res/shaders/ssao.ps index ce4bd4bd..6feb4e0f 100644 Binary files a/engine/engine_shaders/passes/ssao_pass.ps and b/engine/res/shaders/ssao.ps differ diff --git a/engine/engine_shaders/ssao.shader b/engine/res/shaders/ssao.shader similarity index 100% rename from engine/engine_shaders/ssao.shader rename to engine/res/shaders/ssao.shader diff --git a/engine/engine_shaders/passes/text_pass.ps b/engine/res/shaders/text.ps similarity index 97% rename from engine/engine_shaders/passes/text_pass.ps rename to engine/res/shaders/text.ps index 15de8fe1..f11ad6d4 100644 Binary files a/engine/engine_shaders/passes/text_pass.ps and b/engine/res/shaders/text.ps differ diff --git a/engine/engine_shaders/passes/text_pass.vs b/engine/res/shaders/text.vs similarity index 98% rename from engine/engine_shaders/passes/text_pass.vs rename to engine/res/shaders/text.vs index 5279136a..fb4a4891 100644 --- a/engine/engine_shaders/passes/text_pass.vs +++ b/engine/res/shaders/text.vs @@ -1,4 +1,4 @@ -#include ../types.shader +#include types.shader struct Char { diff --git a/engine/engine_shaders/tonemap.shader b/engine/res/shaders/tonemap.shader similarity index 100% rename from engine/engine_shaders/tonemap.shader rename to engine/res/shaders/tonemap.shader diff --git a/engine/engine_shaders/types.shader b/engine/res/shaders/types.shader similarity index 96% rename from engine/engine_shaders/types.shader rename to engine/res/shaders/types.shader index 6b7bd1a3..d5ec6a43 100644 --- a/engine/engine_shaders/types.shader +++ b/engine/res/shaders/types.shader @@ -34,9 +34,11 @@ #define K_SLOT_SPOT_LIGHTS register(t10) // shadows -#define K_SLOT_SHADOW_ATLAS register(t11) -#define K_SLOT_SHADOW_SAMPLER register(s1) #define K_SLOT_SHADOW_PCF register(b0) +#define K_SLOT_SHADOW_SAMPLER register(s1) +#define K_SLOT_SHADOW_ATLAS register(t11) +#define K_SLOT_SHADOW_CIRCLE_FILTER register(t13) +#define K_SLOT_SHADOW_CIRCLE_SAMPLER register(s2) // ---------- Constant Buffer --------------- // diff --git a/engine/engine_shaders/passes/widget_pass.ps b/engine/res/shaders/widget.ps similarity index 95% rename from engine/engine_shaders/passes/widget_pass.ps rename to engine/res/shaders/widget.ps index 10d33f8e..ffe36ff1 100644 Binary files a/engine/engine_shaders/passes/widget_pass.ps and b/engine/res/shaders/widget.ps differ diff --git a/engine/engine_shaders/passes/widget_pass.vs b/engine/res/shaders/widget.vs similarity index 97% rename from engine/engine_shaders/passes/widget_pass.vs rename to engine/res/shaders/widget.vs index 77d08fbd..8c8b7d81 100644 --- a/engine/engine_shaders/passes/widget_pass.vs +++ b/engine/res/shaders/widget.vs @@ -1,4 +1,4 @@ -#include ../types.shader +#include types.shader struct Widget { diff --git a/editor/templates/Game/Code/CMakeLists.txt b/engine/scripts/CMakeLists.txt similarity index 72% rename from editor/templates/Game/Code/CMakeLists.txt rename to engine/scripts/CMakeLists.txt index 3376c575..cd7f2842 100644 --- a/editor/templates/Game/Code/CMakeLists.txt +++ b/engine/scripts/CMakeLists.txt @@ -1,30 +1,28 @@ cmake_minimum_required(VERSION 3.2) -set(GAME_NAME Game) set(ENGINE_PATH ../engine) -project(${GAME_NAME}Code) +project(GameLib) -include(${ENGINE_PATH}/cmake_tools/CMakeLists.txt) include(../cmake_tools/CMakeLists.txt) -build_game_dll() +build_gamelib_dll() -file(GLOB_RECURSE SOURCE_FILES cpp/*.c cpp/*.cpp) +file(GLOB_RECURSE SOURCE_FILES ../scripts/*.c ../scripts/*.cpp) -include_directories(include) +include_directories(../scripts) include_engine(${ENGINE_PATH}) add_library(${PROJECT_NAME} SHARED ${SOURCE_FILES}) add_engine_definitions() -add_game_definitions() +add_gamelib_definitions() link_engine(${PROJECT_NAME} ${ENGINE_PATH}) if (EXISTS ${CMAKE_BINARY_DIR}/bin/${PROJECT_NAME}.dll) configure_file(${CMAKE_BINARY_DIR}/bin/${PROJECT_NAME}.dll ${CMAKE_BINARY_DIR}/bin/${PROJECT_NAME}_Edit.dll COPYONLY) endif() -foreach(CONFIG ${CMAKE_CONFIGURATION_TYPES}) +foreach(config ${CMAKE_CONFIGURATION_TYPES}) if (EXISTS ${CMAKE_BINARY_DIR}/bin/${CONFIG}/${PROJECT_NAME}.dll) configure_file(${CMAKE_BINARY_DIR}/bin/${CONFIG}/${PROJECT_NAME}.dll ${CMAKE_BINARY_DIR}/bin/${CONFIG}/${PROJECT_NAME}_Edit.dll COPYONLY) endif() diff --git a/engine/scripts/game_system.cpp b/engine/scripts/game_system.cpp new file mode 100644 index 00000000..cf4c972b --- /dev/null +++ b/engine/scripts/game_system.cpp @@ -0,0 +1,6 @@ +#include + +extern "C" GAMELIB_API xpe::ecs::cSystem* _cdecl CreateGameSystem() +{ + return new cGameSystem(); +} \ No newline at end of file diff --git a/engine/scripts/game_system.hpp b/engine/scripts/game_system.hpp new file mode 100644 index 00000000..98c70cac --- /dev/null +++ b/engine/scripts/game_system.hpp @@ -0,0 +1,4 @@ +#include +#include + +class GAMELIB_API cGameSystem : xpe::ecs::cSystem {}; \ No newline at end of file diff --git a/engine/src/allocators.cpp b/engine/src/allocators.cpp new file mode 100644 index 00000000..09bd7b12 --- /dev/null +++ b/engine/src/allocators.cpp @@ -0,0 +1,41 @@ +#include + +namespace xpe +{ + namespace core + { + void* align16_alloc(usize size) + { +#ifdef WINDOWS + return _aligned_malloc(size, 16); +#elif LINUX + return ::memalign(16, size); +#else + return main_alloc(size); +#endif + } + + void align16_free(void* address) + { +#ifdef WINDOWS + return _aligned_free(address); +#elif LINUX + return ::free(address); +#else + return main_free(address); +#endif + } + + sStackAllocator::sStackAllocator(usize size) : Size(size) + { + MMemory::StackTotalAllocCount += 1; + MMemory::StackTotalBytes += size; + } + + sStackAllocator::~sStackAllocator() + { + MMemory::StackTotalAllocCount -= 1; + MMemory::StackTotalBytes -= Size; + } + } +} \ No newline at end of file diff --git a/engine/src/core/allocators.hpp b/engine/src/allocators.hpp similarity index 69% rename from engine/src/core/allocators.hpp rename to engine/src/allocators.hpp index a94489e6..17fad7e9 100644 --- a/engine/src/core/allocators.hpp +++ b/engine/src/allocators.hpp @@ -1,24 +1,24 @@ #pragma once -#define hot_alloc(size) xpe::core::cMemoryManager::HotPools->Allocate(size) +#define hot_alloc(size) xpe::core::MMemory::HotPools->Allocate(size) #define hot_allocT(T, count) static_cast(hot_alloc(sizeof(T) * count)) -#define hot_construct(T) xpe::core::cMemoryManager::HotPools->AllocateConstruct() -#define hot_construct_args(T, ...) xpe::core::cMemoryManager::HotPools->AllocateConstructArgs(__VA_ARGS__) -#define hot_free(addr) xpe::core::cMemoryManager::HotPools->Free(addr) +#define hot_construct(T) xpe::core::MMemory::HotPools->AllocateConstruct() +#define hot_construct_args(T, ...) xpe::core::MMemory::HotPools->AllocateConstructArgs(__VA_ARGS__) +#define hot_free(addr) xpe::core::MMemory::HotPools->Free(addr) #define hot_destruct(T, addr) \ addr->~T(); \ hot_free(addr) -#define main_alloc(size) xpe::core::cMemoryManager::MainPools->Allocate(size) +#define main_alloc(size) xpe::core::MMemory::MainPools->Allocate(size) #define main_allocT(T, count) static_cast(main_alloc(sizeof(T) * count)) -#define main_construct(T) xpe::core::cMemoryManager::MainPools->AllocateConstruct() -#define main_construct_args(T, ...) xpe::core::cMemoryManager::MainPools->AllocateConstructArgs(__VA_ARGS__) -#define main_free(addr) xpe::core::cMemoryManager::MainPools->Free(addr) +#define main_construct(T) xpe::core::MMemory::MainPools->AllocateConstruct() +#define main_construct_args(T, ...) xpe::core::MMemory::MainPools->AllocateConstructArgs(__VA_ARGS__) +#define main_free(addr) xpe::core::MMemory::MainPools->Free(addr) #define main_destruct(T, addr) \ addr->~T(); \ main_free(addr) -#ifdef DEBUG +#ifdef K_DEBUG #define TOKENPASTE(x, y) x ## y #define TOKENPASTE2(x, y) TOKENPASTE(x, y) @@ -28,8 +28,6 @@ main_free(addr) #define salloc(size) alloca(size); STACK(size) #define sallocT(T, count) static_cast(alloca(sizeof(T) * count)); STACKT(T, count) -#define LogStackMemory() xpe::core::cMemoryStackManager::Log() - #else #define salloc(size) alloca(size) @@ -43,7 +41,7 @@ namespace xpe { namespace core { - ENGINE_API void* align16_malloc(usize size); + ENGINE_API void* align16_alloc(usize size); ENGINE_API void align16_free(void* address); template @@ -70,10 +68,16 @@ namespace xpe { }; template - bool operator==(const cHotAllocator&, const cHotAllocator&) { return true; } + bool operator==(const cHotAllocator&, const cHotAllocator&) + { + return true; + } template - bool operator!=(const cHotAllocator&, const cHotAllocator&) { return false; } + bool operator!=(const cHotAllocator&, const cHotAllocator&) + { + return false; + } template class cMainAllocator @@ -99,18 +103,16 @@ namespace xpe { }; template - bool operator==(const cMainAllocator&, const cMainAllocator&) { return true; } + bool operator==(const cMainAllocator&, const cMainAllocator&) + { + return true; + } template - bool operator!=(const cMainAllocator&, const cMainAllocator&) { return false; } - - class ENGINE_API cMemoryStackManager final + bool operator!=(const cMainAllocator&, const cMainAllocator&) { - public: - static usize TotalAllocCount; - static usize MemoryOccupiedBytes; - static void Log(); - }; + return false; + } struct ENGINE_API sStackAllocator final { @@ -132,15 +134,15 @@ namespace xpe { template sStackTypedAllocator::sStackTypedAllocator(usize count) : Size(sizeof(T) * count) { - cMemoryStackManager::TotalAllocCount += 1; - cMemoryStackManager::MemoryOccupiedBytes += Size; + MMemory::StackTotalAllocCount += 1; + MMemory::StackTotalBytes += Size; } template sStackTypedAllocator::~sStackTypedAllocator() { - cMemoryStackManager::TotalAllocCount -= 1; - cMemoryStackManager::MemoryOccupiedBytes -= Size; + MMemory::StackTotalAllocCount -= 1; + MMemory::StackTotalBytes -= Size; } } diff --git a/engine/src/anim/anim.hpp b/engine/src/anim/anim.hpp deleted file mode 100644 index 44ce5a73..00000000 --- a/engine/src/anim/anim.hpp +++ /dev/null @@ -1,63 +0,0 @@ -#pragma once - -namespace xpe { - - namespace anim { - - using namespace core; - - struct ENGINE_API sKeyPosition final - { - float Timestamp; - glm::vec3 Position; - - sKeyPosition() = default; - sKeyPosition(float timestamp, const glm::vec3& position) : Timestamp(timestamp), Position(position) {} - }; - - JSON(sKeyPosition, Timestamp, Position) - - struct ENGINE_API sKeyRotate final - { - float Timestamp; - glm::quat Orientation; - - sKeyRotate() = default; - sKeyRotate(float timestamp, const glm::quat& orientation) : Timestamp(timestamp), Orientation(orientation) {} - }; - - JSON(sKeyRotate, Timestamp, Orientation) - - struct ENGINE_API sKeyScale final - { - float Timestamp; - glm::vec3 Scale; - - sKeyScale() = default; - sKeyScale(float timestamp, const glm::vec3& scale) : Timestamp(timestamp), Scale(scale) {} - }; - - JSON(sKeyScale, Timestamp, Scale) - - struct ENGINE_API sAnimationNode final - { - string Name; - glm::mat4 Transform; - vector Children; - }; - - JSON(sAnimationNode, Name, Transform, Children) - - struct ENGINE_API sAnimation - { - bool Play; - float Duration; - int TicksPerSecond; - sAnimationNode Root; - }; - - JSON(sAnimation, Duration, TicksPerSecond, Root) - - } - -} \ No newline at end of file diff --git a/engine/src/anim/anim_system.cpp b/engine/src/anim/anim_system.cpp deleted file mode 100644 index 113a2482..00000000 --- a/engine/src/anim/anim_system.cpp +++ /dev/null @@ -1,219 +0,0 @@ -#include -#include - -#include - -namespace xpe { - - namespace anim { - - void cAnimSystem::Update(cScene* scene, const cTime& dt) - { - auto components = scene->GetComponents(); - for (auto [entity, animation, skeleton, skeletonInfo] : components.each()) - { - for (auto& subAnimation : animation.Animations) { - if (subAnimation.Play) { - AnimateSkeleton(subAnimation, skeleton, skeletonInfo.SkeletonIndex, dt); - } - } - } - } - - void cAnimSystem::AnimateSkeleton(const sAnimation &animation, sSkeleton &skeleton, u32 skeletonIndex, const cTime& dt) - { - m_DeltaSeconds = dt.Seconds(); - m_CurrentSeconds += animation.TicksPerSecond * m_DeltaSeconds; - m_CurrentSeconds = fmod(m_CurrentSeconds, animation.Duration); - UpdateSkeletonTransform(animation.Root, skeleton, *Buffers::Skeleton, skeletonIndex, glm::mat4(1.0f)); - } - - void cAnimSystem::AnimateBone(sBone &bone, float time) - { - glm::mat4 translation = InterpolatePosition(bone, time); - glm::mat4 rotation = InterpolateRotation(bone, time); - glm::mat4 scale = InterpolateScale(bone, time); - bone.Transform = translation * rotation * scale; - } - - int cAnimSystem::GetPositionIndex(sBone &bone, float time) - { - usize count = bone.KeyPositions.size(); - - for (int i = 0; i < count; ++i) - { - if (time < bone.KeyPositions[i + 1].Timestamp) { - return i; - } - } - - return -1; - } - - int cAnimSystem::GetRotationIndex(sBone &bone, float time) - { - usize count = bone.KeyRotations.size(); - - for (int i = 0; i < count; ++i) - { - if (time < bone.KeyRotations[i + 1].Timestamp) { - return i; - } - } - - return -1; - } - - int cAnimSystem::GetScaleIndex(sBone &bone, float time) - { - usize count = bone.KeyScales.size(); - - for (int i = 0; i < count; ++i) - { - if (time < bone.KeyScales[i + 1].Timestamp) { - return i; - } - } - - return -1; - } - - float cAnimSystem::GetScaleFactor(float lastTimestamp, float nextTimestamp, float time) - { - float scaleFactor; - float midWayLength = time - lastTimestamp; - float framesDiff = nextTimestamp - lastTimestamp; - scaleFactor = midWayLength / framesDiff; - return scaleFactor; - } - - glm::mat4 cAnimSystem::InterpolatePosition(sBone &bone, float time) - { - auto& positions = bone.KeyPositions; - - if (positions.empty()) { - return glm::mat4(1.0f); - } - - if (positions.size() == 1) { - return glm::translate(glm::mat4(1.0f), positions[0].Position); - } - - int p0Index = GetPositionIndex(bone, time); - int p1Index = p0Index + 1; - - float scaleFactor = GetScaleFactor( - positions[p0Index].Timestamp, - positions[p1Index].Timestamp, - time - ); - - glm::vec3 finalPosition = glm::mix( - positions[p0Index].Position, - positions[p1Index].Position, - scaleFactor - ); - - return glm::translate(glm::mat4(1.0f), finalPosition); - } - - glm::mat4 cAnimSystem::InterpolateRotation(sBone &bone, float time) - { - auto& rotations = bone.KeyRotations; - - if (rotations.empty()) { - return glm::mat4(1.0f); - } - - if (rotations.size() == 1) - { - auto rotation = glm::normalize(rotations[0].Orientation); - return glm::toMat4(rotation); - } - - int p0Index = GetRotationIndex(bone, time); - int p1Index = p0Index + 1; - - float scaleFactor = GetScaleFactor( - rotations[p0Index].Timestamp, - rotations[p1Index].Timestamp, - time - ); - - glm::quat finalRotation = glm::slerp( - rotations[p0Index].Orientation, - rotations[p1Index].Orientation, - scaleFactor - ); - - finalRotation = glm::normalize(finalRotation); - - return glm::toMat4(finalRotation); - } - - glm::mat4 cAnimSystem::InterpolateScale(sBone &bone, float time) - { - auto& scales = bone.KeyScales; - - if (scales.empty()) { - return glm::mat4(1.0f); - } - - if (scales.size() == 1) { - return glm::scale(glm::mat4(1.0f), scales[0].Scale); - } - - int p0Index = GetScaleIndex(bone, time); - int p1Index = p0Index + 1; - - float scaleFactor = GetScaleFactor( - scales[p0Index].Timestamp, - scales[p1Index].Timestamp, - time - ); - - glm::vec3 finalScale = glm::mix( - scales[p0Index].Scale, - scales[p1Index].Scale, - scaleFactor - ); - - return glm::scale(glm::mat4(1.0f), finalScale); - } - - void cAnimSystem::UpdateSkeletonTransform( - const sAnimationNode& animationNode, - sSkeleton &skeleton, - sSkeletonBuffer& skeletonBuffer, - u32 skeletonIndex, - const glm::mat4 &parentTransform - ) { - const string& nodeName = animationNode.Name; - glm::mat4 nodeTransform = animationNode.Transform; - - sBone* bone = nullptr; - auto it = skeleton.Bones.find(nodeName); - if (it != skeleton.Bones.end()) { - bone = &it->second; - } - - if (bone != nullptr) { - AnimateBone(*bone, m_CurrentSeconds); - nodeTransform = bone->Transform; - } - - glm::mat4 globalTransformation = parentTransform * nodeTransform; - - if (bone != nullptr) { - *skeletonBuffer[bone->ID + skeletonIndex] = { globalTransformation * bone->Offset }; - } - - for (auto& node : animationNode.Children) - { - UpdateSkeletonTransform(node, skeleton, skeletonBuffer, skeletonIndex, globalTransformation); - } - } - - } - -} \ No newline at end of file diff --git a/engine/src/anim/anim_system.hpp b/engine/src/anim/anim_system.hpp deleted file mode 100644 index 933b9d3b..00000000 --- a/engine/src/anim/anim_system.hpp +++ /dev/null @@ -1,47 +0,0 @@ -#pragma once - -#include - -namespace xpe { - - namespace anim { - - using namespace core; - using namespace ecs; - using namespace render; - - class ENGINE_API cAnimSystem : public cSystem - { - - public: - void Update(cScene* scene, const cTime& dt) override final; - - private: - void AnimateSkeleton(const sAnimation& animation, sSkeleton& skeleton, u32 skeletonIndex, const cTime& dt); - void AnimateBone(sBone& bone, float time); - - glm::mat4 InterpolatePosition(sBone& bone, float time); - glm::mat4 InterpolateRotation(sBone& bone, float time); - glm::mat4 InterpolateScale(sBone& bone, float time); - - int GetPositionIndex(sBone& bone, float time); - int GetRotationIndex(sBone& bone, float time); - int GetScaleIndex(sBone& bone, float time); - - float GetScaleFactor(float lastTimestamp, float nextTimestamp, float time); - - void UpdateSkeletonTransform( - const sAnimationNode& animationNode, - sSkeleton& skeleton, - sSkeletonBuffer& skeletonBuffer, - u32 skeletonIndex, - const glm::mat4& parentTransform - ); - - float m_CurrentSeconds = 0; - float m_DeltaSeconds = 0; - }; - - } - -} \ No newline at end of file diff --git a/engine/src/anim/skeleton.hpp b/engine/src/anim/skeleton.hpp deleted file mode 100644 index 0ddd0743..00000000 --- a/engine/src/anim/skeleton.hpp +++ /dev/null @@ -1,37 +0,0 @@ -#pragma once - -#include - -#include - -namespace xpe { - - namespace anim { - - struct ENGINE_API sBone final - { - s32 ID; - string Name; - glm::mat4 Offset; - glm::mat4 Transform = glm::mat4(1.0); - vector KeyPositions; - vector KeyRotations; - vector KeyScales; - }; - JSON(sBone, ID, Name, Offset, Transform, KeyPositions, KeyRotations, KeyScales) - - struct ENGINE_API sSkeleton - { - unordered_map Bones; - }; - JSON(sSkeleton, Bones) - - struct ENGINE_API sSkeletonInfo - { - render::sGeometryInfo GeometryInfo; - u32 SkeletonIndex = 0; - }; - - } - -} \ No newline at end of file diff --git a/engine/src/anim/skeleton_manager.cpp b/engine/src/anim/skeleton_manager.cpp deleted file mode 100644 index 3ba45d42..00000000 --- a/engine/src/anim/skeleton_manager.cpp +++ /dev/null @@ -1,24 +0,0 @@ -#include - -namespace xpe { - - namespace anim { - - void cSkeletonManager::Init() - { - Buffers::Skeleton = new sSkeletonBuffer(); - } - - void cSkeletonManager::Free() - { - delete Buffers::Skeleton; - } - - void cSkeletonManager::Flush() - { - Buffers::Skeleton->Flush(); - } - - } - -} \ No newline at end of file diff --git a/engine/src/anim/skeleton_manager.hpp b/engine/src/anim/skeleton_manager.hpp deleted file mode 100644 index 47c28dc2..00000000 --- a/engine/src/anim/skeleton_manager.hpp +++ /dev/null @@ -1,36 +0,0 @@ -#pragma once - -#include -#include - -namespace xpe { - - namespace anim { - - using namespace ecs; - using namespace render; - - class ENGINE_API cSkeletonManager final - { - public: - static void Init(); - static void Free(); - static void Flush(); - - template - static std::pair AddSkeleton(Args &&... args); - }; - - template - std::pair cSkeletonManager::AddSkeleton(Args &&... args) - { - sSkeleton skeleton(std::forward(args)...); - sSkeletonInfo skeletonInfo; - skeletonInfo.SkeletonIndex = Buffers::Skeleton->Size(); - Buffers::Skeleton->Resize(Buffers::Skeleton->Size() + skeleton.Bones.size()); - return { skeleton, skeletonInfo }; - } - - } - -} \ No newline at end of file diff --git a/engine/src/anim_manager.cpp b/engine/src/anim_manager.cpp new file mode 100644 index 00000000..dadcd181 --- /dev/null +++ b/engine/src/anim_manager.cpp @@ -0,0 +1,398 @@ +#include + +namespace xpe { + + namespace anim { + + float MAnim::s_CurrentSeconds = 0; + float MAnim::s_DeltaSeconds = 0; + + void MAnim::Init() + { + Profile(); + Buffers::Skeleton = new sSkeletonBuffer(); + } + + void MAnim::Free() + { + Profile(); + delete Buffers::Skeleton; + } + + void MAnim::Update(cScene* scene, float dt) + { + Profile(); + + auto components = scene->GetComponents(); + for (auto [entity, animation, skeleton, skeletonInfo] : components.each()) + { + AnimateSkeleton(animation, skeleton, skeletonInfo.SkeletonIndex, dt); + } + } + + void MAnim::AnimateSkeleton(const CAnimation &animation, CSkeleton &skeleton, u32 skeletonIndex, float dt) + { + s_DeltaSeconds = dt * 0.001; + s_CurrentSeconds += animation.TicksPerSecond * s_DeltaSeconds; + s_CurrentSeconds = fmod(s_CurrentSeconds, animation.Duration); + UpdateSkeletonTransform(animation.Root, skeleton, *Buffers::Skeleton, skeletonIndex, glm::mat4(1.0f)); + } + + void MAnim::AnimateBone(sBone &bone, float time) + { + glm::mat4 translation = InterpolatePosition(bone, time); + glm::mat4 rotation = InterpolateRotation(bone, time); + glm::mat4 scale = InterpolateScale(bone, time); + bone.Transform = translation * rotation * scale; + } + + int MAnim::GetPositionIndex(sBone &bone, float time) + { + usize count = bone.KeyPositions.size(); + + for (int i = 0; i < count; ++i) + { + if (time < bone.KeyPositions[i + 1].Timestamp) + { + return i; + } + } + + return -1; + } + + int MAnim::GetRotationIndex(sBone &bone, float time) + { + usize count = bone.KeyRotations.size(); + + for (int i = 0; i < count; ++i) + { + if (time < bone.KeyRotations[i + 1].Timestamp) + { + return i; + } + } + + return -1; + } + + int MAnim::GetScaleIndex(sBone &bone, float time) + { + usize count = bone.KeyScales.size(); + + for (int i = 0; i < count; ++i) + { + if (time < bone.KeyScales[i + 1].Timestamp) + { + return i; + } + } + + return -1; + } + + float MAnim::GetScaleFactor(float lastTimestamp, float nextTimestamp, float time) + { + float scaleFactor; + float midWayLength = time - lastTimestamp; + float framesDiff = nextTimestamp - lastTimestamp; + scaleFactor = midWayLength / framesDiff; + return scaleFactor; + } + + glm::mat4 MAnim::InterpolatePosition(sBone &bone, float time) + { + auto& positions = bone.KeyPositions; + + if (positions.empty()) + { + return glm::mat4(1.0f); + } + + if (positions.size() == 1) + { + return glm::translate(glm::mat4(1.0f), positions[0].Position); + } + + int p0Index = GetPositionIndex(bone, time); + int p1Index = p0Index + 1; + + float scaleFactor = GetScaleFactor( + positions[p0Index].Timestamp, + positions[p1Index].Timestamp, + time + ); + + glm::vec3 finalPosition = glm::mix( + positions[p0Index].Position, + positions[p1Index].Position, + scaleFactor + ); + + return glm::translate(glm::mat4(1.0f), finalPosition); + } + + glm::mat4 MAnim::InterpolateRotation(sBone &bone, float time) + { + auto& rotations = bone.KeyRotations; + + if (rotations.empty()) + { + return glm::mat4(1.0f); + } + + if (rotations.size() == 1) + { + auto rotation = glm::normalize(rotations[0].Orientation); + return glm::toMat4(rotation); + } + + int p0Index = GetRotationIndex(bone, time); + int p1Index = p0Index + 1; + + float scaleFactor = GetScaleFactor( + rotations[p0Index].Timestamp, + rotations[p1Index].Timestamp, + time + ); + + glm::quat finalRotation = glm::slerp( + rotations[p0Index].Orientation, + rotations[p1Index].Orientation, + scaleFactor + ); + + finalRotation = glm::normalize(finalRotation); + + return glm::toMat4(finalRotation); + } + + glm::mat4 MAnim::InterpolateScale(sBone &bone, float time) + { + auto& scales = bone.KeyScales; + + if (scales.empty()) + { + return glm::mat4(1.0f); + } + + if (scales.size() == 1) + { + return glm::scale(glm::mat4(1.0f), scales[0].Scale); + } + + int p0Index = GetScaleIndex(bone, time); + int p1Index = p0Index + 1; + + float scaleFactor = GetScaleFactor(scales[p0Index].Timestamp, scales[p1Index].Timestamp, time); + + glm::vec3 finalScale = glm::mix(scales[p0Index].Scale, scales[p1Index].Scale, scaleFactor); + + return glm::scale(glm::mat4(1.0f), finalScale); + } + + void MAnim::UpdateSkeletonTransform( + const sAnimationNode& animationNode, + CSkeleton &skeleton, + sSkeletonBuffer& skeletonBuffer, + u32 skeletonIndex, + const glm::mat4 &parentTransform + ) + { + const string& nodeName = animationNode.Name; + glm::mat4 nodeTransform = animationNode.Transform; + + sBone* bone = nullptr; + auto it = skeleton.Bones.find(nodeName); + if (it != skeleton.Bones.end()) + { + bone = &it->second; + } + + if (bone != nullptr) + { + AnimateBone(*bone, s_CurrentSeconds); + nodeTransform = bone->Transform; + } + + glm::mat4 globalTransformation = parentTransform * nodeTransform; + + if (bone != nullptr) + { + skeletonBuffer.Set(bone->ID + skeletonIndex, { globalTransformation * bone->Offset }); + } + + for (auto& node : animationNode.Children) + { + UpdateSkeletonTransform(node, skeleton, skeletonBuffer, skeletonIndex, globalTransformation); + } + } + + static void ParseAnimation(sAnimationNode& parent, const aiNode* node) + { + parent.Name = node->mName.data; + parent.Transform = MAssimp::ToMat4(node->mTransformation); + parent.Children.reserve(node->mNumChildren); + + for (int i = 0; i < node->mNumChildren; i++) + { + sAnimationNode child; + ParseAnimation(child, node->mChildren[i]); + parent.Children.emplace_back(child); + } + } + + CAnimation MAnim::LoadAnimation(const char* filepath, const vector& options) + { + Profile(); + + if (MFile::NotExists(filepath)) + { + LogError("Skeleton Animation not found in {}", filepath); + return {}; + } + + CAnimation animation; + + Assimp::Importer importer; + const aiScene* scene = importer.ReadFile(filepath, MAssimp::GetLoadFlags(options)); + + if (!scene || scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE || !scene->mRootNode) + { + LogError("Failed to import 3D animation file {0}", filepath); + return {}; + } + + auto aiAnim = scene->mAnimations[0]; + animation.Duration = aiAnim->mDuration; + animation.TicksPerSecond = aiAnim->mTicksPerSecond; + + ParseAnimation(animation.Root, scene->mRootNode); + + return animation; + } + + static void SetKeyFrames(sBone& bone, const aiNodeAnim* channel) + { + for (int i = 0; i < channel->mNumPositionKeys; i++) + { + aiVector3D aiPosition = channel->mPositionKeys[i].mValue; + float timestamp = channel->mPositionKeys[i].mTime; + bone.KeyPositions.emplace_back(timestamp, MAssimp::ToVec3(aiPosition)); + } + + for (int i = 0; i < channel->mNumRotationKeys; i++) + { + aiQuaternion aiOrienation = channel->mRotationKeys[i].mValue; + float timestamp = channel->mRotationKeys[i].mTime; + bone.KeyRotations.emplace_back(timestamp, MAssimp::ToQuat(aiOrienation)); + } + + for (int i = 0; i < channel->mNumScalingKeys; i++) + { + aiVector3D aiScale = channel->mScalingKeys[i].mValue; + float timestamp = channel->mScalingKeys[i].mTime; + bone.KeyScales.emplace_back(timestamp, MAssimp::ToVec3(aiScale)); + } + } + + static void ParseSkeletonFromAnim(const aiAnimation* animation, CSkeleton& skeleton) + { + int size = animation->mNumChannels; + auto& bones = skeleton.Bones; + usize boneCount = skeleton.Bones.size(); + + for (int i = 0; i < size; i++) + { + auto channel = animation->mChannels[i]; + string boneName = channel->mNodeName.data; + + auto it = bones.find(boneName); + if (it == bones.end()) + { + sBone bone; + bone.ID = boneCount++; + bone.Name = boneName; + bones.insert({ boneName, bone }); + } + + SetKeyFrames(bones[boneName], channel); + } + } + + static void ParseSkeletonFromMesh(aiMesh* mesh, CSkeleton& skeleton) + { + s32 boneCounter = 0; + auto& bones = skeleton.Bones; + + for (int i = 0; i < mesh->mNumBones; i++) + { + string boneName = mesh->mBones[i]->mName.C_Str(); + + if (bones.find(boneName) == bones.end()) + { + sBone newBone; + newBone.ID = boneCounter; + newBone.Name = boneName; + newBone.Offset = MAssimp::ToMat4(mesh->mBones[i]->mOffsetMatrix); + bones.insert({ boneName, newBone }); + boneCounter++; + } + } + } + + static void ParseSkeletonFromScene(aiNode* node, const aiScene* scene, CSkeleton& skeleton) + { + for (u32 i = 0 ; i < node->mNumMeshes ; i++) + { + aiMesh* mesh = scene->mMeshes[node->mMeshes[i]]; + ParseSkeletonFromMesh(mesh, skeleton); + } + + for (u32 i = 0 ; i < node->mNumChildren ; i++) + { + ParseSkeletonFromScene(node->mChildren[i], scene, skeleton); + } + } + + CSkeleton MAnim::LoadSkeleton(const char* filepath, const vector& options) + { + Profile(); + + if (MFile::NotExists(filepath)) + { + LogError("Skeleton not found in {}", filepath); + return {}; + } + + CSkeleton skeleton; + + Assimp::Importer importer; + const aiScene* scene = importer.ReadFile(filepath, MAssimp::GetLoadFlags(options)); + + if (!scene || scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE || !scene->mRootNode) + { + LogError("Failed to import 3D skelet model file {0}", filepath); + return {}; + } + + ParseSkeletonFromScene(scene->mRootNode, scene, skeleton); + ParseSkeletonFromAnim(scene->mAnimations[0], skeleton); + + return skeleton; + } + + CSkeletonInfo MAnim::AddSkeleton(const CSkeleton &skeleton) + { + CSkeletonInfo skeletonInfo; + skeletonInfo.SkeletonIndex = Buffers::Skeleton->Size(); + Buffers::Skeleton->Resize(Buffers::Skeleton->Size() + skeleton.Bones.size()); + for (auto& bonePair : skeleton.Bones) + { + auto& bone = bonePair.second; + Buffers::Skeleton->Set(bone.ID + skeletonInfo.SkeletonIndex, { glm::mat4(1.0) }); + } + return skeletonInfo; + } + } +} \ No newline at end of file diff --git a/engine/src/anim_manager.hpp b/engine/src/anim_manager.hpp new file mode 100644 index 00000000..0fc0c722 --- /dev/null +++ b/engine/src/anim_manager.hpp @@ -0,0 +1,55 @@ +#pragma once + +#include + +namespace xpe +{ + namespace anim + { + class ENGINE_API MAnim final + { + + public: + static void Init(); + static void Free(); + static void Update(cScene* scene, float dt); + + static CAnimation LoadAnimation( + const char* filepath, + const vector& options = { eLoadOption::TRIANGULATE } + ); + + static CSkeleton LoadSkeleton( + const char* filepath, + const vector& options = { eLoadOption::TRIANGULATE } + ); + + static CSkeletonInfo AddSkeleton(const CSkeleton& skeleton); + + private: + static void AnimateSkeleton(const CAnimation& animation, CSkeleton& skeleton, u32 skeletonIndex, float dt); + static void AnimateBone(sBone& bone, float time); + + static glm::mat4 InterpolatePosition(sBone& bone, float time); + static glm::mat4 InterpolateRotation(sBone& bone, float time); + static glm::mat4 InterpolateScale(sBone& bone, float time); + + static int GetPositionIndex(sBone& bone, float time); + static int GetRotationIndex(sBone& bone, float time); + static int GetScaleIndex(sBone& bone, float time); + + static float GetScaleFactor(float lastTimestamp, float nextTimestamp, float time); + + static void UpdateSkeletonTransform( + const sAnimationNode& animationNode, + CSkeleton& skeleton, + sSkeletonBuffer& skeletonBuffer, + u32 skeletonIndex, + const glm::mat4& parentTransform + ); + + static float s_CurrentSeconds; + static float s_DeltaSeconds; + }; + } +} \ No newline at end of file diff --git a/engine/src/app.cpp b/engine/src/app.cpp new file mode 100644 index 00000000..7a1f72a3 --- /dev/null +++ b/engine/src/app.cpp @@ -0,0 +1,387 @@ +#include + +namespace xpe +{ + namespace core + { + void cApp::Run() + { + if (!MFile::Exists("res")) + { + MFile::CreateDir("res"); + } + + if (!MFile::Exists("res/audio")) + { + MFile::CreateDir("res/audio"); + } + + if (!MFile::Exists("res/fonts")) + { + MFile::CreateDir("res/fonts"); + } + + if (!MFile::Exists("res/materials")) + { + MFile::CreateDir("res/materials"); + } + + if (!MFile::Exists("res/models")) + { + MFile::CreateDir("res/models"); + } + + if (!MFile::Exists("res/skybox")) + { + MFile::CreateDir("res/skybox"); + } + + if (!MFile::Exists("config")) + { + MFile::CreateDir("config"); + } + + if (!MFile::Exists("res/shaders")) + { + MFile::CreateDir("res/shaders"); + } + + if (!MFile::Exists("scripts")) + { + MFile::CreateDir("scripts"); + } + + LoadJSON("config/app.json", m_Config); + + sLoggerDescriptor logDesc; + logDesc.Name = m_Config.Title.c_str(); + logDesc.Backtrace = m_Config.LogBacktrace; + InitLogger(logDesc); + + sWindowDescriptor winDesc; + winDesc.Title = m_Config.Title.c_str(); + winDesc.Width = m_Config.WinWidth; + winDesc.Height = m_Config.WinHeight; + winDesc.FrameWidth = m_Config.WinWidth; + winDesc.FrameHeight = m_Config.WinHeight; + winDesc.X = m_Config.WinX; + winDesc.Y = m_Config.WinY; + winDesc.VSync = m_Config.VSync; + winDesc.Fullscreen = m_Config.Fullscreen; + winDesc.Gamma = m_Config.Gamma; + winDesc.Exposure = m_Config.Exposure; + + MTask::Init(); + MWindow::Init(); + MWindow::InitWindow(winDesc); + MInput::Init(); + MAudio::Init(); + MPhysics::Init(MTask::GetSimulationDispatcher()); + + MRender::EnableInfoLog = m_Config.GpuInfo; + MRender::EnableWarnLog = m_Config.GpuWarning; + MRender::EnableErrorLog = m_Config.GpuError; + MRender::AnisotropyLevel = m_Config.AnisotropyLevel; + + MCamera::Camera = new CPerspectiveCamera(); + MCamera::Camera->Viewport.Width = MWindow::GetWidth(); + MCamera::Camera->Viewport.Height = MWindow::GetHeight(); + MCamera::Camera->Exposure = winDesc.Exposure; + MCamera::Camera->Gamma = winDesc.Gamma; + MRender::Init(MCamera::Camera->Viewport, m_Config.MsaaSampleCount); + m_Canvas = new cCanvas(&MCamera::Camera->Viewport); + + InitShaders(); + + // TODO : move into serialization file + m_Scene = new cScene(MPhysics::AddScene("Untitled")); + + Init(); + + MRender::Prepare(); + +#ifdef K_EDITOR + MEditor::SelectedScene = m_Scene; + MEditor::SelectedCamera = MCamera::Camera; + MEditor::ViewportImage = RenderTargets::Final->Colors[0]; + MEditor::Init(); + // StartWatchFiles(); +#endif + + while (m_Opened) + { + long long beginTime = time_point_cast(high_resolution_clock::now()).time_since_epoch().count(); + + Update(); + + // can be null during hot-reloading + // TODO : create game scripting class +// if (m_GameSystem != nullptr) +// { +// m_GameSystem->Update(m_Scene, DeltaTime); +// } + + // submit audio task with current scene state + MTask::Add({sTask::eType::AUDIO, [this]() + { + MAudio::Update(m_Scene, m_DeltaTime); + }}); + + // submit animation task with current scene state + MTask::Add({sTask::eType::ANIMATION, [this]() + { + MAnim::Update(m_Scene, m_DeltaTime); + }}); + + // calls physics simulation that will be automatically dispatched into TaskManager + // we don't need to submit physics system into task + MPhysics::Update(m_Scene, m_DeltaTime); + + Render(); + + MWindow::PollEvents(); + MWindow::Swap(); + + m_Opened = !MWindow::ShouldClose(); + + long long endTime = time_point_cast(high_resolution_clock::now()).time_since_epoch().count(); + m_DeltaTime = endTime - beginTime; + } + + SaveJSON("config/app.json", m_Config); + +#ifdef K_EDITOR + // StopWatchFiles(); + MEditor::Free(); +#endif + + Free(); + + delete m_Scene; + + delete m_Canvas; + MRender::Free(); + + MAudio::Free(); + MPhysics::Free(); + MInput::Free(); + MWindow::FreeWindow(); + MWindow::Free(); + MTask::Free(); + + FreeLogger(); + } + + void cApp::InitShaders() + { + MShader::SetShader(new cSkyboxShader("skybox")); + MShader::SetShader(new cDirectionalShadowShader("directional_shadow")); + MShader::SetShader(new cPointShadowShader("point_shadow")); + MShader::SetShader(new cSpotShadowShader("spot_shadow")); + MShader::SetShader(new cOpaqueShader("opaque")); + MShader::SetShader(new cTransparentShader("transparent")); + MShader::SetShader(new cCompositeTransparentShader("composite_transparent", m_Config.MsaaSampleCount)); + MShader::SetShader(new cSsaoShader("ssao", m_Config.MsaaSampleCount)); + MShader::SetShader(new cWidgetShader("widget")); + MShader::SetShader(new cTextShader("text")); + MShader::SetShader(new cFinalShader("final", m_Config.MsaaSampleCount)); + MShader::GetShader("ssao")->Enable = m_Config.EnableSSAO; + } + + void cApp::Render() + { + RenderTargets::SSAO->Clear(); + MRender::Update(m_Scene, m_DeltaTime); +#ifdef K_EDITOR + MEditor::Update(m_DeltaTime); +#else + m_Canvas->Draw(); +#endif + } + + void cApp::LoadGameLib(const string &dllpath) + { + // TODO : add game script class +// auto* gameSystem = MProc::Load<>(dllpath.c_str(), "CreateGameSystem"); +// if (gameSystem == nullptr) +// { +// LogError("Failed to load game system from DLL {}", dllpath); +// return; +// } +// +// delete m_GameSystem; +// m_GameSystem = gameSystem; +// m_GameSystem->Init(); + } + + void cApp::GameLibModified(const string& watchpath, const string& filepath) + { + LogInfo("App: Game code of {} has been changed!", filepath); + LoadGameLib(filepath); + } + + void cApp::ShaderModified(const string& watchpath, const string& filepath) + { + LogInfo("App: Shader file {} has been changed!", filepath); + MShader::ReloadStage(filepath.c_str()); + } + + void cApp::ModelModified(const string& watchpath, const string& filepath) + { + LogInfo("App: Model file {} has been changed!", filepath); + } + + void cApp::FontModified(const string& watchpath, const string& filepath) + { + LogInfo("App: Font file {} has been changed!", filepath); + } + + void cApp::MaterialModified(const string& watchpath, const string& filepath) + { + LogInfo("App: Material file {} has been changed!", filepath); + } + + void cApp::SkyboxModified(const string& watchpath, const string& filepath) + { + LogInfo("App: Skybox file {} has been changed!", filepath); + } + + void cApp::StartWatchFiles() + { + m_FileWatcher = new cMultiFileWatcher(); + m_DirWatcher = new cDirectoryWatcher(); + + // watch gamelib + { + hstringstream ss; + ss << "GameLib.dll"; + hstring gameCodeDllPath = ss.str(); + if (MFile::Exists(gameCodeDllPath.c_str())) + { + auto& watch = m_FileWatcher->AddWatch(gameCodeDllPath.c_str()); + watch.FileModifiedEvents.Add("GameLib", 1, [this](const string& watchpath, const string& filepath) + { + GameLibModified(watchpath, filepath); + }); + } + } + + // watch shaders + { + hstringstream ss; + ss << "res/shaders"; + hstring shadersPath = ss.str(); + if (MFile::Exists(shadersPath.c_str())) + { + auto& watch = m_DirWatcher->AddWatch(shadersPath.c_str()); + watch.FileModifiedEvents.Add("Shaders", 1, [this](const string& watchpath, const string& filepath) + { + ShaderModified(watchpath, filepath); + }); + watch.FileAddedEvents.Add("Shaders", 1, [this](const string& watchpath, const string& filepath) + { + ShaderModified(watchpath, filepath); + }); + watch.FileDeletedEvents.Add("Shaders", 1, [this](const string& watchpath, const string& filepath) + { + ShaderModified(watchpath, filepath); + }); + } + } + + // watch res + { + hstringstream ss; + ss << "res/models"; + hstring modelsPath = ss.str(); + if (MFile::Exists(modelsPath.c_str())) + { + auto& watch = m_DirWatcher->AddWatch(modelsPath.c_str()); + watch.FileModifiedEvents.Add("Models", 1, [this](const string& watchpath, const string& filepath) + { + ModelModified(watchpath, filepath); + }); + watch.FileAddedEvents.Add("Models", 1, [this](const string& watchpath, const string& filepath) + { + ModelModified(watchpath, filepath); + }); + watch.FileDeletedEvents.Add("Models", 1, [this](const string& watchpath, const string& filepath) + { + ModelModified(watchpath, filepath); + }); + } + + ss = {}; + ss << "res/fonts"; + hstring fontsPath = ss.str(); + if (MFile::Exists(fontsPath.c_str())) + { + auto& watch = m_DirWatcher->AddWatch(fontsPath.c_str()); + watch.FileModifiedEvents.Add("Fonts", 1, [this](const string& watchpath, const string& filepath) + { + FontModified(watchpath, filepath); + }); + watch.FileAddedEvents.Add("Fonts", 1, [this](const string& watchpath, const string& filepath) + { + FontModified(watchpath, filepath); + }); + watch.FileDeletedEvents.Add("Fonts", 1, [this](const string& watchpath, const string& filepath) + { + FontModified(watchpath, filepath); + }); + } + + ss = {}; + ss << "res/materials"; + hstring materialsPath = ss.str(); + if (MFile::Exists(materialsPath.c_str())) + { + auto& watch = m_DirWatcher->AddWatch(materialsPath.c_str()); + watch.FileModifiedEvents.Add("Materials", 1, [this](const string& watchpath, const string& filepath) + { + MaterialModified(watchpath, filepath); + }); + watch.FileAddedEvents.Add("Materials", 1, [this](const string& watchpath, const string& filepath) + { + MaterialModified(watchpath, filepath); + }); + watch.FileDeletedEvents.Add("Materials", 1, [this](const string& watchpath, const string& filepath) + { + MaterialModified(watchpath, filepath); + }); + } + + ss = {}; + ss << "res/skybox"; + hstring skyboxPath = ss.str(); + if (MFile::Exists(skyboxPath.c_str())) + { + auto& watch = m_DirWatcher->AddWatch(skyboxPath.c_str()); + watch.FileModifiedEvents.Add("Skybox", 1, [this](const string& watchpath, const string& filepath) + { + SkyboxModified(watchpath, filepath); + }); + watch.FileAddedEvents.Add("Skybox", 1, [this](const string& watchpath, const string& filepath) + { + SkyboxModified(watchpath, filepath); + }); + watch.FileDeletedEvents.Add("Skybox", 1, [this](const string& watchpath, const string& filepath) + { + SkyboxModified(watchpath, filepath); + }); + } + } + + m_FileWatcher->Start(); + m_DirWatcher->Start(); + } + + void cApp::StopWatchFiles() + { + m_FileWatcher->Stop(); + m_DirWatcher->Stop(); + delete m_FileWatcher; + delete m_DirWatcher; + } + } +} diff --git a/engine/src/app.hpp b/engine/src/app.hpp new file mode 100644 index 00000000..f2c49ab6 --- /dev/null +++ b/engine/src/app.hpp @@ -0,0 +1,66 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef K_EDITOR +#include +#endif + +namespace xpe +{ + namespace core + { + class ENGINE_API cApp : public cObject { + + public: + cApp(const string& title) { m_Config.Title = title; } + ~cApp() {} + + void Run(); + + void LoadGameLib(const string& dllpath); + + protected: + virtual void Init() {} + virtual void Update() {} + virtual void Free() {} + virtual void Render(); + + virtual void InitShaders(); + + void LockFPSFromConfig(); + + void StartWatchFiles(); + void StopWatchFiles(); + + void GameLibModified(const string& watchpath, const string& filepath); + void ShaderModified(const string& watchpath, const string& filepath); + void ModelModified(const string& watchpath, const string& filepath); + void FontModified(const string& watchpath, const string& filepath); + void MaterialModified(const string& watchpath, const string& filepath); + void SkyboxModified(const string& watchpath, const string& filepath); + + float m_DeltaTime = 6; // milliseconds + + sAppConfig m_Config; + + std::atomic_bool m_Opened = true; + + cMultiFileWatcher* m_FileWatcher = nullptr; + cDirectoryWatcher* m_DirWatcher = nullptr; + + cScene* m_Scene = nullptr; + + cCanvas* m_Canvas = nullptr; + }; + } +} + +xpe::core::cApp* CreateApplication(); \ No newline at end of file diff --git a/engine/src/app_config.hpp b/engine/src/app_config.hpp new file mode 100644 index 00000000..cf7a5e4f --- /dev/null +++ b/engine/src/app_config.hpp @@ -0,0 +1,52 @@ +#pragma once + +namespace xpe +{ + namespace core + { + struct ENGINE_API sAppConfig : public res::cJson + { + JSON_CLASS( + sAppConfig, + WinWidth, + WinHeight, + WinX, + WinY, + VSync, + Fullscreen, + Gamma, + Exposure, + AspectRatio, + LogBacktrace, + GpuInfo, + GpuWarning, + GpuError, + MsaaSampleCount, + EnableSSAO, + AnisotropyLevel + ) + + string Title; + s32 WinWidth = 800; + s32 WinHeight = 600; + s32 WinX = 200; + s32 WinY = 150; + bool VSync = true; + bool Fullscreen = false; + float Gamma = 2.2f; + float Exposure = 1; + float AspectRatio = 1.6f; + + s32 LogBacktrace = 32; + bool GpuInfo = false; + bool GpuWarning = false; + bool GpuError = true; + + bool EnableSSAO = true; + + u32 MsaaSampleCount = 1; + + u32 AnisotropyLevel = 4; + }; + } +} \ No newline at end of file diff --git a/loader/src/assimp_manager.cpp b/engine/src/assimp_manager.cpp similarity index 87% rename from loader/src/assimp_manager.cpp rename to engine/src/assimp_manager.cpp index 95c5b546..3aa9fe9b 100644 --- a/loader/src/assimp_manager.cpp +++ b/engine/src/assimp_manager.cpp @@ -1,10 +1,11 @@ #include -namespace xpe { - - namespace res { - - const std::unordered_map cAssimpManager::k_LoadOptions = { +namespace xpe +{ + namespace res + { + const std::unordered_map MAssimp::k_LoadOptions = + { { eLoadOption::TRIANGULATE, aiProcess_Triangulate }, { eLoadOption::FLIP_UV, aiProcess_FlipUVs }, { eLoadOption::CALC_TANGENTS, aiProcess_CalcTangentSpace }, @@ -12,7 +13,5 @@ namespace xpe { { eLoadOption::GEN_NORMAL, aiProcess_GenNormals }, { eLoadOption::JOIN_VERTICES, aiProcess_JoinIdenticalVertices } }; - } - } \ No newline at end of file diff --git a/loader/src/assimp_manager.hpp b/engine/src/assimp_manager.hpp similarity index 88% rename from loader/src/assimp_manager.hpp rename to engine/src/assimp_manager.hpp index 465a95fc..cdc7e02b 100644 --- a/loader/src/assimp_manager.hpp +++ b/engine/src/assimp_manager.hpp @@ -1,18 +1,14 @@ #pragma once -#include - #include #include #include #include -namespace xpe { - - namespace res { - - using namespace core; - +namespace xpe +{ + namespace res + { enum class eLoadOption { TRIANGULATE, @@ -23,7 +19,7 @@ namespace xpe { JOIN_VERTICES }; - class LOADER_API cAssimpManager final + class ENGINE_API MAssimp final { public: @@ -41,7 +37,8 @@ namespace xpe { inline static glm::mat4 ToMat4(const aiMatrix4x4& mat) { - return { + return + { { mat.a1, mat.b1, mat.c1, mat.d1 }, { mat.a2, mat.b2, mat.c2, mat.d2 }, { mat.a3, mat.b3, mat.c3, mat.d3 }, @@ -49,7 +46,8 @@ namespace xpe { }; } - inline static u32 GetLoadFlags(const vector& options) { + inline static u32 GetLoadFlags(const vector& options) + { u32 flags = 0; for (const auto& option : options) diff --git a/engine/src/audio/audio_manager.cpp b/engine/src/audio/audio_manager.cpp deleted file mode 100644 index 4ff1da43..00000000 --- a/engine/src/audio/audio_manager.cpp +++ /dev/null @@ -1,55 +0,0 @@ -#include