52 Commits

Author SHA1 Message Date
391fd5a8a8 WIP: Switching from Premake to CMake build system 2025-06-15 20:55:15 +02:00
7349c0eb16 Basics of the meta Asset Management 2023-06-05 17:48:11 +02:00
19b630104c Big clean up, getting ready for new AssetManagement
* Removing Old EventSystem
* Removing Assets from Editor project
* Clean up of EditorLayer.h
* Moving primitives of renderer out of their subfolder
2023-06-05 17:47:40 +02:00
7ec13a7020 Adding more input handlers 2023-05-17 19:41:48 +02:00
4a84df7c3e Ignore more dirty submodules 2023-05-16 22:06:45 +02:00
a297c7cb3a Adding googletest as a submodule 2023-05-16 22:04:32 +02:00
8ef886df83 Clean up layer stack code, input now goes through each layer 2023-05-16 21:59:10 +02:00
817d0bdca9 Adding tests for decompose function
Added scale and rotation decompose test
2023-05-16 20:43:05 +02:00
c640ac574b Fixed translation issue with Imguizmo 2023-05-16 20:18:26 +02:00
0b2148ad55 Adding more things to .gitignore 2023-05-13 21:37:53 +02:00
95f77209cf Fixing lvalue errors on linux build
nfd is not yet linking on Linux
2023-05-13 21:33:57 +02:00
f7e087ee8d remove yaml-cpp from root directory, Add tests project 2023-05-13 20:13:25 +02:00
e52db0fafd Remove Runtime Project 2023-05-13 20:10:47 +02:00
5bdc0034d1 Moving premake5.lua build file to their individual submodule folder 2023-05-13 20:10:25 +02:00
ceb485018f Rudimentary implementation of the translate,Rotate,Scale tools 2023-05-13 18:10:24 +02:00
daf26c304b Added a few thing , and started simplifying renderer
- Added context menu to Inspector
- Added check to see if project path exists.
- Simplifying the renderer design
2023-05-13 01:31:37 +02:00
550c1b6e5b Updated Editor architecture
- Everything editor related will be happening in EditorLayer
- Added an icon font
- Added proper icon
- Added project badge in main menu bar
- Texture class now keeps track of the texture width and height
2023-05-11 20:27:07 +02:00
c82398205a Script component inspector, glfwErrorCallback etc...
* Filling out script component inspector
* adding error_callback for glfw
* Measuring gflwInit time
* Moving Swap interval set to be after making context current
2023-05-09 19:38:53 +02:00
43fc721413 Replacing a few std::cout with spdlog::info/error 2023-05-09 19:36:34 +02:00
52747202d3 Mark two git submodules to ignore when their working tree has changes 2023-05-08 22:18:14 +02:00
fef75ec64b Started Working on an assetsystem for loading more complex models 2023-05-08 22:08:08 +02:00
3c38e2a988 Editor Layer + Updating Camera System
Started updating the camera system, Moving editor logic to an Editor layer
2023-05-08 22:07:29 +02:00
e9852fe0e7 Implementing started properly implementing Gizmo
Adding GetTransform to the transform component such that the proper view transform can be calculated for any scene camera
2023-05-08 22:06:01 +02:00
8e202f9d59 Introducing application layers
This feature is not really used yet but will help in the future simplify the propegation of events
2023-05-08 22:01:44 +02:00
d8627d0357 Removing unused TransformTree definition files 2023-05-07 20:44:42 +02:00
ec8045c4f4 Added Asset selection in Render3D component view (Not functional yet!) 2023-05-07 15:25:31 +02:00
042dc3a457 Update Transform Component view of the editor 2023-05-07 15:24:23 +02:00
28927d9a4e Moved model file loading logic to the editor code base 2023-05-06 21:06:49 +02:00
89f5b1497f Can move around scene again .. working on Rendering engine still 2023-05-03 16:40:43 +02:00
7448017701 Further abstraction of platform window handling
We could now build our own native window class and stop relying on GLFW. However this won't be important for now!
2023-01-31 18:41:46 +01:00
ba69726e33 Updated gitignore and added submodule
- Added a filebrowser for imgui submodule
- Added gitignore entries for two submodules
2023-01-14 22:18:15 +01:00
7223c20f1d Changed selected type
Moving away from using the pure ENTT library types and starting to use my own
2023-01-14 22:11:09 +01:00
282844b905 Load the previously loaded project and scene on startup
(read from an ini file)
2023-01-14 21:44:48 +01:00
145338d666 Editor Refactor
This refactor of the editor code makes the code more maintainable.

All widget objects have now moved away from RAII and are now just allocated object that live for the entirety of the applications lifetime.
This feels better as I am used to this style plus constantly pushing and popping objects from the stack seems a little wasteful (although I as of right now have no way to prove that it is ).
2023-01-14 17:27:37 +01:00
79b68fbff1 deferred rendering can be enabled for certain meshes 2023-01-13 17:55:45 +01:00
13f67a7cdb Basic input handling, Editor camera Movement 2023-01-04 19:01:58 +01:00
d5a6ddb9d5 Moving vegetation test to the renderer 2023-01-04 15:57:08 +01:00
0f9be33bd6 Primitive Blending functionality 2023-01-01 17:02:44 +01:00
75aa577211 Relation widget + small memory leak solved 2023-01-01 17:00:48 +01:00
fe7e168e21 Adding a relationship component
The relationship component enables us to define a hierarchy through the ECS. This creates a pathway towards Inverse Kinematics
2022-12-31 02:42:27 +01:00
3722e63495 Updated Markdown Documents
- Added new screenshot
- Removed two unnecessary screenshots
- Moved screenshots to a separate showcase markdown file
- Updated the Todo list
- Removed the features markdown file and added it to the README
- Moved development instructions to a separate Development markdown file
2022-12-28 23:49:55 +01:00
3a9c07aff9 Mixing Deferred and Forward rendering
- TODO: fix Skybox affected by lighting pass
2022-12-28 23:17:55 +01:00
2dcc3f1803 Deferred rendering mode + Skybox
- Added deferred rendering mode to the renderer
- Added a skybox to the forward rendering mode
- moved default imported assets directory (temporary fix)
2022-12-28 22:35:23 +01:00
2a5c7811e7 Importing mesh asset now functioning
- Added debug logging for all user actions regarding FileDialog
- Importing a Meshasset wil now Create a propery entity for the asset.
2022-12-27 21:16:56 +01:00
3fa5455b43 Improving the editor, ImGuizmo is now rendering guizmo's
- Added Guzimo's to the sceneview
- Added new menu to the menubar
- Improved multiple widgets (ImGui windows)
- Added a new RuntimeControl widget (ImGui window)
- New Screenshots
2022-12-24 02:10:29 +01:00
ad79aa2865 Small rendering improvements
- Make view and projection matrix part of the camera
- Add a getter function for the camera in renderer
- Take shader uniform values by const ref
2022-12-24 02:04:51 +01:00
fd68c5dde3 Moving Physics to its own system
- Moved Physx to a singular Physics system
- Removed old Physx test code from application.cpp
2022-12-24 02:00:11 +01:00
1f1a776686 Adding physx and fixing memory allocation of AssetView 2022-12-22 17:16:09 +01:00
e7f1bd7d52 Removing big memory hog from renderer 2022-12-21 19:11:27 +01:00
a1ec94e983 Applying better design choices for general engine
Renderer is causing a big memory leak because it never deletes its Vertex Array
2022-11-12 22:40:36 +01:00
4b84707f98 New entrypoint 2022-11-12 16:57:34 +01:00
3d3596a3b6 Framebuffer now takes a size parameter
Scene now fills entire scene/Game view widget
2022-11-11 19:30:54 +01:00
152 changed files with 6145 additions and 2454 deletions

1
.gitattributes vendored
View File

@ -1,3 +1,4 @@
*.png filter=lfs diff=lfs merge=lfs -text *.png filter=lfs diff=lfs merge=lfs -text
*.webp filter=lfs diff=lfs merge=lfs -text *.webp filter=lfs diff=lfs merge=lfs -text
*.xcf filter=lfs diff=lfs merge=lfs -text *.xcf filter=lfs diff=lfs merge=lfs -text
*.jpeg filter=lfs diff=lfs merge=lfs -text

10
.gitignore vendored
View File

@ -16,4 +16,12 @@ x64/
*.gltf *.gltf
!sponza.gltf !sponza.gltf
imgui.ini imgui.ini
libs/physx/physx/include/
libs/physx/physx/compiler/
libs/physx/physx/buildtools/
libs/physx/physx/bin/
libs/nativefiledialog/build/
.docker
**/bin/

14
.gitmodules vendored
View File

@ -14,6 +14,7 @@
[submodule "ImGui"] [submodule "ImGui"]
path = libs/ImGui path = libs/ImGui
url = https://github.com/ocornut/imgui.git url = https://github.com/ocornut/imgui.git
ignore = dirty
[submodule "assimp"] [submodule "assimp"]
path = libs/assimp path = libs/assimp
url = https://github.com/assimp/assimp.git url = https://github.com/assimp/assimp.git
@ -24,15 +25,28 @@
[submodule "libs/physx"] [submodule "libs/physx"]
path = libs/physx path = libs/physx
url = https://git.barink.dev/Nigel/PhysX.git url = https://git.barink.dev/Nigel/PhysX.git
ignore = dirty
[submodule "libs/entt"] [submodule "libs/entt"]
path = libs/entt path = libs/entt
url = https://github.com/skypjack/entt.git url = https://github.com/skypjack/entt.git
[submodule "libs/guizmo"] [submodule "libs/guizmo"]
path = libs/guizmo path = libs/guizmo
url = https://github.com/CedricGuillemet/ImGuizmo.git url = https://github.com/CedricGuillemet/ImGuizmo.git
ignore = dirty
[submodule "libs/yaml-cpp"] [submodule "libs/yaml-cpp"]
path = libs/yaml-cpp path = libs/yaml-cpp
url = https://git.barink.dev/Nigel/yaml-cpp.git url = https://git.barink.dev/Nigel/yaml-cpp.git
ignore = dirty
[submodule "libs/nativefiledialog"] [submodule "libs/nativefiledialog"]
path = libs/nativefiledialog path = libs/nativefiledialog
url = https://git.barink.dev/Nigel/nativefiledialog.git url = https://git.barink.dev/Nigel/nativefiledialog.git
ignore = dirty
[submodule "libs/mINI"]
path = libs/mINI
url = https://github.com/pulzed/mINI.git
[submodule "libs/imgui-filebrowser"]
path = libs/imgui-filebrowser
url = https://github.com/AirGuanZ/imgui-filebrowser.git
[submodule "libs/googletest"]
path = libs/googletest
url = https://github.com/google/googletest.git

21
CmakeLists.txt Normal file
View File

@ -0,0 +1,21 @@
CMAKE_MINIMUM_REQUIRED (VERSION 4.0)
project(Yoggie)
set(EXPORT_COMPILE_COMMANDS_JSON ON)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
if(MSVC)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4099")
else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wclass-struct-conversion")
endif()
add_compile_definitions(_CRT_SECURE_NO_WARNINGS)
add_compile_definitions(GLFW_STATIC)
add_subdirectory(Editor)
add_subdirectory(SandboxApp)
include(libraries.cmake)
add_subdirectory(YoggieEngine)

23
DEVELOPMENT.md Normal file
View File

@ -0,0 +1,23 @@
## Requirements
*_NOTE:_ Right now the build proces of some third party libraries have not been converted and may need special tooling*
#### Software
* Premake
* Git
* C++ Compiler
## Windows development workflow
User premake to generate project files for the approperiate build method.
On Windows I assume you'll build with visual studio
```bash
User:~$ premake vs2022
```
## Linux development workflow
Use premake to generate project files for the approperiate build method.
On Linux I assume you'll build with something like make.
```bash
User@Machine:~$ premake gmake2
```

1
Editor/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
**.dll

17
Editor/CMakeLists.txt Normal file
View File

@ -0,0 +1,17 @@
file(GLOB SOURCE_FILES "src/*.cpp")
file(GLOB HEADER_FILES "src/*.h")
add_executable(Editor ${SOURCE_FILES} "../libs/glad/src/glad.c" ${HEADER_FILES})
target_include_directories(Editor PRIVATE
"../YoggieEngine/src"
"../libs/guizmo"
)
target_link_directories(Editor PRIVATE
"../libs/ImGui/build/Release"
"../libs/guizmo/build/Release" )
target_link_libraries(Editor
thirdparty_tools
YoggieEngine
ImGui
ImGuizmo
)

View File

@ -1,44 +0,0 @@
project "Editor"
kind "ConsoleApp"
buildmessage "Building editor ..."
links{
"YoggieEngine",
"ImGuizmo",
"yaml-cpp",
"nfd.lib"
}
includedirs{
"../YoggieEngine/build/Debug",
-- I'd prefer if didn't need these..
-- We'll figure that out some time later
incfolder["lua"],
incfolder["spdlog"],
incfolder["glm"],
incfolder["assimp"],
incfolder["glad"],
incfolder["glfw"],
incfolder["imgui"],
incfolder["imguizmo"],
incfolder["entt"],
incfolder["yamlcpp"],
incfolder["nativefiledialog"],
}
libdirs {
staticlib["yoggie"],
staticlib["nativefiledialog"]
}
files {
"../libs/glad/src/glad.c",
"./src/**.h",
"./src/**.cpp"
}

BIN
Editor/rsc/Yoggie.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
Editor/rsc/Yoggie2.jpeg (Stored with Git LFS) Normal file

Binary file not shown.

View File

@ -1,46 +0,0 @@
#pragma once
#include <filesystem>
#include <string>
#include "../../YoggieEngine/src/YoggieEngine.h"
enum class ASSET_TYPE {
Unknown = -1,
Mesh,
Texture,
Material
};
class Asset {
public:
Asset(const char* name): name(name) {}
virtual ASSET_TYPE GetType() { return ASSET_TYPE::Unknown; }
const char* GetName() const { return name.c_str(); }
bool isFolder = false ;
protected:
std::string name;
};
class MeshAsset : Asset {
public:
MeshAsset(YoggieEngine::Mesh mesh) : Asset("New MeshAsset"), mesh(mesh) {}
ASSET_TYPE GetType() override { return ASSET_TYPE::Mesh; }
private:
YoggieEngine::Mesh& mesh;
};
class TextureAsset : Asset {
public:
TextureAsset (YoggieEngine::Texture texture): Asset("New TextureAsset"), texture(texture) {}
ASSET_TYPE GetType() override { return ASSET_TYPE::Texture; }
private:
YoggieEngine::Texture& texture;
};
class MaterialAsset : Asset {
public:
MaterialAsset () : Asset("New MaterialAsset"){}
ASSET_TYPE GetType() override { return ASSET_TYPE::Material; }
private:
};

View File

@ -1,149 +0,0 @@
#include "AssetManager.h"
#include "../../YoggieEngine/src/AssetManager/ModelImporter.h"
#include <iostream>
#include <fstream>
#include <spdlog/spdlog.h>
std::vector<Asset> AssetManager::assets;
std::filesystem::path AssetManager::currentPath;
void AssetManager::Init()
{
assets = std::vector<Asset>();
currentPath = std::filesystem::path(".");
}
void AssetManager::BuildAssetView()
{
if (currentPath.empty()) {
return;
}
for (auto& dir_entry : std::filesystem::directory_iterator(currentPath))
{
auto asset = Asset(dir_entry.path().filename().string().c_str());
if (dir_entry.is_directory()) {
asset.isFolder = true;
}
assets.push_back(asset);
}
}
void AssetManager::setAssetPath(std::filesystem::path path)
{
currentPath = path;
}
YoggieEngine::Mesh* AssetManager::LoadFromAssetFile(const std::filesystem::path assetPath)
{
YoggieEngine::Mesh imported;
std::ifstream AssetFile;
AssetFile.open(assetPath, std::ios::binary);
if (AssetFile.is_open()) {
char* Header = (char*)malloc(8);
unsigned long long Vsize = 0;
uint32_t Vnum = 0;
uint32_t Enum = 0;
// Read header
AssetFile.read(Header, 8);
AssetFile.read((char*)&Vsize, sizeof(unsigned long long));
AssetFile.read((char*)&Vnum, sizeof(uint32_t));
AssetFile.read((char*)&Enum, sizeof(uint32_t));
// print Header info
std::cout << "File has header: " << Header << std::endl;
std::cout << "Vertex size: " << Vsize << std::endl;
std::cout << "Number of Vertices: " << Vnum << std::endl;
std::cout << "Number of Elements: " << Enum << std::endl;
free(Header);
// Load Vertices (Vertex + UV )
imported.vertices = std::vector < YoggieEngine::Vertex>();
for (int i = 0; i < Vnum; i++)
{
YoggieEngine::Vertex data = YoggieEngine::Vertex();
AssetFile.read((char*)&data, Vsize);
imported.vertices.push_back(data);
}
// skip x bytes
AssetFile.ignore(sizeof(char) * 3);
// Load Elements
imported.elements = std::vector<unsigned int>();
for (int i = 0; i < Enum; i++) {
unsigned int data = 0;
AssetFile.read((char*)&data, sizeof(unsigned int));
imported.elements.push_back(data);
}
}
else {
std::cout << "Failed ot open mesh " << std::endl;
}
return nullptr;
}
YoggieEngine::Renderable* AssetManager::LoadFromSource(const std::filesystem::path srcPath, const std::filesystem::path assetFolder)
{
auto model = (YoggieEngine::ModelImporter()).Import(srcPath.string());
YoggieEngine::Mesh* exportMesh = model->renderable->mesh;
std::filesystem::path MeshFileName = assetFolder / srcPath.filename().replace_extension(".mesh");
std::cout << "Save path: " << MeshFileName << std::endl;
std::ofstream meshAsset;
meshAsset.open(MeshFileName.c_str(), std::ios::binary);
if (meshAsset.is_open()) {
// write a header
static const char* HEADER = "MESH";
meshAsset.write(HEADER, sizeof(HEADER));
auto Vsize = sizeof(YoggieEngine::Vertex);
std::cout << "size of vertex: " << Vsize << std::endl;
std::cout << "Addr of vSize: " << &Vsize << std::endl;
auto Vnum = exportMesh->vertices.size();
auto Enum = exportMesh->elements.size();
meshAsset.write((char*)&Vsize, sizeof(unsigned long long));
meshAsset.write((char*)&Vnum, sizeof(uint32_t));
meshAsset.write((char*)&Enum, sizeof(uint32_t));
// write all vertices
for (auto vertice : exportMesh->vertices)
{
meshAsset.write((char*)&vertice, sizeof(vertice));
}
// write 3 x 0 byte
meshAsset.write((const char*)"\0\0\0", sizeof(char) * 3);
// write all indices
for (auto index : exportMesh->elements) {
meshAsset.write((char*)&index, sizeof(index));
}
meshAsset.close();
}
else {
spdlog::error("Failed to create/open mesh file.");
}
return model->renderable;
}

View File

@ -1,20 +0,0 @@
#pragma once
#include <vector>
#include "Asset.h"
class AssetManager {
public:
static void Init();
static void BuildAssetView();
static void setAssetPath(std::filesystem::path path);
static YoggieEngine::Mesh* LoadFromAssetFile(const std::filesystem::path assetPath);
static YoggieEngine::Renderable* LoadFromSource(const std::filesystem::path srcPath, const std::filesystem::path assetFolder);
static std::vector<Asset> assets ;
private:
static std::filesystem::path currentPath;
};

View File

@ -1,22 +1,25 @@
#include "Console.h"
#include <stdio.h> #include <stdio.h>
#include "EditorConsole.h"
Console::Console()
EditorConsole::EditorConsole() : EditorWindow("Console"), Items(ImVector<char*>()), AutoScroll(false), ScrollToBottom(false)
: Items(ImVector<char*>()), AutoScroll(false), ScrollToBottom(false)
{ {
AddLog("Hello Editor console!"); AddLog("Hello Editor console!");
} }
EditorConsole::~EditorConsole() { Console::~Console() {
} }
void EditorConsole::Draw() { void Console::Show() {
ImGui::SetNextWindowSize(ImVec2(520, 600), ImGuiCond_FirstUseEver); Draw();
}
for (int i = 0; i < Items.Size; i++) void Console::Draw() {
ImGui::SetNextWindowSize(ImVec2(520, 600), ImGuiCond_FirstUseEver);
for (int i = 0; i < Items.Size; i++)
{ {
const char* item = Items[i]; const char* item = Items[i];
ImGui::TextUnformatted(item); ImGui::TextUnformatted(item);
@ -24,7 +27,7 @@ void EditorConsole::Draw() {
} }
void EditorConsole::AddLog(const char* fmt, ...) { void Console::AddLog(const char* fmt, ...) {
char buf[1024]; char buf[1024];
va_list args; va_list args;
va_start(args, fmt); va_start(args, fmt);

22
Editor/src/Console.h Normal file
View File

@ -0,0 +1,22 @@
#pragma once
#include "../../YoggieEngine/src/YoggieEngine.h"
#include "EditorWindow.h"
#include <imgui.h>
class Console : public EditorWindow {
public:
Console();
~Console();
void Draw() override;
void Show();
void AddLog(const char* fmt, ...);
private:
ImVector<char*> Items;
bool AutoScroll;
bool ScrollToBottom;
};

View File

@ -4,7 +4,7 @@
#include <nfd.h> #include <nfd.h>
#include <iostream> #include <iostream>
#include <functional> #include <functional>
#include "Project.h" #include "Project/Project.h"
struct DialogSpec { struct DialogSpec {
const std::string& id; const std::string& id;
const std::string& Title; const std::string& Title;
@ -31,9 +31,9 @@ public:
location = std::string(path); location = std::string(path);
break; break;
case(NFD_CANCEL): case(NFD_CANCEL):
std::cout << "NFD_CANCEL" << std::endl; spdlog::info("NFD_CANCEL" );
case (NFD_ERROR): case (NFD_ERROR):
std::cout << "NFD_Error: " << NFD_GetError() << std::endl; spdlog::error("NFD_Error: {0}" , NFD_GetError() );
break; break;
}; };

19
Editor/src/EditorCamera.h Normal file
View File

@ -0,0 +1,19 @@
#pragma once
#include "../../YoggieEngine/src/YoggieEngine.h"
class EditorCamera : public YoggieEngine::Camera {
public:
EditorCamera () : Camera(){
Front = glm::vec3(0.0f, 0.0f, 1.0f);
Right = glm::vec3(-1.0f, 0.0f, 0.0f);
Up = glm::vec3(0.0f, 1.0f, 0.0f);
}
private:
glm::vec3 Front;
glm::vec3 Right;
glm::vec3 Up;
};

View File

@ -1,13 +0,0 @@
#pragma once
#include "Project/Project.h"
struct EditorContext {
std::shared_ptr<Project> CurrentProject;
Scene MainScene;
EditorContext() = default;
EditorContext(EditorContext& other) = default;
~EditorContext() = default;
};

517
Editor/src/EditorLayer.h Normal file
View File

@ -0,0 +1,517 @@
#pragma once
#include <iostream>
#include <mini/ini.h>
#include <nfd.h>
#include <ImGuizmo.h>
#include <memory>
#include "Inspector.h"
#include "Console.h"
#include "IconsMaterialDesign.h"
#include "Project.h"
#include "EditorCamera.h"
using namespace YoggieEngine;
class EditorLayer : public Layer {
public:
EditorLayer() : Layer()
{
Logo.Load("rsc/Yoggie.png");
Selected = YoggieEngine::Entity{ (entt::entity)-1, (scene.get()) };
}
void OnStartup() override {
std::string path = (std::filesystem::current_path()).string();
scene = std::make_unique<Scene>();
project = std::make_unique<Project>();
project.get()->setProjectDirectory(path);
LoadLastOrEmptyProject();
//Console console = Console();
}
void OnUpdate() override {
scene.get()->Update();
renderer.get()->Render(*scene, *camera);
}
void OnUI() override {
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, { ImGui::GetWindowWidth(), 7 });
ImGui::BeginMainMenuBar();
int scaleFactor = 30;
ImGui::Image((ImTextureID)Logo.GetID(), { Logo.getSize().x / scaleFactor , Logo.getSize().y / scaleFactor });
ImGui::PopStyleVar();
if (ImGui::BeginMenu("App")) {
if (ImGui::MenuItem("Load Project"))
{
nfdresult_t result = NFD_OpenDialog({ "yproj" }, NULL, &path);
switch (result) {
case(NFD_OKAY):
//Project::LoadProject(path, project);
//AssetRegistry::setAssetPath(project.GetProjectDirectory());
//AssetRegistry::BuildAssetView();
break;
case(NFD_CANCEL):
break;
case(NFD_ERROR):
spdlog::error("NFD_Error: {0}", NFD_GetError());
break;
}
}
if (ImGui::MenuItem("Save project as...")) {
nfdresult_t result = NFD_SaveDialog({ "yproj" }, NULL, &path);
switch (result) {
case(NFD_OKAY):
spdlog::info("Save as: {0}", path);
//Project::SaveProject(path, project);
break;
case(NFD_CANCEL):
break;
case(NFD_ERROR):
spdlog::error("NFD_Error: {0}", NFD_GetError());
break;
}
}
ImGui::EndMenu();
}
if (ImGui::BeginMenu("Scene")) {
if (ImGui::MenuItem("Save scene"))
{
nfdresult_t result = NFD_SaveDialog({ "yscene" }, NULL, &path);
switch (result) {
case(NFD_OKAY):
//SaveScene(path, scene);
//project.AddScene(scene);
break;
case(NFD_CANCEL):
break;
case(NFD_ERROR):
std::cout << "NFD_Error: " << NFD_GetError() << std::endl;
break;
}
}
if (ImGui::MenuItem("Load scene"))
{
auto result = NFD_OpenDialog({ "yscene" }, NULL, &path);
switch (result) {
case (NFD_OKAY):
//LoadScene(path, scene);
break;
case(NFD_CANCEL):
break;
case(NFD_ERROR):
std::cout << "NFD_Error: " << NFD_GetError() << std::endl;
break;
}
}
if (ImGui::MenuItem("Add Entity"))
{
//scene.AddEntity("New Entity");
}
if (ImGui::MenuItem("Import Model"))
{
auto result = NFD_OpenDialog("obj,fbx,gltf", NULL, &path);
switch (result) {
case(NFD_OKAY):
// Import Model
/*
AssetRegistry::LoadFromSource(
path,
"build/Debug/Assets"//project.get()->GetProjectDirectory() / "Assets"
);
*/
break;
case(NFD_CANCEL):
break;
case(NFD_ERROR):
std::cout << "NFD_Error: " << NFD_GetError() << std::endl;
break;
}
}
if (ImGui::MenuItem("Import MeshAsset (temp)"))
{
auto result = NFD_OpenDialog("mesh", NULL, &path);
switch (result) {
case(NFD_OKAY):
{
}
break;
case(NFD_CANCEL):
spdlog::debug("User cancelled action");
break;
case(NFD_ERROR):
spdlog::warn("Something went wrong!");
break;
}
}
ImGui::EndMenu();
}
ImGui::SameLine(ImGui::GetWindowWidth() / 4 * 3);
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0.3f, 0.3f, 0.3f, 1.0f));
ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 3.0f);
ImGui::Button(ICON_MD_ROCKET_LAUNCH "Project");
ImGui::SameLine(ImGui::GetWindowWidth() - 120);
ImGui::PopStyleColor(1);
ImGui::PopStyleVar();
ImGui::EndMainMenuBar();
ImGui::Begin("RuntimeControls");
ImGui::BeginGroup();
ImGui::SameLine();
ImGui::Text(ICON_MD_TRANSFORM);
auto spacing = 10;
float buttonWidth = 75.0f;
float buttonHeight = 30;
float ColorIntensity = 0.5f;
float ColorIntensityHovered = 0.75;
float ColorIntensityActive = 0.85;
float yPadding = 6.f;
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2{0, yPadding });
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4{ 0.0f,ColorIntensity ,0.0f ,1.0f });
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4{ 0.0f,ColorIntensityHovered ,0.0f ,1.0f });
ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4{ 0.0f,ColorIntensityActive ,0.0f ,1.0f });
ImGui::SameLine(0, spacing);
if (ImGui::Button("Translate", { buttonWidth,buttonHeight }))
activeOperation = ImGuizmo::OPERATION::TRANSLATE;
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2{ 0, yPadding });
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4{ ColorIntensity, 0.0f ,0.0f ,1.0f });
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4{ ColorIntensityHovered, 0.0f ,0.0f ,1.0f });
ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4{ ColorIntensityActive, 0.0f ,0.0f ,1.0f });
ImGui::SameLine(0, spacing);
if (ImGui::Button("Rotate", { buttonWidth,buttonHeight }))
activeOperation = ImGuizmo::OPERATION::ROTATE;
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2{ 0, yPadding });
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4{ 0.0f, 0.0f ,ColorIntensity ,1.0f });
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4{ 0.0f, 0.0f ,ColorIntensityHovered ,1.0f });
ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4{ 0.0f, 0.0f ,ColorIntensityActive ,1.0f });
ImGui::SameLine(0, spacing);
if (ImGui::Button("Scale", { buttonWidth,buttonHeight }))
activeOperation = ImGuizmo::OPERATION::SCALE;
ImGui::PopStyleColor(9);
ImGui::PopStyleVar(3);
ImGui::EndGroup();
ImGui::SameLine((ImGui::GetWindowContentRegionMax().x / 2) - (90));
auto color = ImVec4{ 0.001 * 12 , 0.001 * 201 , 0.001 * 69, 1.0f };
ImGui::PushStyleColor(ImGuiCol_Button, color);
const float strengthIncrease = 1.5f;
ImGui::PushStyleColor(
ImGuiCol_ButtonHovered,
ImVec4{
color.x * strengthIncrease,
color.y * strengthIncrease,
color.z * strengthIncrease,
color.w
}
);
if (ImGui::Button(ICON_MD_PLAY_ARROW, { 90,25 })) {
// Play game
}
ImGui::PopStyleColor(2);
ImGui::SameLine();
color = ImVec4{ 0.001 * 14, 0.001 * 157, 0.001 * 201, 1.0f };
ImGui::PushStyleColor(ImGuiCol_Button, color);
ImGui::PushStyleColor(
ImGuiCol_ButtonHovered,
ImVec4{
color.x * strengthIncrease,
color.y * strengthIncrease,
color.z * strengthIncrease,
color.w
}
);
if (ImGui::Button(ICON_MD_ELECTRIC_BOLT, { 90,25 })) {
// Simulate physics
}
ImGui::PopStyleColor(2);
ImGui::End();
unsigned int viewportWindowFlags = ImGuiWindowFlags_NoTitleBar
| ImGuiWindowFlags_NoDecoration
| ImGuiWindowFlags_NoScrollbar
| ImGuiWindowFlags_NoMove
| ImGuiWindowFlags_NoCollapse;
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2{ 0,0 });
ImGui::Begin("SceneView",nullptr,viewportWindowFlags);
// spdlog::info("{0}x{1}", ImGui::GetWindowWidth(), ImGui::GetWindowHeight());
SceneisFocused = ImGui::IsWindowFocused() || ImGui::IsWindowHovered();
ImGui::Image((ImTextureID)(intptr_t)renderer.get()->getCurrentFrameBuffer().GetColourAttachment(),
ImVec2{(float)ImGui::GetWindowWidth(),(float)ImGui::GetWindowHeight()});
//ImGuizmo::ViewManipulate(glm::value_ptr(cameraView), 1, ImGui::GetWindowPos(), { 90,90 }, 0x22CCCCCCC);
if(Selected.isValid()){
ImGuizmo::SetOrthographic(false);
ImGuizmo::SetDrawlist();
ImGuizmo::SetRect(ImGui::GetWindowPos().x, ImGui::GetWindowPos().y, ImGui::GetWindowWidth(), ImGui::GetWindowHeight());
const auto& ProjMatrix = camera->getProjection(ImGui::GetWindowWidth(), ImGui::GetWindowHeight());
const glm::mat4& viewMatrix = glm::inverse(camera->getTransform());
auto& tc = Selected.GetComponent<YoggieEngine::TransformComponent>();
auto transform = tc.GetTransform();
ImGuizmo::Manipulate(
glm::value_ptr(viewMatrix),
glm::value_ptr(ProjMatrix),
activeOperation, ImGuizmo::LOCAL, glm::value_ptr(transform));
if (ImGuizmo::IsUsing())
{
tc.Decompose(transform);
}
}
ImGui::End();
ImGui::PopStyleVar();
ImGui::Begin("EditorCamera");
ImGui::SliderFloat3("position", glm::value_ptr(camera->Position), -50, 50);
ImGui::End();
ImGui::Begin(ICON_MD_MENU "SceneExplorer",nullptr);
scene.get()->getReg().each([&](entt::entity enttNumber) {
YoggieEngine::Entity entity = YoggieEngine::Entity(enttNumber, &*scene.get());
auto id = entity.GetComponent<YoggieEngine::IdentifierComponent>();
if (ImGui::Selectable(id.name.c_str(), entity == Selected)) {
Selected = YoggieEngine::Entity(enttNumber, &*scene);
}
});
ImGui::End();
{
ImGui::Begin("Asset", nullptr);
const char* hidden_extensions[]{
".exe",
".pdb",
".idb",
".dll",
".ini"
};
std::vector <Asset> files = std::vector<Asset>();
int iconSize = 60;
int maxColumns = 3;
YoggieEngine::Texture folderIcon;
YoggieEngine::Texture assetIcon;
//assetIcon = YoggieEngine::Texture("rsc/AssetIcon.png");
ImGui::DragInt("IconSize", &iconSize, 1, 30, 90);
ImGui::DragInt("Max. Columns", &maxColumns, 1, 1, 6);
if (ImGui::BeginTable("##Resources", 3)) {
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0.f, 0.f, 0.f, 0.f));
ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(0.f, 0.f, 0.f, 0.f));
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(1.f, 1.f, 1.f, 0.2f));
int row = 0;
int column = 0;
for (auto& asset : files) {
if (column % 3 == 0) {
ImGui::TableNextRow();
column = 0;
row++;
}
ImGui::TableSetColumnIndex(column);
ImGui::ImageButton(
(ImTextureID)assetIcon.GetID(),
ImVec2{ (float)iconSize, (float)iconSize });
ImGui::Text(asset.Handle.String().c_str(), row);
column++;
}
ImGui::PopStyleColor(3);
ImGui::EndTable();
}
ImGui::End();
}
ImGui::ShowDemoWindow();
//ImGui::ShowMetricsWindow();
}
void OnCreate() override {
spdlog::info(" Layer Create!" );
}
void OnDestroy() override {
spdlog::info( " Layer Destroy!" );
}
bool OnKey(int key, int mode) override {
float movement_speed = 0.10f;
if (SceneisFocused) {
if (key == YOGGIE_KEY_UP)
camera->Rotation.x += movement_speed;
if (key == YOGGIE_KEY_DOWN)
camera->Rotation.x -= movement_speed;
if (key == YOGGIE_KEY_LEFT)
camera->Rotation.y += movement_speed;
if (key == YOGGIE_KEY_RIGHT)
camera->Rotation.y -= movement_speed;
if (key == YOGGIE_KEY_A)
camera->Position += glm::vec3(1.0f, 0.0f, 0.0f) * movement_speed;
if (key == YOGGIE_KEY_S)
camera->Position += glm::vec3(0.0f, 0.0f, -1.0f) * movement_speed;
if (key == YOGGIE_KEY_D)
camera->Position -= glm::vec3(1.0f, 0.0f, 0.0f) * movement_speed;
if (key == GLFW_KEY_W)
camera->Position -= glm::vec3(0.0f, 0.0f, -1.0f) * movement_speed;
}
return true;
}
private:
std::unique_ptr<Inspector> inspector = std::make_unique<Inspector>(Selected);
std::unique_ptr<Renderer> renderer = std::make_unique<Renderer>();
std::unique_ptr<EditorCamera> camera = std::make_unique<EditorCamera>();
std::unique_ptr<Project> project;
std::unique_ptr<Scene> scene;
Texture Logo;
bool SimulatePhysics = true;
bool SceneisFocused = false;
YoggieEngine::Entity Selected;
ImGuizmo::OPERATION activeOperation = ImGuizmo::OPERATION::TRANSLATE;
char* path = nullptr;
void LoadLastOrEmptyProject() {
// Check if there is a last known loaded project and
// load that one .
// Otherwise load no project..
// OR
// Load an empty project.
mINI::INIStructure ini;
if (std::filesystem::exists("build\\Debug\\Editor.ini"))
{
mINI::INIFile file("build\\Debug\\Editor.ini");
file.read(ini);
}
else
{
spdlog::debug("Could not find an `Editor.ini` file.");
}
if (ini["editor"]["openlastproject"] == "TRUE")
{
Project::LoadProject(ini["cache"]["project"], *project);
///LoadScene(ini["cache"]["scene"], scene);
}
else
{
spdlog::debug("Starting without a project. Please create one.");
}
}
};

27
Editor/src/EditorWindow.h Normal file
View File

@ -0,0 +1,27 @@
#pragma once
#include <imgui.h>
#include <string>
class EditorWindow {
public:
EditorWindow (const std::string& name, ImGuiWindowFlags_ flags = ImGuiWindowFlags_None ) : name(name) , flags(flags) {}
void Update()
{
ImGui::Begin(name.c_str(), nullptr, flags);
Draw();
ImGui::End();
}
~EditorWindow() = default;
protected:
std::string name;
private:
ImGuiWindowFlags_ flags;
virtual void Draw() = 0;
};

File diff suppressed because it is too large Load Diff

197
Editor/src/Inspector.cpp Normal file
View File

@ -0,0 +1,197 @@
#include "Inspector.h"
#include "TransformVec3.h"
#include "IconsMaterialDesign.h"
void Inspector::Draw()
{
if (selected.isValid()) {
AddComponentDropDown();
ShowComponents();
}
}
void AddComponent(YoggieEngine::Entity selected , int i) {
switch (i) {
case 0:
selected.AddComponent<YoggieEngine::ScriptComponent>();
break;
case 1:
selected.AddComponent<YoggieEngine::CameraComponent>();
break;
case 2:
selected.AddComponent<YoggieEngine::LightComponent>();
break;
case 3:
selected.AddComponent<YoggieEngine::Render3DComponent>();
default:
break;
}
}
void Inspector::AddComponentDropDown()
{
static char* names[] = { "Script Component", "Camera Component", "Light Component", "Render3D"};
if (ImGui::Button("Add Component"))
ImGui::OpenPopup("Component picker");
ImGui::SameLine();
if (ImGui::BeginPopup("Component picker")) {
for (int i = 0; i < IM_ARRAYSIZE(names); i++) {
if (ImGui::MenuItem(names[i]))
AddComponent(selected, i);
}
ImGui::EndPopup();
}
ImGui::NewLine();
}
void Inspector::ShowComponents()
{
auto component = selected.GetComponent<YoggieEngine::IdentifierComponent>();
ImGui::InputText("Name:", (char*)component.name.c_str(), component.name.size() * sizeof(char), ImGuiInputTextFlags_ReadOnly);
if (selected.HasComponent<YoggieEngine::TransformComponent>()) {
auto& transform = selected.GetComponent<YoggieEngine::TransformComponent>();
if (ImGui::CollapsingHeader("Transform", ImGuiTreeNodeFlags_DefaultOpen)) {
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4{ 1.0, 1.0f, 1.0f, 0.0f });
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4{ 1.0, 1.0f, 1.0f, 0.0f });
ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4{ 1.0, 1.0f, 1.0f, 0.0f });
ImGui::SetCursorPosX(ImGui::GetContentRegionMax().x - 20);
ImGui::Button(ICON_MD_SETTINGS, { 20,20 });
ImGui::OpenPopupOnItemClick("##myContext", ImGuiPopupFlags_MouseButtonRight);
if (ImGui::BeginPopupContextWindow("##myContext")) {
if (ImGui::MenuItem("Reset")) {
spdlog::info("Reset component");
}
if (ImGui::MenuItem("Copy Component")) {
spdlog::info("Copy component");
}
ImGui::EndPopup();
}
ImGui::PopStyleColor(3);
/*
ImGui::DragFloat3("Position", glm::value_ptr(transform.Position), 0.1f);
ImGui::DragFloat3("Rotation", glm::value_ptr(transform.Rotation), 0.1f);
ImGui::DragFloat3("Scale", glm::value_ptr(transform.Scale), 0.1f, 0.0f);
*/
auto something = glm::value_ptr(transform.Position);
ImGuiExtension::TransformVec3("Position", transform.Position);
ImGuiExtension::TransformVec3("Rotation", transform.Rotation);
ImGuiExtension::TransformVec3("Scale", transform.Scale);
}
if (selected.HasComponent<YoggieEngine::RelationComponent>()) {
ImGui::Text("Has relation");
}
}
if (selected.HasComponent<YoggieEngine::Render3DComponent>()) {
auto& render3d = selected.GetComponent<YoggieEngine::Render3DComponent>();
const char* AssetNames[]{ "Asset1" , "Asset2" };
if (ImGui::CollapsingHeader("Render3D", ImGuiTreeNodeFlags_DefaultOpen)) {
if (ImGui::Button("Select Renderable Asset"))
ImGui::OpenPopup("Renderable_list_popup");
ImGui::SameLine();
ImGui::TextUnformatted(render3d.mesh.elements.empty() ? "<None>" : "ASSET_GUID_OR_ID");
if (ImGui::BeginPopup("Renderable_list_popup")) {
ImGui::Text("None");
ImGui::Separator();
for (int i = 0; i < IM_ARRAYSIZE(AssetNames); i++) {
if(ImGui::Selectable(AssetNames[i]))
{ }
}
ImGui::EndPopup();
}
ImGui::ColorEdit3("Colour", glm::value_ptr(render3d.color));
ImGui::Checkbox("Use static rendering:", &render3d.isStatic);
}
}
static bool deferred = true;
if (selected.HasComponent<YoggieEngine::LightComponent>()) {
auto& light = selected.GetComponent<YoggieEngine::LightComponent>();
if (ImGui::CollapsingHeader("Light", ImGuiTreeNodeFlags_DefaultOpen)) {
ImGui::ColorEdit3("Colour", glm::value_ptr(light.Color));
ImGui::Checkbox("Deferred", &deferred);
}
}
if (selected.HasComponent <YoggieEngine::CameraComponent>()) {
auto& camera = selected.GetComponent<YoggieEngine::CameraComponent>();
if (ImGui::CollapsingHeader("Camera")) {
ImGui::DragFloat3("Position:", glm::value_ptr(camera.Position), 0.01f);
ImGui::DragFloat3("Rotation:", glm::value_ptr(camera.Rotation), 0.01f);
}
}
if (selected.HasComponent<YoggieEngine::RigidBody>()) {
auto& rigibody = selected.GetComponent<YoggieEngine::RigidBody>();
if (ImGui::CollapsingHeader("RigidBody")) {
}
}
if (selected.HasComponent<YoggieEngine::ScriptComponent>()) {
const char* AssetNames[]{ "Script 1" , "Script 2" };
if (ImGui::CollapsingHeader("Script", ImGuiTreeNodeFlags_Leaf)) {
if (ImGui::Button("Select Renderable Asset"))
ImGui::OpenPopup("Scripts_list_popup");
if (ImGui::BeginPopup("Scripts_list_popup")) {
ImGui::Text("None");
ImGui::Separator();
for (int i = 0; i < IM_ARRAYSIZE(AssetNames); i++) {
if (ImGui::Selectable(AssetNames[i]))
{
}
}
ImGui::EndPopup();
}
ImGui::SameLine();
std::string scriptAssetId = "<Random_GUID>";
ImGui::InputText("asset", scriptAssetId.data(), scriptAssetId.length(), ImGuiInputTextFlags_ReadOnly | ImGuiInputTextFlags_AutoSelectAll);
}
}
}
void ComponentView(const std::string& componentName, voidFunction func)
{
ImGuiWindowFlags_ window_flags = ImGuiWindowFlags_None;
ImGui::PushStyleVar(ImGuiStyleVar_ChildRounding, 5.0f);
ImGui::BeginChild(componentName.c_str());
func();
ImGui::EndChild();
ImGui::PopStyleVar();
}

22
Editor/src/Inspector.h Normal file
View File

@ -0,0 +1,22 @@
#pragma once
#include "../../YoggieEngine/src/YoggieEngine.h"
#include "EditorWindow.h"
typedef void (*voidFunction) (void);
inline void ComponentView(const std::string& componentName, voidFunction func);
class Inspector : public EditorWindow {
public:
Inspector( YoggieEngine::Entity& selected ) : EditorWindow("Inspector"), selected(selected){}
void Draw()override;
private:
void AddComponentDropDown();
void ShowComponents();
YoggieEngine::Entity& selected;
};

View File

@ -13,6 +13,15 @@ void Project::SaveProject(std::filesystem::path path, Project& project)
projectYAML << YAML::Key << "Project" << YAML::Value << project.Name; projectYAML << YAML::Key << "Project" << YAML::Value << project.Name;
projectYAML << YAML::Key << "Directory" << YAML::Value << path.parent_path().u8string(); projectYAML << YAML::Key << "Directory" << YAML::Value << path.parent_path().u8string();
projectYAML << YAML::EndMap; projectYAML << YAML::EndMap;
projectYAML << YAML::BeginMap;
projectYAML << YAML::Key << "Scenes" << YAML::Value << YAML::BeginSeq;
for (auto scene : project.Scenes) {
projectYAML << scene->name;
}
projectYAML << YAML::EndSeq;
std::ofstream projectFile; std::ofstream projectFile;
projectFile.open(path.u8string()); projectFile.open(path.u8string());
@ -20,8 +29,13 @@ void Project::SaveProject(std::filesystem::path path, Project& project)
projectFile.close(); projectFile.close();
} }
void Project::LoadProject(std::filesystem::path path, std::shared_ptr<Project>& project) void Project::LoadProject(std::filesystem::path path, Project& project)
{ {
if (!std::filesystem::exists(path)) {
throw std::runtime_error("Couldn't find project file!");
}
std::string YAMLProject; std::string YAMLProject;
std::stringstream sstream; std::stringstream sstream;
std::ifstream projectFile; std::ifstream projectFile;
@ -36,10 +50,9 @@ void Project::LoadProject(std::filesystem::path path, std::shared_ptr<Project>&
YAML::Node node = YAML::Load(YAMLProject); YAML::Node node = YAML::Load(YAMLProject);
// this is probably not perfect but it seems to work for now // this is probably not perfect but it seems to work for now
project.reset(); project = node.as<Project>();
project = std::make_shared<Project>(node.as<Project>());
std::cout << "loading..." << project.get()->Name << std::endl; spdlog::info("loaded project {0}", project.Name);
@ -55,12 +68,19 @@ namespace YAML {
{ {
if (!node.IsMap()) if (!node.IsMap())
return false; return false;
rhs.setName(node["Project"].as<std::string>());
rhs.setProjectDirectory(node["Directory"].as<std::string>()); std::string projectName = node["Project"].as<std::string>();
rhs.setName(projectName);
std::string projectDirectory = node["Directory"].as<std::string>();
rhs.setProjectDirectory(projectDirectory);
return true; return true;
} }
}; };
} }

View File

@ -1,11 +1,15 @@
#pragma once #pragma once
#include <filesystem> #include <filesystem>
#include <iostream> #include <iostream>
#include "../../YoggieEngine/src/YoggieEngine.h"
#include <yaml-cpp/yaml.h>
class Project { class Project {
public: public:
Project() = default; Project() = default;
Project(const std::string& name): Name(name){} Project(const std::string& name): Name(name){}
~Project() { std::cout << "Unloading project..." << Name << std::endl; } ~Project() { spdlog::info("Unloading project {0}...", Name);}
void setName(std::string& name) { Name = name; } void setName(std::string& name) { Name = name; }
const std::string& GetName()const { return Name; } const std::string& GetName()const { return Name; }
@ -13,10 +17,21 @@ public:
void setProjectDirectory(std::string& path) { ProjectDirectory = std::filesystem::path(path); } void setProjectDirectory(std::string& path) { ProjectDirectory = std::filesystem::path(path); }
const std::filesystem::path GetProjectDirectory() { return ProjectDirectory; } const std::filesystem::path GetProjectDirectory() { return ProjectDirectory; }
void AddScene(YoggieEngine::Scene& scene)
{
Scenes.push_back(&scene);
}
static void SaveProject(std::filesystem::path path, Project& project); static void SaveProject(std::filesystem::path path, Project& project);
static void LoadProject(std::filesystem::path path, std::shared_ptr<Project>& project); static void LoadProject(std::filesystem::path path, Project& project);
private: private:
std::string Name; std::string Name;
std::filesystem::path ProjectDirectory; std::filesystem::path ProjectDirectory;
std::vector<YoggieEngine::Scene*> Scenes;
friend class YAML::convert<Project>;
}; };

View File

@ -1,68 +0,0 @@
#pragma once
#include "../../YoggieEngine/src/AssetManager/ModelImporter.h"
#include "../../YoggieEngine/src/Graphics/Memory/Framebuffer.h"
#include "../../YoggieEngine/src/PerfCounter.h"
#include "../../YoggieEngine/src/Scene/Entity.h"
#include "Project/Project.h"
class EditorRuntime : public ApplicationRuntime {
public:
EditorRuntime() = default;
void Start() override
{
CurrentProject = std::make_shared<Project>("Random");
framebuffer = new Framebuffer();
// Create a level and load it as the current level
auto importer = ModelImporter();
// Create a cube
Model = importer.Import("build/Debug/Models/Cube.obj");
cube = MainScene.AddEntity("cube");
auto& render3DComponent = cube.AddComponent<Render3DComponent>();
render3DComponent.mesh = *(Model->renderable->mesh);
cube.GetComponent<TransformComponent>().Position = glm::vec3(1.0f, 0.0f, 5.0f);
auto cube2 = MainScene.AddEntity("Cube1");
auto& rendercube2 = cube2.AddComponent<Render3DComponent>();
rendercube2.mesh = *(Model->renderable->mesh);
// create an ambient light source
auto AmbientLight = MainScene.AddEntity("AmbientLight");
auto light = AmbientLight.AddComponent<LightComponent>();
light.Color = glm::vec3(1.0f);
light.Strength = 1.0f;
Selected = (entt::entity)-1;
}
void Update() override
{
}
void FixedUpdate() override
{
}
void Stop() override
{
}
private:
std::shared_ptr<Project> CurrentProject = nullptr;
Scene MainScene;
Framebuffer* framebuffer;
SceneObject* Model;
Entity cube;
entt::entity Selected;
friend class Editor;
};

View File

@ -1,139 +0,0 @@
#pragma once
#include <yaml-cpp/yaml.h>
#include <yaml-cpp/node/type.h>
#include <string>
#include <filesystem>
#include <fstream>
#include "../../YoggieEngine/src/Scene/Entity.h"
void WriteFile(std::string& emitter, std::filesystem::path path)
{
std::cout << "Writing Scene file to: " << path.u8string() << std::endl;
std::ofstream sceneFile;
sceneFile.open(path.u8string());
sceneFile << emitter.c_str();
sceneFile.close();
}
YAML::Emitter& operator<< (YAML::Emitter& emitter, glm::vec3& vector) {
emitter << YAML::Flow << YAML::BeginSeq << vector.x << vector.y << vector.x << YAML::EndSeq;
return emitter;
}
std::string Serialize( Scene& scene) {
YAML::Emitter emitter;
emitter << YAML::BeginMap;
emitter << YAML::Key << "Scene" << YAML::Value << "test-Scene";
emitter << YAML::Key << "Entities" << YAML::Value << YAML::BeginSeq;
scene.getReg().each([&scene, &emitter](auto enttNumber) {
Entity entity = Entity(enttNumber, &scene);
emitter << YAML::BeginMap;
emitter << YAML::Key << "Entity" << YAML::Value << entity.GetComponent<IdentifierComponent>().name;
if (entity.HasComponent<IdentifierComponent>()) {
emitter << YAML::Key << "Ident";
emitter << YAML::BeginMap;
emitter << YAML::Value << entity.GetComponent<IdentifierComponent>().name;
emitter << YAML::EndMap;
}
if (entity.HasComponent<TransformComponent>()) {
emitter << YAML::Key << "Transform" << YAML::Value ;
emitter << YAML::BeginMap;
emitter << YAML::Key << "Position";
emitter << YAML::Value << entity.GetComponent<TransformComponent>().Position;
emitter << YAML::Key << "Rotation";
emitter << YAML::Value << entity.GetComponent<TransformComponent>().Rotation;
emitter << YAML::Key << "Scale";
emitter << YAML::Value << entity.GetComponent<TransformComponent>().Scale;
emitter << YAML::EndMap;
}
if (entity.HasComponent<LightComponent>()) {
emitter << YAML::Key << "Light";
emitter << YAML::Value;
emitter << YAML::BeginMap;
emitter << YAML::Key << "strength";
emitter << YAML::Value << entity.GetComponent<LightComponent>().Strength;
emitter << YAML::Key << "Color";
emitter << YAML::Value << entity.GetComponent<LightComponent>().Color;
emitter << YAML::EndMap;
}
emitter << YAML::EndMap;
});
emitter << YAML::EndSeq;
emitter << YAML::EndMap;
return std::string(emitter.c_str());
}
void SaveScene(std::filesystem::path path, Scene& scene) {
std::string YAMLString = Serialize(scene);
WriteFile(YAMLString, path);
}
void LoadScene(std::filesystem::path path, Scene& scene)
{
auto sceneYAML = YAML::LoadFile(path.u8string());
if (!sceneYAML["Scene"]) {
spdlog::error("Not a scene file!");
return;
}
scene.getReg().clear();
std::string SceneName = sceneYAML["Scene"].as<std::string>();
auto entities = sceneYAML["Entities"];
for (const auto& entity : entities) {
std::string entityID = entity["Ident"].as<std::string>();
YoggieEngine::Entity SE = scene.AddEntity(entityID);
if (entity["Transform"])
{
TransformComponent tc = SE.GetComponent<TransformComponent>();
auto positionNode = entity["Transform"]["Position"];
tc.Position = glm::vec3(positionNode[0].as<float>(), positionNode[1].as<float>(), positionNode[2].as<float>());
auto rotationNode = entity["Transform"]["Rotation"];
tc.Rotation = glm::vec3(rotationNode[0].as<float>(), rotationNode[1].as<float>(), rotationNode[2].as<float>());
auto scaleNode = entity["Transform"]["Scale"];
tc.Scale = glm::vec3(scaleNode[0].as<float>(), scaleNode[1].as<float>(), scaleNode[2].as<float>());
}
if (entity["Light"]) {
LightComponent lc = SE.AddComponent<LightComponent>();
lc.Strength = entity["Light"]["strength"].as<float>();
lc.Color = glm::vec3(entity["Light"]["Color"][0].as<float>(), entity["Light"]["Color"][1].as<float>(), entity["Light"]["Color"][2].as<float>());
}
}
}

View File

@ -0,0 +1,59 @@
#pragma once
#include <imgui_widgets.cpp>
#include <glm/glm.hpp>
namespace ImGuiExtension {
void TransformVec3(const char* label, glm::vec3& vector) {
ImGui::PushID(label);
ImGui::Columns(2);
ImGui::SetColumnWidth(0, 100.0f);
ImGui::Text(label);
ImGui::NextColumn();
ImGui::PushMultiItemsWidths(3, ImGui::CalcItemWidth());
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2{ 0, 0 });
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4{ 0.8f, 0.1f, 0.15f, 1.0f });
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4{ 0.9f,0.2f,0.2f, 1.0f });
ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4{ 0.8f,0.1f,0.15f, 1.0f });
if (ImGui::Button("X"))
vector.x = 0;
ImGui::PopStyleColor(3);
ImGui::SameLine();
ImGui::DragFloat("##X", &glm::value_ptr(vector)[0], 0.1f, 0.0f, 0.0f, "%.2f");
ImGui::PopItemWidth();
ImGui::SameLine();
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4{ 0.2f, 0.7f, 0.2f, 1.0f });
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4{ 0.3f,0.8f,0.3f, 1.0f });
ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4{ 0.2f,0.7f,0.2f, 1.0f });
if (ImGui::Button("Y"))
vector.y = 0;
ImGui::PopStyleColor(3);
ImGui::SameLine();
ImGui::DragFloat("##Y", &glm::value_ptr(vector)[1], 0.1f, 0.0f, 0.0f, "%.2f");
ImGui::PopItemWidth();
ImGui::SameLine();
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4{ 0.1f, 0.25f, 0.8f, 1.0f });
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4{ 0.2f,0.35f,0.9f, 1.0f });
ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4{ 0.1f,0.25f,0.8f, 1.0f });
if (ImGui::Button("Z"))
vector.z = 0;
ImGui::PopStyleColor(3);
ImGui::SameLine();
ImGui::DragFloat("##Z", &glm::value_ptr(vector)[2], 0.1f, 0.0f, 0.0f, "%.2f");
ImGui::PopItemWidth();
ImGui::PopStyleVar();
ImGui::Columns(1);
ImGui::PopID();
}
}

View File

@ -1,18 +0,0 @@
#pragma once
#include <imgui.h>
class EditorConsole
{
public:
EditorConsole();
~EditorConsole();
void Draw();
void AddLog(const char* fmt, ...);
private:
ImVector<char*> Items;
bool AutoScroll;
bool ScrollToBottom;
};

View File

@ -1,228 +0,0 @@
#include "widgets.h"
#include "EditorConsole.h"
#include <iostream>
#include "../../YoggieEngine/src/Scene/Components.h"
#include "../../YoggieEngine/src/Scene/Entity.h"
#include "../AssetManagement/AssetManager.h"
class Editor;
void ComponentView(const std::string& componentName, voidFunction func)
{
ImGuiWindowFlags_ window_flags = ImGuiWindowFlags_None;
ImGui::PushStyleVar(ImGuiStyleVar_ChildRounding, 5.0f);
ImGui::BeginChild(componentName.c_str());
func();
ImGui::EndChild();
ImGui::PopStyleVar();
}
void Inspector(entt::entity ent , Scene& scene) {
ImGui::Begin("Inspector");
static char* names[] = { "Script Component", "Camera Component" };
static float Zoom = 90;
static glm::vec3 Position = glm::vec3(0.0f, 0.0f, 0.0f);
static glm::vec3 Rotation = glm::vec3(0.0f, 0.0f, 0.0f);
if (scene.getReg().valid(ent)) {
Entity entity = Entity(ent, &scene);
if (ImGui::Button("Add Component"))
ImGui::OpenPopup("Component picker");
ImGui::SameLine();
if (ImGui::BeginPopup("Component picker")) {
for (int i = 0; i < IM_ARRAYSIZE(names); i++)
if (ImGui::MenuItem(names[i])) {
std::cout << "Add a " << names[i] << " to "
<< entity.GetComponent<IdentifierComponent>().name << std::endl;
}
ImGui::EndPopup();
}
ImGui::NewLine();
auto component = entity.GetComponent<IdentifierComponent>();
char* buf = new char(component.name.size());
strcpy(buf, component.name.c_str());
ImGui::InputText("Name:",buf , sizeof(buf), ImGuiInputTextFlags_ReadOnly);
if (entity.HasComponent<TransformComponent>()) {
auto& transform = entity.GetComponent<TransformComponent>();
if (ImGui::CollapsingHeader("Transform", ImGuiTreeNodeFlags_DefaultOpen)) {
ImGui::DragFloat3("Position", glm::value_ptr(transform.Position), 0.01f);
ImGui::DragFloat3("Rotation", glm::value_ptr(transform.Rotation), 0.01f);
ImGui::DragFloat3("Scale", glm::value_ptr(transform.Scale), 0.01f, 0.0f);
}
}
if (entity.HasComponent<Render3DComponent>()) {
auto& render3d = entity.GetComponent<Render3DComponent>();
if (ImGui::CollapsingHeader("Render3D", ImGuiTreeNodeFlags_DefaultOpen)) {
ImGui::ColorEdit3("Colour", glm::value_ptr(render3d.color));
}
}
if (entity.HasComponent<LightComponent>()) {
auto& light = entity.GetComponent<LightComponent>();
if (ImGui::CollapsingHeader("Light", ImGuiTreeNodeFlags_DefaultOpen)) {
ImGui::DragFloat("Strength", &light.Strength, 0.001f);
ImGui::ColorEdit3("Colour", glm::value_ptr(light.Color));
}
}
if (entity.HasComponent <CameraComponent>()) {
auto& camera = entity.GetComponent<CameraComponent>();
ComponentView("Camera", [] {
ImGui::SliderFloat("Zoom", &Zoom, 10, 190);
ImGui::InputFloat3("Position:", &Position[0]);
ImGui::InputFloat3("Rotation:", &Rotation[0]);
});
}
if (entity.HasComponent<ScriptComponent>()) {
ComponentView("Scripting", [] {
ImGui::LabelText("##--", "Hello scripting");
});
}
}
ImGui::End();
}
void SceneExplorer(entt::entity& selected, Scene& scene )
{
ImGui::Begin("Scene Explorer");
scene.getReg().each([&](entt::entity enttNumber) {
Entity entity = Entity(enttNumber, &scene);
auto id = entity.GetComponent<IdentifierComponent>();
if (ImGui::Selectable(id.name.c_str(), enttNumber == selected )) {
selected = enttNumber;
}
});
ImGui::End();
}
void Viewport(Framebuffer& framebuffer) {
unsigned int viewportWindowFlags = ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoScrollbar ;
ImGui::Begin("Viewport", false, viewportWindowFlags);
ImGui::Image((void*)(intptr_t)framebuffer.GetColourAttachment(), ImVec2{ (float)800,(float)600 });
ImGuizmo::SetDrawlist();
ImGuizmo::SetRect(ImGui::GetWindowPos().x, ImGui::GetWindowPos().y, ImGui::GetWindowWidth(), ImGui::GetWindowHeight());
ImGuizmo::Enable(true);
auto cam = glm::mat4(1.0f);
auto eye = glm::vec3(0.0f);
auto center = glm::vec3(0.0f);
auto up = glm::vec3(0.0f, 1.0f, 0.0f);
auto view = glm::lookAt(eye, center, up);
glm::mat4 projection = glm::perspective(glm::radians(90.0f), (800.0f / 600.0f), 0.001f, 100.0f);
auto transformMatrix = glm::mat4(1.0f);
ImGuizmo::Manipulate(glm::value_ptr(view), glm::value_ptr(projection), ImGuizmo::TRANSLATE, ImGuizmo::WORLD, glm::value_ptr(transformMatrix));
//ImGuizmo::Manipulate(glm::value_ptr(static_cam), glm::value_ptr(static_projection), ImGuizmo::TRANSLATE, ImGuizmo::WORLD, glm::value_ptr(trans));
ImGuizmo::ViewManipulate(glm::value_ptr(cam), 8.0f, ImVec2{ 0.0f,0.0f }, ImVec2{ 128.0f,128.0f }, 0x10101010);
ImGui::End();
}
void GamePort(Framebuffer& framebuffer)
{
unsigned int viewportWindowFlags = ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoScrollbar;
ImGui::Begin("Game", false, viewportWindowFlags);
ImGui::Image((void*)(intptr_t)framebuffer.GetColourAttachment(), ImVec2{ (float)800, (float)600 });
ImGui::End();
}
void Settings() {
ImGui::Begin("Settings");
ImGui::LabelText("##title-settings", "Fine grain control over your engine... ");
ImGui::End();
}
auto console = EditorConsole();
void Console() {
ImGui::Begin("Console", false);
console.Draw();
ImGui::End();
}
void AssetsFinder() {
static YoggieEngine::Texture folderIcon ("rsc/folderIcon.png");
static YoggieEngine::Texture AssetIcon("rsc/assetIcon.png");
static int iconSize = 60;
ImGui::Begin("Asset-Finder", false);
ImGui::DragInt("IconSize", &iconSize, 1, 30, 90);
if (ImGui::BeginTable("##resources", 3))
{
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0.f, 0.f, 0.f, 0.f));
ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(0.f, 0.f, 0.f, 0.f));
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(1.f, 1.f, 1.f, 0.2f));
int row = 0;
int column = 0 ;
for (auto& asset : AssetManager::assets) {
if (column % 3 == 0) {
ImGui::TableNextRow();
column = 0;
row++;
}
ImGui::TableSetColumnIndex(column);
if (asset.isFolder) {
ImGui::ImageButton(
(ImTextureID)folderIcon.GetID(),
ImVec2{ (float)iconSize,(float)iconSize });
ImGui::Text(asset.GetName(), row);
}
else {
ImGui::ImageButton(
(ImTextureID)AssetIcon.GetID(),
ImVec2{ (float)iconSize, (float)iconSize });
ImGui::Text(asset.GetName(), row);
}
column++;
}
ImGui::PopStyleColor(3);
ImGui::EndTable();
}
ImGui::End();
}

View File

@ -1,28 +0,0 @@
#pragma once
#include <glm/glm.hpp>
#include <imgui.h>
#include <string>
#include <entt/entt.hpp>
#include <entt/entity/fwd.hpp>
#include "../../libs/guizmo/ImGuizmo.h"
#include "../../YoggieEngine/src/YoggieEngine.h"
typedef void ( *voidFunction ) (void);
using namespace YoggieEngine;
void ComponentView(const std::string& componentName, voidFunction func);
void Inspector(entt::entity entity, Scene& scene);
void SceneExplorer(entt::entity& selected, Scene& scene);
void Viewport(Framebuffer& framebuffer);
void GamePort(Framebuffer& framebuffer);
void Settings();
void Console();
void AssetsFinder();

View File

@ -1,309 +1,17 @@
#include <imgui.h> #include "EditorLayer.h"
#include <backends/imgui_impl_opengl3.h> #include "EntryPoint.h"
#include <backends/imgui_impl_glfw.h> #include <stack>
#include <ImGuizmo.h>
#include <nfd.h> using namespace YoggieEngine;
#include <glm/glm.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include "UI/Widgets.h"
#include "Project/Project.h"
#include "SceneSerializer.h"
#include "EditorContext.h"
#include "SceneRuntime.h"
#include "AssetManagement/AssetManager.h"
const unsigned int MS_PER_UPDATE = 2;
class Editor : public Application { class Editor : public Application {
public: public:
Editor() : Application("Editor") {} Editor() : Application("Editor") {}
void Run() override
{
BarinkWindow mainWindow = BarinkWindow(1200, 700);
InputSystem = new InputManager();
renderer = new Renderer();
InputSystem->attach(&mainWindow);
InitImGui(mainWindow);
activeRuntime.Start();
double previous = glfwGetTime();
double lag = 0.0;
AssetManager::Init();
renderer->Prepare(activeRuntime.MainScene);
while (!mainWindow.WindowShouldClose())
{
double current = glfwGetTime();
double elapsed = current - previous;
previous = current;
lag += elapsed;
InputSystem->PollEvents();
while (lag >= MS_PER_UPDATE)
{
activeRuntime.Update();
lag -= MS_PER_UPDATE;
}
renderer->Render(activeRuntime.framebuffer, activeRuntime.MainScene);
ImGuiBegin();
RenderGUI();
ImGuiEnd();
mainWindow.SwapBuffers();
glClear(GL_COLOR_BUFFER_BIT| GL_DEPTH_BUFFER_BIT);
}
activeRuntime.Stop();
delete InputSystem;
delete renderer;
ImGui_ImplOpenGL3_Shutdown();
ImGui_ImplGlfw_Shutdown();
ImGui::DestroyContext();
}
void InitImGui(BarinkWindow& window )
{
IMGUI_CHECKVERSION();
ImGui::CreateContext();
ImGuiIO& io = ImGui::GetIO();
io.ConfigFlags |= ImGuiConfigFlags_::ImGuiConfigFlags_ViewportsEnable;
io.ConfigFlags |= ImGuiConfigFlags_::ImGuiConfigFlags_DockingEnable;
io.Fonts->AddFontFromFileTTF("build/Debug/Fonts/Roboto-Regular.ttf", 18);
ImGui::StyleColorsDark();
ImGui_ImplGlfw_InitForOpenGL(window.windowptr(), true);
ImGui_ImplOpenGL3_Init("#version 440");
}
void ImGuiBegin() {
ImGui_ImplGlfw_NewFrame();
ImGui_ImplOpenGL3_NewFrame();
ImGui::NewFrame();
ImGuizmo::SetOrthographic(true);
ImGuizmo::BeginFrame();
}
void ImGuiEnd() {
ImGui::EndFrame();
ImGui::Render();
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
if (ImGui::GetIO().ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
{
GLFWwindow* last_context = glfwGetCurrentContext();
ImGui::UpdatePlatformWindows();
ImGui::RenderPlatformWindowsDefault();
glfwMakeContextCurrent(last_context);
}
}
void RenderGUI() {
ImGui::DockSpaceOverViewport(ImGui::GetMainViewport());
// Show a menu bar
ImGui::BeginMainMenuBar();
if (ImGui::BeginMenu("Application")) {
if (ImGui::MenuItem("Load Project"))
{
nfdresult_t result = NFD_OpenDialog({ "yproj" }, NULL, &path);
switch (result) {
case(NFD_OKAY):
Project::LoadProject(path, activeRuntime.CurrentProject);
AssetManager::setAssetPath(activeRuntime.CurrentProject.get()->GetProjectDirectory());
AssetManager::BuildAssetView();
break;
case(NFD_CANCEL):
break;
case(NFD_ERROR):
std::cout << "NFD_Error: " << NFD_GetError() << std::endl;
break;
}
}
if (ImGui::MenuItem("Save project as...")) {
nfdresult_t result = NFD_SaveDialog({ "yproj" }, NULL, &savePath);
switch (result) {
case(NFD_OKAY):
std::cout << "Save as: " << savePath << std::endl;
Project::SaveProject(savePath, *activeRuntime.CurrentProject.get());
break;
case(NFD_CANCEL):
break;
case(NFD_ERROR):
std::cout << "NFD_Error: " << NFD_GetError() << std::endl;
break;
}
}
if (ImGui::MenuItem("Preferences"))
{
}
if (ImGui::MenuItem("Exit"))
{
// TODO: Exit application
}
ImGui::EndMenu();
}
if (ImGui::BeginMenu("Scene")) {
if (ImGui::MenuItem("Save scene"))
{
nfdresult_t result = NFD_SaveDialog({ "yscene" }, NULL, &scenePath);
switch (result) {
case(NFD_OKAY):
SaveScene(scenePath, activeRuntime.MainScene);
break;
case(NFD_CANCEL):
break;
case(NFD_ERROR):
std::cout << "NFD_Error: " << NFD_GetError() << std::endl;
break;
}
}
if (ImGui::MenuItem("Load scene"))
{
auto result = NFD_OpenDialog({ "yscene" }, NULL, &openScenePath);
switch (result) {
case (NFD_OKAY):
LoadScene(openScenePath, activeRuntime.MainScene);
break;
case(NFD_CANCEL):
break;
case(NFD_ERROR):
std::cout << "NFD_Error: " << NFD_GetError() << std::endl;
break;
}
}
if (ImGui::MenuItem("Add Entity"))
{
activeRuntime.MainScene.AddEntity("New Entity");
}
if (ImGui::MenuItem("Import Model"))
{
auto result = NFD_OpenDialog( "obj,fbx,gltf" , NULL, &modelImportPath);
switch (result) {
case(NFD_OKAY):
// Import Model
AssetManager::LoadFromSource(modelImportPath, activeRuntime.CurrentProject.get()->GetProjectDirectory() / "Assets");
break;
case(NFD_CANCEL):
break;
case(NFD_ERROR):
std::cout << "NFD_Error: " << NFD_GetError() << std::endl;
break;
}
}
if (ImGui::MenuItem("Import MeshAsset (temp)"))
{
auto result = NFD_OpenDialog("mesh", NULL, &modelImportPath);
switch (result) {
case(NFD_OKAY):
AssetManager::LoadFromAssetFile(modelImportPath);
break;
case(NFD_CANCEL):
break;
case(NFD_ERROR):
break;
}
}
ImGui::EndMenu();
}
ImGui::EndMainMenuBar();
ImGui::Begin("ProjectInfo");
ImGui::Text("Project: %s", activeRuntime.CurrentProject.get()->GetName().c_str());
ImGui::Text("Directory: %s", activeRuntime.CurrentProject.get()->GetProjectDirectory().u8string().c_str());
ImGui::End();
//ShowStats();
Viewport(*activeRuntime.framebuffer);
GamePort(*activeRuntime.framebuffer);
SceneExplorer(activeRuntime.Selected, activeRuntime.MainScene);
Inspector(activeRuntime.Selected, activeRuntime.MainScene);
Settings();
AssetsFinder();
Console();
ImGui::ShowDemoWindow();
ImGui::ShowMetricsWindow();
}
private:
EditorContext context;
EditorRuntime activeRuntime ;
char* path = nullptr;
char* savePath = nullptr;
char* scenePath = nullptr;
char* openScenePath = nullptr;
char* modelImportPath = nullptr;
void Run() override {
PushLayer(new EditorLayer());
Application::Run();
}
}; };
int main (int argc , char* argv[]) { YoggieEngine::Application *CreateApplication() { return new Editor(); }
Editor().Run();
}

View File

@ -1,26 +0,0 @@
# Yoggie Engine features
## Features
**NOTE** __Not in any particular order__
- Rendering
- OpenGL
- Vulkan
- Logging
- Different for debug and release
- Different per OS
- Physics
- PhysX
- Alternative for non-nvidia stuff?!
- Basic Entity Component system
- Graphical scripting ??
- Scripting support ( idk what language)
- LUA
- Configuration options
- JSON
- LUA
- YAML

View File

@ -1,18 +0,0 @@
project "ImGui"
kind "StaticLib"
includedirs {
"../libs/glfw/include",
"../libs/ImGui"
}
files {
"../libs/ImGui/*.cpp",
"../libs/ImGui/backends/imgui_impl_glfw.cpp",
"../libs/ImGui/backends/imgui_impl_Opengl3.cpp",
}
libdirs{
"../libs/ImGui",
"../libs/glad"
}

View File

@ -1,19 +0,0 @@
project "ImGuizmo"
kind "StaticLib"
includedirs {
"../libs/glfw/include",
"../libs/ImGui",
"../libs/guizmo"
}
files {
"../libs/guizmo/*.cpp",
}
libdirs{
"../libs/ImGui",
"../libs/glad"
}
include("../ImGui")

View File

@ -1,38 +1,34 @@
# Yoggie Engine # Yoggie Engine
<img src="Screenshots/Yoggie.webp" width="400" ></img> <img src="Screenshots/Yoggie.webp" width="160" ></img>
## Goal
Must support building a full game in 48 hours.
The goal is to build a mature enough engine to be capable of using during game jams.
## Screenshots ## Features
*_NOTE:_ Just because it is listed as a feature here does not imply it has been nor guarantees it ever will be implemented*
- Rendering
- OpenGL
- Vulkan
- Metal (Possibly)
- Logging
- Different for debug and release
- Physics
- PhysX
- Jolt Physics
- Entity Component system
- Graphical scripting (Possibly)
- Scripting support
- LUA
- C# (for object orientated approaches to gamedev)
- Configuration options
- JSON
- YAML
- INI
<img src="Screenshots/screen1.png" width="300"></img> \ ## More docs
<img src="Screenshots/screen2.png" width="300"></img> \ [Todo list](TODO.md) \
<img src="Screenshots/YoggieEditor.png" width="300"></img> [Planning](https://git.barink.dev/Nigel/MyGameEngine/projects)\
## Planning [Development](DEVELOPMENT.md)\
see [TODO](docs/TODO.md) \ [Show case](SHOWCASE.md)
see [Features](Features.md)
_NOTE:_
The planning is moving away from markdown in favor
of gitea Projects. New planning will be visible on [this page](https://git.barink.dev/Nigel/MyGameEngine/projects).
## Requirements
#### Software
* Premake
* Git
* C++ Compiler
## Windows development workflow
User premake to generate project files for the approperiate build method.
On Windows I assume you'll build with visual studio
```bash
User:~$ premake vs2022
```
## Linux development workflow
Use premake to generate project files for the approperiate build method.
On Linux I assume you'll build with something like make.
```bash
User@Machine:~$ premake gmake2
```

View File

@ -1,39 +0,0 @@
project "Runtime"
kind "ConsoleApp"
buildmessage "Building the runtime ..."
links{
"YoggieEngine"
}
includedirs{
"./../YoggieEngine/src",
-- I'd prefer if didn't need these..
-- We'll figure that out some time later
"./../libs/lua/include",
"./../libs/spdlog/include",
"./../libs/glm",
"./../libs/GorillaAudio/include",
"./../libs/assimp/include",
"./../libs/glad/include",
"./../libs/glfw/include",
"./../libs/tinygltf",
"./../libs/glew/include",
"./../libs/glm",
"./../libs/ImGui",
"./include"
}
libdirs {
'./../YoggieEngine/build/Debug'
}
files {
"./src/*.h",
"./src/*.cpp"
}

View File

@ -1,6 +0,0 @@
#include <iostream>
int main()
{
std::cout << "Welcome to the runtime!" << std::endl;
}

17
SHOWCASE.md Normal file
View File

@ -0,0 +1,17 @@
## The engine development in pictures
__Testing OpenGl with ImGui as a concept__
<img src="Screenshots/OpenGLAndImGuiTest.png" width="300"></img>
__Working on docking with different windows using ImGui__
<img src="Screenshots/YoggieEditor_workingGuizmo.png" width="300"></img>
__A first more complete look of the engine__
<img src="Screenshots/YoggieEditorV0.2.png" width="300"></img>
__Mixing deferred and forward rendering and adding a skybox__
<img src="Screenshots/ImprovedRendering.png" width="300"></img>

View File

@ -0,0 +1,6 @@
file(GLOB SOURCE_FILES "src/*.cpp")
file(GLOB HEADER_FILES "src/*.h")
add_executable(SandboxApp ${SOURCE_FILES} ${HEADER_FILES} )
target_link_directories(SandboxApp PRIVATE "../build/YoggieEngine/Debug")
target_link_libraries(SandboxApp YoggieEngine)
target_include_directories(SandboxApp PRIVATE "../YoggieEngine/src")

View File

@ -1,40 +0,0 @@
project "SandboxApp"
kind "ConsoleApp"
buildmessage "Building SandboxApp ..."
links{
"YoggieEngine"
}
includedirs{
"./../YoggieEngine/Include",
-- I'd prefer if didn't need these..
-- We'll figure that out some time later
"./../libs/lua/include",
"./../libs/spdlog/include",
"./../libs/glm",
"./../libs/GorillaAudio/include",
"./../libs/assimp/include",
"./../libs/glad/include",
"./../libs/glfw/include",
"./../libs/tinygltf",
"./../libs/glew/include",
"./../libs/glm",
"./../libs/ImGui",
"../libs/entt/src",
}
libdirs {
'./../YoggieEngine/build/Debug'
}
files {
"./src/*.h",
"./src/*.cpp"
}

View File

@ -1,11 +1,10 @@
#pragma once #pragma once
#include "YoggieEngine.h"
#include "imgui.h" #include "imgui.h"
#include "../../YoggieEngine/src/BarinkEngine.h"
#include "../../YoggieEngine/src/Graphics/Memory/Framebuffer.h"
void CameraTool(); void CameraTool();
void ScriptingTool(char* code); void ScriptingTool(char *code);
///void transformWindow(Transform& transform, std::string PanelName); /// void transformWindow(Transform& transform, std::string PanelName);
void materialWindow(Material& material, std::string PanelName); void materialWindow(Material &material, std::string PanelName);
void SceneExplorer(const std::string& PanelName); void SceneExplorer(const std::string &PanelName);
void SceneView(Framebuffer& framebuffer); void SceneView(Framebuffer &framebuffer);

View File

@ -1,123 +1,102 @@
#include <imgui.h>
#include "GUI.h" #include "GUI.h"
#include "Util.h" #include "Util.h"
#include <entt/entt.hpp> #include <entt/entt.hpp>
#include <imgui.h>
#include "../../YoggieEngine/src/BarinkEngine.h" #include "YoggieEngine.h"
#include "../../YoggieEngine/src/Scene/Components.h"
#include "../../YoggieEngine/src/Scene/Scene.h"
#include "../../YoggieEngine/src/Scene/Entity.h"
#include "../../YoggieEngine/src/AssetManager/ModelImporter.h"
#include "../../YoggieEngine/src/PerfCounter.h"
/* /*
* Define globals * Define globals
*/ */
Scene scene; Scene scene;
BarinkEngine::Renderable* renderable; BarinkEngine::Renderable *renderable;
BarinkEngine::SceneObject* object; BarinkEngine::SceneObject *object;
Entity cube; Entity cube;
/* /*
* Runs once at startup * Runs once at startup
* - USe to initialize the game/sandbox/demo * - USe to initialize the game/sandbox/demo
*/ */
void Start() { void Start() {
auto importer = BarinkEngine::ModelImporter(); auto importer = BarinkEngine::ModelImporter();
// Load in asset(S) // Load in asset(S)
object = importer.Import("build/Debug/Models/Cube.obj"); object = importer.Import("build/Debug/Models/Cube.obj");
renderable = object->renderable; renderable = object->renderable;
// Add Entities to the scene
cube = scene.AddEntity("cube");
auto &render3DComponent =
cube.AddComponent<BarinkEngine::Render3DComponent>();
render3DComponent.mesh = *renderable->mesh;
cube.GetComponent<BarinkEngine::TransformComponent>().transform =
glm::rotate(glm::mat4(1.0f), 32.0f, glm::vec3(0.5f, 1.0f, 0.0f));
// Add Entities to the scene // Create a second cube
cube = scene.AddEntity("cube");
auto& render3DComponent = cube.AddComponent<BarinkEngine::Render3DComponent>();
render3DComponent.mesh = *renderable->mesh;
cube.GetComponent<BarinkEngine::TransformComponent>()
.transform = glm::rotate(glm::mat4(1.0f), 32.0f, glm::vec3(0.5f,1.0f,0.0f));
auto cube2 = scene.AddEntity("Cube2");
auto &cube2Render = cube2.AddComponent<BarinkEngine::Render3DComponent>();
cube2Render.mesh = *renderable->mesh;
cube2Render.color = glm::vec3(0.0f, 1.0f, 0.0f);
auto &cube2Trans = cube2.GetComponent<BarinkEngine::TransformComponent>();
cube2Trans.transform =
glm::translate(glm::mat4(1.0f), glm::vec3(1.0f, 0.0f, 5.0f));
// Create a second cube // Create a light
auto AmbientLight = scene.AddEntity("AmbientLight");
auto cube2 = scene.AddEntity("Cube2"); AmbientLight.AddComponent<BarinkEngine::LightComponent>();
auto& cube2Render = cube2.AddComponent<BarinkEngine::Render3DComponent>();
cube2Render.mesh = *renderable->mesh;
cube2Render.color = glm::vec3(0.0f, 1.0f, 0.0f);
auto& cube2Trans = cube2.GetComponent<BarinkEngine::TransformComponent>();
cube2Trans.transform = glm::translate( glm::mat4(1.0f), glm::vec3(1.0f,0.0f, 5.0f));
// Create a light
auto AmbientLight = scene.AddEntity("AmbientLight");
AmbientLight.AddComponent<BarinkEngine::LightComponent>();
renderer.Prepare(scene);
}
/*
* Runs every frame
* - Use to draw Immediate mode graphics (Not meant for HUD's )
*/
void ImmediateGraphicsDraw()
{
// Show internal BarinkEngine stats
EngineInstrumentation::ShowStats();
ImGui::Begin("Scene view");
auto group = scene.getReg().view<BarinkEngine::IdentifierComponent>();
group.each([](auto entity, BarinkEngine::IdentifierComponent& identifier) {
ImGui::Text("%s", identifier.name.c_str());
});
ImGui::End();
ImGui::ShowMetricsWindow();
ImGui::Begin("Settings");
auto& a = cube.GetComponent<BarinkEngine::Render3DComponent>();
auto& b = cube.GetComponent<BarinkEngine::TransformComponent>();
ImGui::DragFloat3("Color", &a.color[0], 0.01f, 0.0f, 1.0f);
ImGui::DragFloat3("Position", &b.transform[3][0], 0.01f, 0.0f, 16.0f);
auto l = scene.getReg().view<BarinkEngine::LightComponent>();
l.each([](auto entity, BarinkEngine::LightComponent& light) {
ImGui::Text("Lighting");
ImGui::SliderFloat("Intensity", &light.Strength, 0.0f, 1.0f);
ImGui::SliderFloat3("l-Color", &light.Color[0], 0.0f, 1.0f);
});
ImGui::End();
renderer.Prepare(scene);
} }
/* /*
* Runs every frame * Runs every frame
* - Meant for game logic ( non-physics related) * - Use to draw Immediate mode graphics (Not meant for HUD's )
*/ */
void Update() void ImmediateGraphicsDraw() {
{ // Show internal BarinkEngine stats
} EngineInstrumentation::ShowStats();
void Render() ImGui::Begin("Scene view");
{ auto group = scene.getReg().view<BarinkEngine::IdentifierComponent>();
renderer.Render(scene); group.each([](auto entity, BarinkEngine::IdentifierComponent &identifier) {
ImGui::Text("%s", identifier.name.c_str());
});
ImGui::End();
ImGui::ShowMetricsWindow();
ImGui::Begin("Settings");
auto &a = cube.GetComponent<BarinkEngine::Render3DComponent>();
auto &b = cube.GetComponent<BarinkEngine::TransformComponent>();
ImGui::DragFloat3("Color", &a.color[0], 0.01f, 0.0f, 1.0f);
ImGui::DragFloat3("Position", &b.transform[3][0], 0.01f, 0.0f, 16.0f);
auto l = scene.getReg().view<BarinkEngine::LightComponent>();
l.each([](auto entity, BarinkEngine::LightComponent &light) {
ImGui::Text("Lighting");
ImGui::SliderFloat("Intensity", &light.Strength, 0.0f, 1.0f);
ImGui::SliderFloat3("l-Color", &light.Color[0], 0.0f, 1.0f);
});
ImGui::End();
} }
/* /*
* Runs at the end of the program * Runs every frame
* - Meant for cleanup * - Meant for game logic ( non-physics related)
*/ */
void Stop() void Update() {}
{
} void Render() { renderer.Render(scene); }
/*
* Runs at the end of the program
* - Meant for cleanup
*/
void Stop() {}

View File

@ -1,6 +1,6 @@
#pragma once #pragma once
#include "../../YoggieEngine/src/BarinkEngine.h" #include "YoggieEngine.h"
//void PrintSceneTree(Node& node, int depth); // void PrintSceneTree(Node& node, int depth);
//glm::mat4 CalculateModelMat(Transform& transform); // glm::mat4 CalculateModelMat(Transform& transform);

BIN
Screenshots/ImprovedRendering.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
Screenshots/YoggieEditor.png (Stored with Git LFS)

Binary file not shown.

BIN
Screenshots/YoggieEditorV0.2.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
Screenshots/YoggieEditor_workingGuizmo.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
Screenshots/screen2.png (Stored with Git LFS)

Binary file not shown.

37
TODO.md
View File

@ -1,24 +1,23 @@
# Project Planning # Project Planning
**NOTE:** __Fairly detailed planning__ <input type="checkbox" checked> Setup build system</input>\
<input type="checkbox" checked>Link with GLFW</input>\
<input type="checkbox" checked>Link GLEW or GLAD</input>\
<input type="checkbox" checked></input> Setup build system \ <input type="checkbox" checked>Basic Window</input>\
<input type="checkbox" checked></input> Link with GLFW \ <input type="checkbox" checked>Work on basic logging</input>\
<input type="checkbox" checked></input> Basic Window \ <input type="checkbox" checked>Running LUA</input>\
<input type="checkbox" checked></input> Basic Triangle rendering \ <input type="checkbox" checked>Basic triangle rendering</input>\
<input type="checkbox" checked></input> Basic IMGui \ <input type="checkbox" checked>Load model files</input>\
<input type="checkbox"></input> Basic Textures \ <input type="checkbox" checked>Basic ImGui </input>\
<input type="checkbox" checked></input> Link GLEW or GLAD \ <input type="checkbox" checked>Skybox support</input>\
<input type="checkbox" checked></input> Work on basic logging \ <input type="checkbox">Basic Textures <i>(Soon)</i></input>\
<input type="checkbox" checked></input> Input handling \ <input type="checkbox">More shader work <i>(Hopefully coming in January)</i></input> \
<input type="checkbox"></input> More shader work \ <input type="checkbox">Input handling <i>(Soon)</i></input>\
<input type="checkbox" checked></input> Load FBX model files \ <input type="checkbox">Basic Physics <i>(Almost implemented)</i></input>\
<input type="checkbox"></input> Basic Physics \ <input type="checkbox">Lua Scripting <i>(Soon)</i> </input>\
<input type="checkbox" checked> Running LUA \ <input type="checkbox">Basic Sound system</input>
<input type="checkbox"> Lua Scripting \ ### What's next?
<input type="checkbox"></input> To far in the future I am not sure what's going to be added next
## Resources ## Resources
https://renderdoc.org/ \ https://renderdoc.org/ \

View File

@ -0,0 +1,22 @@
file(GLOB SOURCE_FILES src/*.cpp)
add_library(YoggieEngine ${SOURCE_FILES} )
#target_precompile_headers(YoggieEngine PUBLIC src/YoggieEngine.h )
target_link_directories(YoggieEngine PUBLIC
"../libs/physx/physx/bin/win.x86_64.vc142.md/debug"
)
target_link_libraries(YoggieEngine
thirdparty_tools
PhysX_64
PhysXCooking_64
PhysXCommon_64
PhysXFoundation_64
PhysXPvdSDK_static_64
PhysXExtensions_static_64
)
target_include_directories(YoggieEngine PUBLIC
"../libs/physx/pxshared/include"
"../libs/physx/physx/include"
)

View File

@ -1,73 +0,0 @@
project "YoggieEngine"
kind "StaticLib"
pchheader "YoggieEngine.h"
pchsource "src/YoggieEngine.cpp"
buildmessage "Building Yoggie Engine"
disablewarnings{
"4099" -- Ignore the missing debug signals for GLFW warning
}
includedirs {
"./src",
"../libs/spdlog/include",
"../libs/glm",
"../libs/glfw/include",
"../libs/glew/include",
"../libs/glad/include",
"../libs/assimp/include",
"../libs/entt/src",
"../libs/physx/physx/include",
"../libs/lua/include",
"../libs/GorillaAudio/include",
"../libs/steam-audio/include",
"../libs/ImGui",
}
links {
-- This needs to fall under the filter as the names can differ on different platforms
"phonon",
"lua54",
"spdlog",
"assimp-vc143-mtd",
"glfw3",
"ImGui",
}
libdirs {
"../libs/steam-audio/lib/windows-x64",
"../libs/lua",
"../libs/spdlog/build/Release",
"../libs/assimp/lib/Debug",
"../libs/glfw/build/src/Debug",
}
files {
"./src/**.cpp",
"./src/**.h"
}
prebuildcommands
{
ok,err = os.copyfile("YoggieEngine/src/Graphics/shaders/*" ,"SandboxApp/build/Debug/")
}
postbuildcommands
{
ok,err = os.copyfile("YoggieEngine/build/Debug/intermediates/YoggieEngine.pch", "YoggieEngine/build/Debug/YoggieEngine.pch")
}

View File

@ -1,17 +1,161 @@
#include <YoggieEngine.h> #include <YoggieEngine.h>
#include "Application.h" #include "Application.h"
#include <imgui.h>
#include <backends/imgui_impl_opengl3.h>
#include <backends/imgui_impl_glfw.h>
#include "../../libs/guizmo/ImGuizmo.h"
#include "../../Editor/src/IconsMaterialDesign.h"
namespace YoggieEngine { namespace YoggieEngine {
Application::Application(const std::string& name )
Application::Application(const std::string& name)
: m_AppName(name) : m_AppName(name)
{ {
appWindow = CreateNativeWindow(1200, 700, m_AppName.c_str());
// Initialize engine should possibly happen here
EngineInstrumentation::PerfomanceSamplerInit(); EngineInstrumentation::PerfomanceSamplerInit();
// Initilize ImGui for this application
IMGUI_CHECKVERSION();
ImGui::CreateContext();
ImGuiIO& io = ImGui::GetIO();
io.ConfigFlags |= ImGuiConfigFlags_::ImGuiConfigFlags_ViewportsEnable;
io.ConfigFlags |= ImGuiConfigFlags_::ImGuiConfigFlags_DockingEnable;
io.Fonts->AddFontFromFileTTF("build/Debug/Fonts/Roboto-Regular.ttf", 18);
ImFontConfig config;
config.MergeMode = true;
config.GlyphMinAdvanceX = 18.0f;
static const ImWchar icon_ranges[] = { ICON_MIN_MD , ICON_MAX_MD, 0 };
io.Fonts->AddFontFromFileTTF("build/Debug/Fonts/MaterialIcons-Regular.ttf", 24, &config, icon_ranges);
ImGui::StyleColorsDark();
/*
ImGuiStyle* style = &ImGui::GetStyle();
ImVec4* colors = style->Colors;
colors[ImGuiCol_TitleBg] = ImVec4(0.72f, 0.24f, 0.87f, 1.00f);
colors[ImGuiCol_MenuBarBg] = ImVec4(0.72f, 0.24f, 0.87f, 1.00f);
colors[ImGuiCol_Tab] = ImVec4(0.53f, 0.09f, 0.67f, 1.00f);
*/
ImGui_ImplGlfw_InitForOpenGL((GLFWwindow*)appWindow->GetHandle(), true);
ImGui_ImplOpenGL3_Init("#version 450");
ImGuizmo::SetImGuiContext(ImGui::GetCurrentContext());
//ImGuizmo::SetOrthographic(true);
//init_inputSystem(appWindow);
glfwSetWindowUserPointer((GLFWwindow*)this->appWindow->GetHandle(), this);
glfwSetKeyCallback((GLFWwindow*)this->appWindow->GetHandle(), HandleKey);
} }
void Application::HandleKey(GLFWwindow* window, int key, int scancode, int action, int mods) {
auto app = (Application*)glfwGetWindowUserPointer(window);
for (auto i = app->AppLayerstack.begin(); i < app->AppLayerstack.end(); i++) {
if ((*i)->OnKey(key, action)) {
break;
}
}
}
void Application::Run() { void Application::Run() {
std::cout << "No run function implemented!";
for (auto i = AppLayerstack.begin(); i < AppLayerstack.end(); i++) {
(*i)->OnStartup();
}
double previous = glfwGetTime();
double lag = 0.0;
while (!appWindow->WindowShouldClose()) {
PollEvents();
double now = glfwGetTime();
double elapsed = now - previous;
previous = now;
lag += elapsed;
for (auto i = AppLayerstack.begin(); i < AppLayerstack.end(); i++) {
(*i)->OnUpdate();
}
GuiBegin();
for (auto i = AppLayerstack.begin(); i < AppLayerstack.end(); i++) {
(*i)->OnUI();
}
GuiEnd();
SwapBuffers();
}
for (auto i = AppLayerstack.begin(); i < AppLayerstack.end(); i++) {
(*i)->OnDestroy();
}
} }
} void Application::PollEvents() {
appWindow->Poll();
}
void Application::SwapBuffers()
{
appWindow->SwapBuffers();
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}
void Application::GuiBegin() {
ImGui_ImplGlfw_NewFrame();
ImGui_ImplOpenGL3_NewFrame();
ImGui::NewFrame();
ImGuizmo::BeginFrame();
ImGui::DockSpaceOverViewport(ImGui::GetMainViewport());
}
void Application::GuiEnd() {
ImGui::EndFrame();
ImGui::Render();
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
if (ImGui::GetIO().ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
{
GLFWwindow* last_context = glfwGetCurrentContext();
ImGui::UpdatePlatformWindows();
ImGui::RenderPlatformWindowsDefault();
glfwMakeContextCurrent(last_context);
}
}
void Application::PushLayer(Layer* layer)
{
AppLayerstack.PushLayer(layer);
layer->OnAttach();
}
Application::~Application() {
ImGui_ImplOpenGL3_Shutdown();
ImGui_ImplGlfw_Shutdown();
ImGui::DestroyContext();
delete appWindow;
}
}

View File

@ -1,33 +1,38 @@
#pragma once #pragma once
#include "YoggieEngine.h" #include "YoggieEngine.h"
#include "LayerStack.h"
namespace YoggieEngine { namespace YoggieEngine {
// forward declaration
class InputManager;
class Application { class Application {
public: public:
Application(const std::string& name); Application(const std::string& name);
~Application();
virtual void Run(); virtual void Run();
void PollEvents();
void SwapBuffers();
void GuiBegin();
void GuiEnd();
void PushLayer(Layer* layer);
static Application& Get() { return *Application::instance; }
static void HandleKey(GLFWwindow* window, int key, int scancode, int action, int mods);
static void HandleMouseButton(GLFWwindow* window, int button, int action, int mods);
static void HandleScroll(GLFWwindow* window, double xoffset, double yoffset);
protected: protected:
std::string m_AppName; std::string m_AppName;
Renderer* renderer = nullptr; NativeWindow* appWindow;
InputManager* InputSystem = nullptr;
friend class ApplicationRuntime; LayerStack AppLayerstack;
}; Layer* guiLayer;
static Application* instance ;
friend class ImGuiLayer;
class ApplicationRuntime {
public:
virtual void Start() = 0;
virtual void Update() = 0;
virtual void FixedUpdate() = 0;
virtual void Stop() = 0;
}; };
}; };

View File

@ -1,102 +0,0 @@
#include <YoggieEngine.h>
#include "ModelImporter.h"
namespace YoggieEngine {
SceneObject* ModelImporter::Import(const std::string path)
{
SceneObject* root = new SceneObject(std::string(path), nullptr);
Assimp::Importer importer;
const aiScene* scene = importer.ReadFile(path, aiProcess_Triangulate | aiProcess_FlipUVs);
aiNode* currentNode = scene->mRootNode;
std::vector<Mesh> meshes = processNode(currentNode, scene);
std::cout << "[DEBUG]: Loaded " << meshes.size() << " meshes!" << std::endl;
// create a renderable (per mesh ?? )
root->renderable = new Renderable();
root->renderable->mesh = new Mesh(meshes[0]);
return root;
}
std::vector<Mesh> ModelImporter::processNode(aiNode* node, const aiScene* scene)
{
std::vector<Mesh> meshes;
for (unsigned int i = 0; i < node->mNumMeshes; i++) {
aiMesh* mesh = scene->mMeshes[node->mMeshes[i]];
meshes.push_back(processMesh(mesh, scene));
}
for (unsigned int i = 0; i < node->mNumChildren; i++) {
auto m2 = processNode(node->mChildren[i], scene);
for (auto m : m2) {
meshes.push_back(m);
}
}
return meshes;
}
Mesh ModelImporter::processMesh(aiMesh* mesh, const aiScene* scene) {
std::vector<unsigned int> indices;
std::vector<Vertex> vertices;
ProcessVertices(mesh, vertices);
ProcessIndices(mesh, indices);
Mesh result;
result.vertices = vertices;
result.elements = indices;
return result;
}
void ProcessVertices(aiMesh* mesh, std::vector<Vertex>& out_vertices) {
// Process vertices
for (unsigned int i = 0; i < mesh->mNumVertices; i++) {
Vertex v{};
glm::vec3 vector;
vector.x = mesh->mVertices[i].x;
vector.y = mesh->mVertices[i].y;
vector.z = mesh->mVertices[i].z;
v.vertices = vector;
if (mesh->mTextureCoords[0]) {
glm::vec2 texCoord;
texCoord.x = mesh->mTextureCoords[0][i].x;
texCoord.y = mesh->mTextureCoords[0][i].y;
v.uv = texCoord;
}
out_vertices.push_back(v);
}
}
void ProcessIndices(aiMesh* mesh, std::vector<unsigned int>& out_indices) {
// Process Indices
for (unsigned int i = 0; i < mesh->mNumFaces; i++) {
aiFace face = mesh->mFaces[i];
if (face.mNumIndices < 3)
continue;
for (unsigned int j = 0; j < face.mNumIndices; j++) {
out_indices.push_back(face.mIndices[j]);
}
}
}
}

View File

@ -1,31 +0,0 @@
#pragma once
#define STB_IMAGE_IMPLEMENTATION
#define STB_IMAGE_WRITE_IMPLEMENTATION
#include "../Graphics/Primitives/Mesh.h"
#include <assimp/Importer.hpp>
#include <assimp/scene.h>
#include <assimp/postprocess.h>
#include <string>
#include "../Scene/TransformTree/SceneNodeTypes.h"
namespace YoggieEngine {
void ProcessVertices(aiMesh* mesh, std::vector<Vertex>& out_vertices);
void ProcessIndices(aiMesh* mesh, std::vector<unsigned int>& out_indices);
class ModelImporter {
public:
SceneObject* Import(const std::string path);
private:
static Mesh ModelImporter::processMesh(aiMesh* mesh, const aiScene* scene);
static std::vector<Mesh> ModelImporter::processNode(aiNode* node, const aiScene* scene);
};
}

View File

@ -0,0 +1,22 @@
#pragma once
#include "uuid.h"
typedef uuid::v4::UUID AssetHandle;
enum class AssetType {
Unknown = -1,
Mesh,
Texture,
Material,
Shader
};
struct Asset {
AssetHandle Handle;
template<class T >
static AssetType GetType(T t) { return t.GetType(); }
virtual AssetType GetType() { return AssetType::Unknown; }
};

View File

@ -0,0 +1,143 @@
#include <YoggieEngine.h>
#include "AssetImporter.h"
#include <assimp/Importer.hpp>
#include <assimp/postprocess.h>
#include <assimp/scene.h>
namespace YoggieEngine {
void ProcessVertices(aiMesh* mesh, std::vector<YoggieEngine::Vertex>& out_vertices) {
for (unsigned int i = 0; i < mesh->mNumVertices; i++) {
YoggieEngine::Vertex v{};
glm::vec3 vector{};
vector.x = mesh->mVertices[i].x;
vector.y = mesh->mVertices[i].y;
vector.z = mesh->mVertices[i].z;
v.vertices = vector;
if (mesh->mTextureCoords[0]) {
glm::vec2 texCoord{};
texCoord.x = mesh->mTextureCoords[0][i].x;
texCoord.y = mesh->mTextureCoords[0][i].y;
v.uv = texCoord;
}
out_vertices.push_back(v);
}
}
void ProcessIndices(aiMesh* mesh, std::vector<unsigned int>& out_indices) {
for (unsigned int i = 0; i < mesh->mNumFaces; i++) {
aiFace face = mesh->mFaces[i];
if (face.mNumIndices < 3)
continue;
for (unsigned int j = 0; j < face.mNumIndices; j++) {
out_indices.push_back(face.mIndices[j]);
}
}
}
YoggieEngine::Mesh processMesh(aiMesh* mesh, const aiScene* scene) {
std::vector<unsigned int> indices;
std::vector<YoggieEngine::Vertex> vertices;
ProcessVertices(mesh, vertices);
ProcessIndices(mesh, indices);
YoggieEngine::Mesh result;
result.vertices = vertices;
result.elements = indices;
return result;
}
std::vector<YoggieEngine::Mesh> processNode(aiNode* node, const aiScene* scene) {
std::vector<YoggieEngine::Mesh> meshes = std::vector<YoggieEngine::Mesh>();
for (unsigned int i = 0; i < node->mNumMeshes; i++) {
aiMesh* mesh = scene->mMeshes[node->mMeshes[i]];
meshes.push_back(processMesh(mesh, scene));
}
for (unsigned int i = 0; i < node->mNumChildren; i++) {
auto m2 = processNode(node->mChildren[i], scene);
for (auto m : m2) {
meshes.push_back(m);
}
}
return meshes;
}
void LoadModelFile(std::filesystem::path path) {
Assimp::Importer importer;
const aiScene* scene = importer.ReadFile(path.string(), aiProcess_Triangulate | aiProcess_FlipUVs);
aiNode* currentNode = scene->mRootNode;
auto meshes = processNode(currentNode, scene);
}
bool IsSupportedImageFormat(const std::string& extension) {
static std::vector<std::string> supported_image_extensions = { "jpeg", "jpg", "png","bmp","hdr","psd","tga","gif","pic","psd","pgm","ppm" };
for (auto support_extension : supported_image_extensions) {
if (extension == support_extension)
return true;
}
return false;
}
Asset AssetImporter::ImportAsset(AssetMetadata& metadata) {
static Asset emptyAsset;
// Check file extension so we can choose our loader
if (metadata.filepath.has_extension() == true)
{
spdlog::error("Asset file has no extension!");
}
const auto extension = metadata.filepath.extension().string();
// Handle as Model file
bool IsSupportedModelFile = importer.IsExtensionSupported(extension);
if (IsSupportedModelFile) {
LoadModelFile(metadata.filepath);
return emptyAsset;
}
// Handle as Texture
if (IsSupportedImageFormat(extension))
{
Texture texture;
texture.Load(metadata.filepath.string());
return texture;
}
// Handle as shader
if (extension == "glsl" || extension == "vert" || extension == "frag") {
//Shader shader;
//shader.
return emptyAsset;
}
return emptyAsset;
}
};

View File

@ -0,0 +1,12 @@
#pragma once
#include "AssetMetadata.h"
#include <assimp/Importer.hpp>
namespace YoggieEngine{
class AssetImporter {
public:
static Asset ImportAsset(AssetMetadata& metadata);
private:
static Assimp::Importer importer;
};
}

View File

@ -0,0 +1,16 @@
#pragma once
#include <map>
#include "AssetMetaData.h"
typedef std::map<AssetHandle, AssetMetadata> AssetRegistry;
class AssetManager {
public:
virtual Asset& GetAsset(AssetHandle handle) = 0;
protected:
AssetRegistry Assets;
std::map<AssetHandle, Asset> LoadedAssets;
};

View File

@ -0,0 +1,41 @@
#include "YoggieEngine.h"
#include "AssetManagerEditor.h"
#include "AssetImporter.h"
using namespace YoggieEngine;
Asset& AssetManagerEditor::GetAsset(AssetHandle handle)
{
static Asset EmptyAsset{};
// 1. Check if handle is valid
if (IsAssetHandleValid(handle) == false)
return EmptyAsset;
// 2. check if asset needs loading
Asset asset;
if (IsAssetLoaded(handle)) {
asset = LoadedAssets.at(handle);
}
else {
// Load asset
// Get MetaData
//auto& metadata = Assets[handle];
// Load Asset
//asset = AssetImporter::ImportAsset(metadata);
}
// 3. return asset.
return asset;
}
bool AssetManagerEditor::IsAssetHandleValid(AssetHandle handle)
{
return Assets.find(handle) != Assets.end();
}
bool AssetManagerEditor::IsAssetLoaded(AssetHandle handle ) {
return LoadedAssets.find(handle) != LoadedAssets.end();
}

View File

@ -0,0 +1,11 @@
#pragma once
#include "AssetManager.h"
class AssetManagerEditor : public AssetManager {
public:
Asset& GetAsset(AssetHandle handle) override;
private:
bool IsAssetHandleValid(AssetHandle handle);
bool IsAssetLoaded(AssetHandle handle);
};

View File

@ -0,0 +1,7 @@
#pragma once
#include <filesystem>
#include "Asset.h"
struct AssetMetadata{
AssetHandle handle;
std::filesystem::path filepath;
};

View File

@ -0,0 +1,72 @@
/*
*
* SOURCE: https://github.com/rkg82/uuid-v4/blob/main/uuid/v4/uuid.h
*
*/
#ifndef __UUID__
#define __UUID__
#include <random>
#include <string>
namespace uuid::v4
{
// Encaasulate the genaeration of a Version 4 UUID object
// A Version 4 UUID is a universally unique identifier that is generated using random numbers.
class UUID
{
public:
UUID() {}
// I need a better UUID class that will work as a key in std::map
// because this won't properly work
bool operator() (const UUID& lhs, const UUID& rhs) const {
return 1==1;
}
bool operator< (const UUID& rhs)const {
return false;
}
// method for creating UUID object.
void generate ()
{
std::random_device rd;
std::mt19937 engine{ rd() };
std::uniform_int_distribution<int> dist{ 0, 256 }; //Limits of the interval
for (int index = 0; index < 16; ++index)
{
_data[index] = (unsigned char)dist(engine);
}
_data[6] = ((_data[6] & 0x0f) | 0x40); // Version 4
_data[8] = ((_data[8] & 0x3f) | 0x80); // Variant is 10
}
// Returns UUID as formatted string
std::string String()
{
// Formats to "0065e7d7-418c-4da4-b4d6-b54b6cf7466a"
char buffer[256] = { 0 };
std::snprintf(buffer, 255,
"%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
_data[0], _data[1], _data[2], _data[3],
_data[4], _data[5],
_data[6], _data[7],
_data[8], _data[9],
_data[10], _data[11], _data[12], _data[13], _data[14], _data[15]);
std::string uuid = buffer;
return uuid;
}
private:
unsigned char _data[16] = { 0 };
};
};
#endif // #ifndef __UUID__

View File

@ -0,0 +1,21 @@
#pragma once
#include "YoggieEngine.h"
extern YoggieEngine::Application* CreateApplication();
namespace YoggieEngine
{
int entryPoint()
{
Application* app = CreateApplication();
app->Run();
delete app;
return 0;
}
}
int main(int argc, char** argv)
{
return YoggieEngine::entryPoint();
}

View File

@ -1,12 +0,0 @@
#pragma once
namespace YoggieEngine {
struct Event
{
public:
std::string name;
int argc;
void** argv;
};
}

View File

@ -1,28 +0,0 @@
#include <YoggieEngine.h>
#include "EventEmitter.h"
namespace YoggieEngine {
void EventEmitter::Subscribe(EventListener& subscriber)
{
subscribers.push_back(&subscriber);
}
void EventEmitter::Unsubscribe(EventListener& subscriber)
{
subscribers.remove(&subscriber);
}
void EventEmitter::EmitEvent(Event& incident)
{
// Notify all subscribers an event has taken place
for (auto it = subscribers.begin(); it != subscribers.end(); ++it)
{
(*it)->ReceiveEvent(incident);
}
}
EventEmitter::EventEmitter() {
subscribers = std::list<EventListener*>{};
}
}

View File

@ -1,16 +0,0 @@
#pragma once
namespace YoggieEngine{
class EventEmitter {
public:
void Subscribe(EventListener& subscriber);
void Unsubscribe(EventListener& subscriber);
protected:
std::list<EventListener*> subscribers;
void EmitEvent(Event& incident);
EventEmitter();
};
}

View File

@ -1,9 +0,0 @@
#pragma once
#include "Event.h"
namespace YoggieEngine {
class EventListener {
public:
virtual void ReceiveEvent(Event& incident) = 0;
};
}

View File

@ -0,0 +1,42 @@
#pragma once
#include <glm/gtx/quaternion.hpp>
namespace YoggieEngine {
class Camera {
public:
Camera() {
projection = glm::perspective(glm::radians(90.0f), 800.0f / 600.0f, 0.001f, 1000.0f);
//projection[3][1] *= -1;
}
glm::mat4 getTransform() const {
auto transform = glm::translate(glm::mat4(1.0f), Position)
* glm::toMat4(glm::quat(Rotation))
* glm::scale(glm::mat4(1.0f), glm::vec3(1.0f));
return glm::inverse(transform);
}
glm::mat4& getProjection(float width, float height) {
//projection[3][1] *= -1;
return projection;
}
glm::vec3 Position = glm::vec3(0.0f);
glm::vec3 Rotation = glm::vec3(0.0f);
private:
glm::mat4 view;
glm::mat4 projection;
};
}

View File

@ -0,0 +1,42 @@
#include <YoggieEngine.h>
#include "CubeMap.h"
YoggieEngine::CubeMap::CubeMap()
{
}
YoggieEngine::CubeMap::CubeMap(std::vector<std::string>& texture_faces)
{
glGenTextures(1, &textureID);
glBindTexture(GL_TEXTURE_CUBE_MAP, textureID);
stbi_set_flip_vertically_on_load(false);
int width, height, nrChannels;
unsigned char* data;
for (unsigned int i = 0; i < texture_faces.size(); i++)
{
data = stbi_load(texture_faces[i].c_str(), &width, &height, &nrChannels, 0);
if (data) {
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
stbi_image_free(data);
}
else {
spdlog::debug("Loading image {} failed!", texture_faces[i]);
stbi_image_free(data);
}
}
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
stbi_set_flip_vertically_on_load(true);
}
YoggieEngine::CubeMap::~CubeMap()
{
}

View File

@ -0,0 +1,19 @@
#pragma once
namespace YoggieEngine {
class CubeMap {
public:
CubeMap();
CubeMap(std::vector<std::string>& texture_faces);
~CubeMap();
unsigned int getID() { return textureID; }
private:
unsigned int textureID;
};
};

View File

@ -0,0 +1,15 @@
#pragma once
#include "Scene/Components.h"
namespace YoggieEngine {
struct DrawCommand {
bool isDynamic;
unsigned int VAO_identifier;
unsigned int num_elements;
unsigned int IBO_identifier;
TransformComponent& transform;
glm::vec3& color;
// Material
};
};

View File

@ -0,0 +1,49 @@
#include <YoggieEngine.h>
#include "Framebuffer.h"
namespace YoggieEngine {
Framebuffer::Framebuffer(int width, int height)
{
glGenFramebuffers(1, &Id);
glBindFramebuffer(GL_FRAMEBUFFER, Id);
// Create a colour texture!
glGenTextures(1, &ColourAttachment);
glBindTexture(GL_TEXTURE_2D, ColourAttachment);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glBindTexture(GL_TEXTURE_2D, 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, ColourAttachment, 0);
// Create a depth buffer
glGenRenderbuffers(1, &DepthAttachment);
glBindRenderbuffer(GL_RENDERBUFFER, DepthAttachment);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, width, height);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, DepthAttachment);
if (!glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE)
{
std::cout << "Framebuffer is incomplete!" << std::endl;
}
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
Framebuffer::~Framebuffer()
{
glDeleteTextures(1, &ColourAttachment);
glDeleteTextures(1, &DepthAttachment);
glDeleteFramebuffers(1, &Id);
}
}

View File

@ -3,7 +3,7 @@ namespace YoggieEngine {
class Framebuffer { class Framebuffer {
public: public:
Framebuffer(); Framebuffer(int width,int height);
~Framebuffer(); ~Framebuffer();
GLuint GetId() { return Id; } GLuint GetId() { return Id; }

View File

@ -1,73 +0,0 @@
#include <YoggieEngine.h>
#include "Framebuffer.h"
namespace YoggieEngine {
Framebuffer::Framebuffer()
{
glGenFramebuffers(1, &Id);
glBindFramebuffer(GL_FRAMEBUFFER, Id);
// Create a colour texture!
glGenTextures(1, &ColourAttachment);
glBindTexture(GL_TEXTURE_2D, ColourAttachment);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 800, 600, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glBindTexture(GL_TEXTURE_2D, 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, ColourAttachment, 0);
// Create a depth buffer
glGenTextures(1, &DepthAttachment);
glBindTexture(GL_TEXTURE_2D, DepthAttachment);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8, 800, 600, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, NULL);
glBindTexture(GL_TEXTURE_2D, 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, DepthAttachment, 0);
/*
* // Render buffer
glGenRenderbuffers(1, &DepthAttachment);
glBindRenderbuffer(GL_RENDERBUFFER, DepthAttachment);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, 800, 600);
glBindRenderbuffer(GL_RENDERBUFFER, 0);
glFramebufferRenderbuffer(GL_RENDERBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, DepthAttachment);
*/
if (!glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE)
{
std::cout << "Framebuffer is incomplete!" << std::endl;
}
else {
std::cout << "Framebuffer is complete!" << std::endl;
}
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
Framebuffer::~Framebuffer()
{
glDeleteTextures(1, &ColourAttachment);
glDeleteRenderbuffers(1, &DepthAttachment);
glDeleteFramebuffers(1, &Id);
}
}

View File

@ -0,0 +1,60 @@
#include <YoggieEngine.h>
#include "OpenglAPI.h"
namespace YoggieEngine {
GLenum glCheckError_(const char* file, int line) {
GLenum errorCode;
while ((errorCode = glGetError()) != GL_NO_ERROR) {
std::string error;
switch (errorCode)
{
case GL_INVALID_ENUM: error = "INVALID_ENUM"; break;
case GL_INVALID_VALUE: error = "INVALID_VALUE"; break;
case GL_INVALID_OPERATION: error = "INVALID_OPERATION"; break;
case GL_STACK_OVERFLOW: error = "STACK_OVERFLOW"; break;
case GL_STACK_UNDERFLOW: error = "STACK_UNDERFLOW"; break;
case GL_OUT_OF_MEMORY: error = "OUT_OF_MEMORY"; break;
case GL_INVALID_FRAMEBUFFER_OPERATION: error = "INVALID_FRAMEBUFFER_OPERATION"; break;
};
spdlog::error("{0} | {1} ({2})", error, file, line);
}
return errorCode;
}
#ifdef DEBUG
#define glCheckError() glCheckError_(__FILE__, __LINE__)
#else
#define glCheckError()
#endif
void OpenGLApi::DrawTriangles(Render3DComponent rc) {
glBindVertexArray(rc.VAO);
glCheckError();
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, rc.IBO);
glCheckError();
glDrawElements(GL_TRIANGLES, static_cast<unsigned int> (rc.mesh.elements.size()), GL_UNSIGNED_INT, 0);
glCheckError();
glBindVertexArray(0);
}
void OpenGLApi::DrawCubeMap(unsigned int VertexAttributeObject, CubeMap CubeTexture) {
glDepthMask(GL_FALSE);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_CUBE_MAP, CubeTexture.getID());
//glCheckError(); // INVALID ENUM FOR SOME REASON
glBindVertexArray(VertexAttributeObject);
glDrawArrays(GL_TRIANGLES, 0, 36);
//glCheckError();
glBindVertexArray(0);
glDepthMask(GL_TRUE);
}
}

View File

@ -0,0 +1,9 @@
#pragma once
namespace YoggieEngine {
class OpenGLApi {
public:
static void DrawTriangles(Render3DComponent rc);
static void DrawCubeMap(unsigned int VertexAttributeObject, CubeMap CubeTexture);
};
};

View File

@ -1,24 +0,0 @@
#include <YoggieEngine.h>
#include "Camera.h"
namespace YoggieEngine {
Camera::Camera(glm::vec3 position, glm::vec3 rotation, float zoom)
: Position(position), Rotation(rotation), Zoom(zoom) {
Front = glm::vec3(-1.0f, 0.0f, 0.0f);
Right = glm::vec3(0.0f, 0.0f, 1.0f);
Up = glm::vec3(0.0f, 1.0f, 0.0f);
}
Camera::~Camera() {
}
glm::mat4 Camera::GetViewMatrix() {
return glm::lookAt(
Position,
Position + Front,
Up
);
}
}

View File

@ -1,21 +0,0 @@
#pragma once
namespace YoggieEngine {
class Camera {
public:
glm::vec3 Position;
glm::vec3 Rotation;
float Zoom;
Camera(glm::vec3 position, glm::vec3 rotation, float zoom);
~Camera();
glm::mat4 GetViewMatrix();
private:
glm::vec3 Front;
glm::vec3 Right;
glm::vec3 Up;
};
}

View File

@ -1,21 +0,0 @@
#pragma once
namespace YoggieEngine {
class Shader {
private:
char* readFile(const char* filePath);
public:
Shader(const std::string vertexShaderPath, const std::string fragmentShaderPath);
void Use() const;
void setUniformMat4(std::string uniformName, glm::mat4 matrix4)const;
void setUniformVec4(std::string uniformName, glm::vec4 vector4)const;
void setUniformVec3(std::string uniformName, glm::vec3 vector3)const;
void setUniformVec2(std::string uniformName, glm::vec2 vector2)const;
void setUniformFloat(std::string uniformName, float value)const;
void setUniformInt(std::string uniformName, int value) const;
int id;
};
}

View File

@ -1,13 +0,0 @@
#pragma once
namespace YoggieEngine {
class Texture {
public:
Texture(const std::string texturePath);
void Bind();
void Unbind();
const unsigned int GetID() const { return Id; }
private:
unsigned int Id;
};
}

View File

@ -2,7 +2,7 @@
#include "RenderSurface.h" #include "RenderSurface.h"
namespace YoggieEngine { namespace YoggieEngine {
RenderSurface::RenderSurface() { RenderSurface::RenderSurface() {
shader = new Shader("build/SandboxAppliction/Debug/renderSuface.vs", "build/SandboxApplication/Debug/renderSurface.fs"); shader = new Shader("build/SandboxAppliction/Debug/Shaders/forward/geometry.vert", "build/SandboxApplication/Debug/Shaders/forward/geometry.frag");
verts = std::vector<glm::vec3>{ verts = std::vector<glm::vec3>{
{-0.5f, 0.5f, 0.0f}, // 0 {-0.5f, 0.5f, 0.0f}, // 0

View File

@ -1,6 +1,6 @@
#pragma once #pragma once
#include "../Graphics/Memory/Buffer.h" #include "../Graphics/Buffer.h"
#include "../Graphics/Memory/VertexArray.h" #include "../Graphics/VertexArray.h"
namespace YoggieEngine { namespace YoggieEngine {

View File

@ -1,9 +0,0 @@
#pragma once
namespace YoggieEngine {
struct Renderable {
Mesh* mesh;
Material* material;
Texture* texture;
};
}

View File

@ -1,109 +1,341 @@
#include <YoggieEngine.h> #include <YoggieEngine.h>
#include "Renderer.h" #include "Renderer.h"
#include "../Scene/Components.h" #include "../Scene/Components.h"
#include "../Graphics/Memory/VertexArray.h" #include "../Graphics/Buffer.h"
#include "../Graphics/Memory/Buffer.h" #include "../Graphics/VertexArray.h"
#include "Framebuffer.h"
#include "../Scene/Components.h"
#include"../Scene/Scene.h"
#include "Camera.h"
#include "OpenglAPI.h"
namespace YoggieEngine { namespace YoggieEngine {
float Angle = 0.0; unsigned int quadVAO = 0;
Camera cam = Camera(glm::vec3(12.0f, 0.0f, 0.0f), glm::vec3(0.0f, 0.0f, 0.0f), 90.0f); unsigned int quadVBO = 0;
glm::mat4 projection = glm::perspective(glm::radians(cam.Zoom), (800.0f / 600.0f), 0.001f, 100.0f); // vegetation test
std::vector<glm::vec3> vegetation = {
glm::vec3(-1.5f, 0.0f, -0.48f),
glm::vec3(1.5f, 0.0f, 0.51f),
glm::vec3(0.0f, 0.0f, 0.7f),
glm::vec3(-0.3f, 0.0f, -2.3f)
};
Renderer::Renderer(){ unsigned int transparentVAO, transparentVBO;
Texture grassTexture;
float skyboxVertices[]{
// positions
-1.0f, 1.0f, -1.0f,
-1.0f, -1.0f, -1.0f,
1.0f, -1.0f, -1.0f,
1.0f, -1.0f, -1.0f,
1.0f, 1.0f, -1.0f,
-1.0f, 1.0f, -1.0f,
-1.0f, -1.0f, 1.0f,
-1.0f, -1.0f, -1.0f,
-1.0f, 1.0f, -1.0f,
-1.0f, 1.0f, -1.0f,
-1.0f, 1.0f, 1.0f,
-1.0f, -1.0f, 1.0f,
1.0f, -1.0f, -1.0f,
1.0f, -1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f, 1.0f, -1.0f,
1.0f, -1.0f, -1.0f,
-1.0f, -1.0f, 1.0f,
-1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f, -1.0f, 1.0f,
-1.0f, -1.0f, 1.0f,
-1.0f, 1.0f, -1.0f,
1.0f, 1.0f, -1.0f,
1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
-1.0f, 1.0f, 1.0f,
-1.0f, 1.0f, -1.0f,
-1.0f, -1.0f, -1.0f,
-1.0f, -1.0f, 1.0f,
1.0f, -1.0f, -1.0f,
1.0f, -1.0f, -1.0f,
-1.0f, -1.0f, 1.0f,
1.0f, -1.0f, 1.0f
};
Renderer::Renderer() :
m_framebuffer(800, 600),
gBufferShader("build/Debug/Shaders/deferred/geometry.vert", "build/Debug/Shaders/deferred/geometry.frag"),
lightingPassShader("build/Debug/Shaders/deferred/lightPass.vert", "build/Debug/Shaders/deferred/lightPass.frag"),
SkyboxShader("build/Debug/Shaders/Cubemaps/Skybox.vert", "build/Debug/Shaders/Cubemaps/Skybox.frag"),
BlendingShader("build/Debug/Shaders/forward/Blending.vert", "build/Debug/Shaders/forward/Blending.frag"),
forwardShader("build/Debug/Shaders/forward/geometry.vert", "build/Debug/Shaders/forward/geometry.frag"),
postProcessingShader("build/Debug/Shaders/forward/postprocessing.vert", "build/Debug/Shaders/forward/postprocessing.frag")
{
width = 800;
height = 600;
glEnable(GL_DEPTH_TEST); glEnable(GL_DEPTH_TEST);
CreateGBuffer();
std::vector<std::string> faces{
"build/Debug/skybox/Open_Water/right.jpg",
"build/Debug/skybox/Open_Water/left.jpg",
"build/Debug/skybox/Open_Water/top.jpg",
"build/Debug/skybox/Open_Water/bottom.jpg",
"build/Debug/skybox/Open_Water/front.jpg",
"build/Debug/skybox/Open_Water/back.jpg"
};
skybox = CubeMap(faces);
grassTexture.Load("build/Debug/Texture/grass.png");
} }
Renderer::~Renderer(){}
void Renderer::Prepare(Scene& scene ) { void Renderer::CreateGBuffer() {
auto group = scene.getReg().view<Render3DComponent>(); // Deferred Rendering
group.each([](auto enity, Render3DComponent& renderComponent) { glGenFramebuffers(1, &gBuffer);
VertexArray va = VertexArray(); glBindFramebuffer(GL_FRAMEBUFFER, gBuffer);
Buffer vertexBuffer = Buffer();
Buffer elementBuffer = Buffer();
va.Create(); // - Position Color Buffer ;
va.Bind(); glGenTextures(1, &gPosition);
glBindTexture(GL_TEXTURE_2D, gPosition);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, width, height, 0, GL_RGBA, GL_FLOAT, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, gPosition, 0);
vertexBuffer.createBuffer(); // - normal color buffer ;
vertexBuffer.Bind(false); glGenTextures(1, &gNormal);
vertexBuffer.setBufferData((void*)&renderComponent.mesh.vertices[0], renderComponent.mesh.vertices.size() * sizeof(Vertex), false); glBindTexture(GL_TEXTURE_2D, gNormal);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, width, height, 0, GL_RGBA, GL_FLOAT, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, gNormal, 0);
elementBuffer.createBuffer(); // - Color + Specular buffer ;
elementBuffer.Bind(true); glGenTextures(1, &gColorSpec);
elementBuffer.setBufferData((void*)&renderComponent.mesh.elements[0], renderComponent.mesh.elements.size() * sizeof(unsigned int), true); glBindTexture(GL_TEXTURE_2D, gColorSpec);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
va.AttachAttribute(0, 3, sizeof(Vertex)); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)0); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, GL_TEXTURE_2D, gColorSpec, 0);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
va.Unbind();
vertexBuffer.Unbind(false);
elementBuffer.Unbind(true);
renderComponent.VAO = va.getID();
renderComponent.IBO = elementBuffer.getBufferID();
});
}
unsigned int attachments[3] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1 , GL_COLOR_ATTACHMENT2 };
glDrawBuffers(3, attachments);
void Renderer::Render(Scene& scene) // Create and attach a depth buffer
{ glGenRenderbuffers(1, &gDepth);
auto group = scene.getReg().view<TransformComponent, Render3DComponent>(); glBindRenderbuffer(GL_RENDERBUFFER, gDepth);
group.each([&](auto entity , TransformComponent& trans, Render3DComponent& renderComponent) glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, width, height);
{ glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, gDepth);
glBindVertexArray(renderComponent.VAO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, renderComponent.IBO);
renderComponent.shader.Use(); if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
{
spdlog::critical("Framebuffer not complete {}{}", __FILE__, __LINE__);
}
auto lights = scene.getReg().view<LightComponent>(); glBindFramebuffer(GL_FRAMEBUFFER, 0);
lights.each([&](auto entity, LightComponent& light) {
renderComponent.shader.setUniformVec3("lighting.color", light.Color);
renderComponent.shader.setUniformFloat("lighting.strength", light.Strength);
});
glm::mat4 rotation = glm::rotate(glm::mat4(1.0f), trans.Rotation.x, glm::vec3(1.0f, 0.0f, 0.0f));
rotation *= glm::rotate(glm::mat4(1.0f), trans.Rotation.y, glm::vec3(0.0f, 1.0f, 0.0f));
rotation *= glm::rotate(glm::mat4(1.0f), trans.Rotation.z, glm::vec3(0.0f, 0.0f, 1.0f));
glm::mat4 modelMatrix = glm::translate(glm::mat4(1.0f), trans.Position) * glm::scale(glm::mat4(1.0f), trans.Scale) *rotation;
renderComponent.shader.setUniformVec3("Color", renderComponent.color);
renderComponent.shader.setUniformMat4("M", modelMatrix);
renderComponent.shader.setUniformMat4("V", cam.GetViewMatrix());
renderComponent.shader.setUniformMat4("P", projection);
//std::cout << "Draw " << renderComponent.mesh.elements.size() << " elements" << std::endl;
glDrawElements(GL_TRIANGLES, static_cast<unsigned int>(renderComponent.mesh.elements.size()) ,
GL_UNSIGNED_INT, NULL);
glBindVertexArray(0);
});
} }
void Renderer::Render(Framebuffer* framebuffer, Scene& scene)
{
if (framebuffer == nullptr)
return;
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer->GetId()); void Renderer::Render(Scene& scene , Camera MainCamera){
int oldviewport[4];
glGetIntegerv(GL_VIEWPORT, oldviewport);
glViewport(0, 0, width, height);
glBindFramebuffer(GL_FRAMEBUFFER, gBuffer);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f); glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
Render(scene); // Render skybox if the scene has one
SkyboxShader.Use();
SkyboxShader.setUniformMat4("projection", MainCamera.getProjection(width, height));
SkyboxShader.setUniformMat4("view", glm::inverse(glm::mat4(glm::mat3(MainCamera.getTransform()))));
if (!skyboxVAO) {
unsigned int VBO;
glGenVertexArrays(1, &skyboxVAO);
glGenBuffers(1, &VBO);
glBindVertexArray(skyboxVAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(skyboxVertices), &skyboxVertices, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
}
OpenGLApi::DrawCubeMap(skyboxVAO, skybox);
auto renderables = scene.getReg().view<TransformComponent, Render3DComponent>();
gBufferShader.Use();
for (auto renderable : renderables) {
auto entity = Entity(renderable, &scene);
auto& renderComponent = entity.GetComponent<Render3DComponent>();
auto& transform = entity.GetComponent<TransformComponent>();
// Geometry pass
gBufferShader.setUniformVec3("Color", renderComponent.color);
gBufferShader.setUniformMat4("Model", transform.GetTransform());
gBufferShader.setUniformMat4("View", glm::inverse(MainCamera.getTransform()));
gBufferShader.setUniformMat4("Projection", MainCamera.getProjection(width, height));
OpenGLApi::DrawTriangles(renderComponent);
}
// Light pass
glBindFramebuffer(GL_FRAMEBUFFER, m_framebuffer.GetId());
lightingPassShader.Use();
lightingPassShader.setUniformInt("gPosition", 0);
lightingPassShader.setUniformInt("gNormal", 1);
lightingPassShader.setUniformInt("gColorSpec", 2);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, gPosition);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, gNormal);
glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_2D, gColorSpec);
auto lights = scene.getReg().view<LightComponent, TransformComponent>();
unsigned int lightnr = 0;
for (auto light : lights) {
auto lightComponent = Entity(light, &scene).GetComponent<LightComponent>();
auto transformComponent = Entity(light, &scene).GetComponent<TransformComponent>();
auto name = "lights[" + std::to_string(lightnr) + "]";
lightingPassShader.setUniformVec3(name + ".Position", transformComponent.Position);
lightingPassShader.setUniformVec3(name + ".Color", lightComponent.Color);
const float linear = 0.7f;
const float quadratic = 1.8f;
lightingPassShader.setUniformFloat(name + ".Linear", linear);
lightingPassShader.setUniformFloat(name + ".Quadratic", quadratic);
lightnr++;
}
if (quadVAO == 0)
{
float quadVertices[] = {
-1.0f, 1.0f, 0.0f, 0.0f, -1.0f,
-1.0f, -1.0f, 0.0f, 0.0f, 0.0f,
1.0f, 1.0f, 0.0f, 1.0f, -1.0f,
1.0f, -1.0f, 0.0f, 1.0f, 0.0f,
};
unsigned int quadVBO;
// setup plane VAO ;
glGenVertexArrays(1, &quadVAO);
glGenBuffers(1, &quadVBO);
glBindVertexArray(quadVAO);
glBindBuffer(GL_ARRAY_BUFFER, quadVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(quadVertices), &quadVertices, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float)));
}
glBindVertexArray(quadVAO);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glBindVertexArray(0);
// Copy GBuffer
glBindFramebuffer(GL_READ_FRAMEBUFFER, gBuffer);
glBindFramebuffer(GL_DRAW_BUFFER, m_framebuffer.GetId());
glBlitFramebuffer(0, 0, width, height, 0, 0, width, height, GL_DEPTH_BUFFER_BIT, GL_NEAREST);
if (transparentVAO == 0) {
unsigned int transparentVBO;
float transparentVertices[] = {
// positions // texture Coords
0.0f, 0.5f, 0.0f, 0.0f, 1.0f,
0.0f, -0.5f, 0.0f, 0.0f, 0.0f,
1.0f, -0.5f, 0.0f, 1.0f, 0.0f,
0.0f, 0.5f, 0.0f, 0.0f, 1.0f,
1.0f, -0.5f, 0.0f, 1.0f, 0.0f,
1.0f, 0.5f, 0.0f, 1.0f, 1.0f
};
glGenVertexArrays(1, &transparentVAO);
glGenBuffers(1, &transparentVBO);
glBindVertexArray(transparentVAO);
glBindBuffer(GL_ARRAY_BUFFER, transparentVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(transparentVertices), transparentVertices, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float)));
glBindVertexArray(0);
}
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
BlendingShader.Use();
glBindVertexArray(transparentVAO);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, grassTexture.GetID());
BlendingShader.setUniformMat4("V", glm::inverse(MainCamera.getTransform()));
BlendingShader.setUniformMat4("P", MainCamera.getProjection(width, height));
for (unsigned int i = 0; i < vegetation.size(); i++) {
auto translation = glm::translate(glm::mat4(1.0f), vegetation[i]);
BlendingShader.setUniformMat4("M", translation);
glDrawArrays(GL_TRIANGLES, 0, 6);
}
glBindVertexArray(0);
glDisable(GL_BLEND);
glBindFramebuffer(GL_FRAMEBUFFER, 0); glBindFramebuffer(GL_FRAMEBUFFER, 0);
glViewport(oldviewport[0], oldviewport[1], oldviewport[2], oldviewport[3]);
} }
Renderer::~Renderer(){}
void Renderer::setCurrentFrameBuffer(const Framebuffer& fb)
{
m_framebuffer = fb;
}
void Renderer::setClearColor(const glm::vec3& ClearColor)
{
m_clearColor = ClearColor;
}
} }

View File

@ -1,23 +1,113 @@
#pragma once #pragma once
#include "GLFW/glfw3.h" #include "GLFW/glfw3.h"
#include <vector>
#include "../PerfCounter.h" #include "../PerfCounter.h"
#include "../Scene/Scene.h"
#include "Renderable.h" #include "Framebuffer.h"
#include "Memory/Framebuffer.h"
#include "../Scene/Components.h"
#include"../Scene/Scene.h"
namespace YoggieEngine { namespace YoggieEngine {
struct RendererConfig {
int ScreenWidth, ScreenHeight;
glm::vec3 ClearColor;
bool DepthTest;
};
class Renderer { class Renderer {
public: public:
Renderer(); Renderer();
~Renderer(); ~Renderer();
void Prepare(Scene& scene);
void Render(Scene& scene );
void Render(Framebuffer* framebuffer, Scene& scene); // Forward pass
/*
forwardShader.Use();
forwardShader.setUniformVec3("Color", renderComponent.color);
forwardShader.setUniformMat4("M", transform.LocalTransform);
forwardShader.setUniformMat4("V", MainCamera.view);
forwardShader.setUniformMat4("P", MainCamera.projection);
OpenGLApi::DrawTriangles(renderComponent);
*/
void Render(Scene& scene, Camera MainCamera);
void setCurrentFrameBuffer(const Framebuffer& fb);
void setClearColor(const glm::vec3& ClearColor);
Framebuffer& getCurrentFrameBuffer() { return m_framebuffer; }
private:
Framebuffer m_framebuffer;
int width, height;
glm::vec3 m_clearColor;
bool m_depthTest;
void CreateGBuffer();
Shader forwardShader;
// deferred rending parameters
unsigned int gBuffer, gPosition, gNormal, gColorSpec, gDepth;
Shader lightingPassShader;
Shader gBufferShader;
Shader SkyboxShader;
Shader postProcessingShader;
// blending
Shader BlendingShader;
CubeMap skybox;
Texture grassTexture;
unsigned int transparentVAO = 0;
unsigned int skyboxVAO = 0;
unsigned int quadVAO = 0;
float skyboxVertices[36*3]{
// positions
-1.0f, 1.0f, -1.0f,
-1.0f, -1.0f, -1.0f,
1.0f, -1.0f, -1.0f,
1.0f, -1.0f, -1.0f,
1.0f, 1.0f, -1.0f,
-1.0f, 1.0f, -1.0f,
-1.0f, -1.0f, 1.0f,
-1.0f, -1.0f, -1.0f,
-1.0f, 1.0f, -1.0f,
-1.0f, 1.0f, -1.0f,
-1.0f, 1.0f, 1.0f,
-1.0f, -1.0f, 1.0f,
1.0f, -1.0f, -1.0f,
1.0f, -1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f, 1.0f, -1.0f,
1.0f, -1.0f, -1.0f,
-1.0f, -1.0f, 1.0f,
-1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f, -1.0f, 1.0f,
-1.0f, -1.0f, 1.0f,
-1.0f, 1.0f, -1.0f,
1.0f, 1.0f, -1.0f,
1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
-1.0f, 1.0f, 1.0f,
-1.0f, 1.0f, -1.0f,
-1.0f, -1.0f, -1.0f,
-1.0f, -1.0f, 1.0f,
1.0f, -1.0f, -1.0f,
1.0f, -1.0f, -1.0f,
-1.0f, -1.0f, 1.0f,
1.0f, -1.0f, 1.0f
};
std::vector<glm::vec3> vegetation = {
glm::vec3(-1.5f, 0.0f, -0.48f),
glm::vec3(1.5f, 0.0f, 0.51f),
glm::vec3(0.0f, 0.0f, 0.7f),
glm::vec3(-0.3f, 0.0f, -2.3f)
};
}; };
} }

View File

@ -101,29 +101,29 @@ namespace YoggieEngine {
} }
void Shader::setUniformMat4(std::string uniformName, glm::mat4 matrix4) const void Shader::setUniformMat4(std::string uniformName, const glm::mat4& matrix4) const
{ {
glUniformMatrix4fv(glGetUniformLocation(id, uniformName.c_str()), 1, GL_FALSE, glm::value_ptr(matrix4)); glUniformMatrix4fv(glGetUniformLocation(id, uniformName.c_str()), 1, GL_FALSE, glm::value_ptr(matrix4));
} }
void Shader::setUniformVec4(std::string uniformName, glm::vec4 vector4) const void Shader::setUniformVec4(std::string uniformName, const glm::vec4& vector4) const
{ {
glUniform4fv(glGetUniformLocation(id, uniformName.c_str()), 1, glm::value_ptr(vector4)); glUniform4fv(glGetUniformLocation(id, uniformName.c_str()), 1, glm::value_ptr(vector4));
} }
void Shader::setUniformVec3(std::string uniformName, glm::vec3 vector3) const void Shader::setUniformVec3(std::string uniformName, const glm::vec3& vector3) const
{ {
glUniform3fv(glGetUniformLocation(id, uniformName.c_str()), 1, glm::value_ptr(vector3)); glUniform3fv(glGetUniformLocation(id, uniformName.c_str()), 1, glm::value_ptr(vector3));
} }
void Shader::setUniformVec2(std::string uniformName, glm::vec2 vector2) const void Shader::setUniformVec2(std::string uniformName,const glm::vec2& vector2) const
{ {
glUniform2fv(glGetUniformLocation(id, uniformName.c_str()), 1, glm::value_ptr(vector2)); glUniform2fv(glGetUniformLocation(id, uniformName.c_str()), 1, glm::value_ptr(vector2));
} }
void Shader::setUniformFloat(std::string uniformName, float value) const void Shader::setUniformFloat(std::string uniformName, const float& value) const
{ {
glUniform1f(glGetUniformLocation(id, uniformName.c_str()), value); glUniform1f(glGetUniformLocation(id, uniformName.c_str()), value);
} }
void Shader::setUniformInt(std::string uniformName, int value) const void Shader::setUniformInt(std::string uniformName, const int& value) const
{ {
glUniform1i(glGetUniformLocation(id, uniformName.c_str()), value); glUniform1i(glGetUniformLocation(id, uniformName.c_str()), value);
} }

View File

@ -0,0 +1,26 @@
#pragma once
#include "Assets/Asset.h"
namespace YoggieEngine {
class Shader : public Asset{
private:
char* readFile(const char* filePath);
AssetType GetType() override{ return AssetType::Shader; }
public:
Shader(const std::string vertexShaderPath, const std::string fragmentShaderPath);
void Use() const;
void setUniformMat4(std::string uniformName, const glm::mat4& matrix4)const;
void setUniformVec4(std::string uniformName, const glm::vec4& vector4)const;
void setUniformVec3(std::string uniformName, const glm::vec3& vector3)const;
void setUniformVec2(std::string uniformName, const glm::vec2& vector2)const;
void setUniformFloat(std::string uniformName, const float& value)const;
void setUniformInt(std::string uniformName, const int& value) const;
int id;
};
}

View File

@ -1,34 +1,36 @@
#include <YoggieEngine.h> #include <YoggieEngine.h>
#include "Texture.h" #include "Texture.h"
#include <GLFW/glfw3.h>
#define STB_IMAGE_IMPLEMENTATION
#include "../stb_image.h"
namespace YoggieEngine { namespace YoggieEngine {
Texture::Texture(const std::string texturePath) {
int width, height, channels; void Texture::Load(const std::string texturePath, bool Transparency) {
int channels;
unsigned char* data = stbi_load(texturePath.c_str(), &width, &height, &channels, 0); unsigned char* data = stbi_load(texturePath.c_str(), &width, &height, &channels, 0);
std::cout << channels << std::endl;
if (data) { if (data) {
glGenTextures(1, &Id); glGenTextures(1, &Id);
glBindTexture(GL_TEXTURE_2D, Id); glBindTexture(GL_TEXTURE_2D, Id);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
glGenerateMipmap(GL_TEXTURE_2D); glGenerateMipmap(GL_TEXTURE_2D);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); if (Transparency) {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
}
else {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
}
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
} }
else { else {
spdlog::error("Failed to load image (%s)", texturePath); std::cout << "Failed to load image!" << std::endl;
spdlog::error("Failed to load image ({0})", texturePath);
} }
stbi_image_free(data); stbi_image_free(data);
} }
void Texture::Bind() { void Texture::Bind() {

View File

@ -0,0 +1,22 @@
#pragma once
#include "Assets/Asset.h"
namespace YoggieEngine {
class Texture : public Asset {
public:
Texture() = default;
void Load(const std::string texturePath, bool Transparency = false);
void Bind();
void Unbind();
const unsigned int GetID() const { return Id; }
const ImVec2 getSize() { return {(float)width, (float)height}; }
AssetType GetType() override { return AssetType::Texture; }
private:
unsigned int Id;
int width;
int height;
};
}

Some files were not shown because too many files have changed in this diff Show More