58 Commits

Author SHA1 Message Date
Erris
15a137644f moving nfde 2026-03-10 03:36:27 +01:00
Erris
9add74afa8 submodules 2026-03-10 03:26:42 +01:00
erris
7b6afc5240 Edit .onedev-buildspec.yml 2026-03-10 03:22:09 +01:00
erris
2b0b81b2c8 Edit .onedev-buildspec.yml 2026-03-10 03:07:51 +01:00
Erris
0d9dcfd541 Merge branch 'main' of https://git.anfer.fr/OpenEngine 2026-03-10 03:07:33 +01:00
Erris
772b219caa updating cmakelists 2026-03-10 03:07:27 +01:00
erris
be57a1fc16 Edit .onedev-buildspec.yml 2026-03-10 02:58:52 +01:00
erris
67a42e5685 Edit .onedev-buildspec.yml 2026-03-10 02:47:19 +01:00
Erris
6ace0bac91 updating cmakelists 2026-03-10 02:41:24 +01:00
erris
9b2d5bf35a Edit .onedev-buildspec.yml 2026-03-10 02:31:38 +01:00
erris
378d4c58a9 Edit .onedev-buildspec.yml 2026-03-10 02:19:15 +01:00
erris
c5d650cf6b Edit .onedev-buildspec.yml 2026-03-10 02:16:45 +01:00
erris
709fb3141b Edit .onedev-buildspec.yml 2026-03-10 02:13:21 +01:00
erris
3e96b676da Edit .onedev-buildspec.yml 2026-03-10 02:10:50 +01:00
erris
f761718957 Edit .onedev-buildspec.yml 2026-03-10 02:06:35 +01:00
erris
b72206b531 Edit .onedev-buildspec.yml 2026-03-10 02:01:13 +01:00
erris
ca74942001 Edit .onedev-buildspec.yml 2026-03-10 01:59:32 +01:00
erris
57a15752c7 Edit .onedev-buildspec.yml 2026-03-10 01:56:50 +01:00
Erris
5c5f55ec16 Merge branch 'main' of https://git.anfer.fr/OpenEngine 2026-03-10 01:56:00 +01:00
Erris
25d82d6689 adding .envrc necessary for compilation 2026-03-10 01:55:47 +01:00
erris
2e3f7c9e20 Edit .onedev-buildspec.yml 2026-03-10 01:53:39 +01:00
erris
0001e7e023 Edit .onedev-buildspec.yml 2026-03-10 01:51:20 +01:00
erris
d3a0e88eb0 Edit .onedev-buildspec.yml 2026-03-10 01:45:26 +01:00
erris
752d556204 Edit .onedev-buildspec.yml 2026-03-10 01:41:33 +01:00
erris
94529460e2 Edit .onedev-buildspec.yml 2026-03-10 01:40:54 +01:00
erris
37864d6d37 Edit .onedev-buildspec.yml 2026-03-10 01:39:59 +01:00
erris
54c083ccda Edit .onedev-buildspec.yml 2026-03-10 01:09:15 +01:00
Erris
44910bd3f8 test autopush 2026-03-09 17:41:40 +01:00
Erris
b4f4aa010e Merge branch 'main' of https://git.anfer.fr/OpenEngine 2026-03-09 17:40:10 +01:00
Erris
521ee17daf Merge branch 'fastgltf' 2026-03-09 17:35:29 +01:00
Erris
2175b60990 test commit to sync to gitea 2026-03-09 17:19:20 +01:00
erris
ebb179ec68 Adding repo sync to gitea 2026-03-09 17:18:07 +01:00
erris
ee8841b6d4 Add README.md 2026-03-09 16:39:04 +01:00
Erris
a0c900166f improved model loading and added model component 2026-03-09 16:37:30 +01:00
Erris
ac18bb6f00 Initial fastgltf integration 2026-03-08 11:38:46 +01:00
Erris
464ab70c46 Merge branch 'jolt' 2026-03-07 11:53:40 +01:00
Erris
48d2905695 Merge branch 'fastgltf' into jolt 2026-03-07 11:53:23 +01:00
Erris
af7b7d2bfa adding plane shape and universal guizmo (this is the wrong branch) 2026-03-07 11:48:46 +01:00
Erris
1eda916f3e Merge branch '3d' 2026-03-06 18:09:39 +01:00
Erris
44f766863d Merge branch 'jolt' into 3d 2026-03-06 18:09:26 +01:00
Erris
2d3fe57d5a added UUID 2026-03-06 18:07:51 +01:00
Erris
5be3c61859 fixing segv when closing the program 2026-03-05 22:30:48 +01:00
Erris
a187bd2894 needed for jolt 2026-03-05 01:23:26 +01:00
Erris
ecf27eae73 various bug fix, serialization, adding shapes 2026-03-05 01:22:41 +01:00
Erris
f45091349e added rotation 2026-03-04 11:18:16 +01:00
Erris
eaef554b10 Adding basic impl of Jolt
Update positions on 60tps, position of objects can be modified while
physic simulation is running. Position is owned by transform comps but
the truth is held by the physics engine for affected entities
2026-03-04 10:19:46 +01:00
Erris
282eeeabda fixed unselecting entity when cursor goes from ImGui to viewport while click is held 2026-03-03 09:38:52 +01:00
Erris
4a624cfe70 adding materials, adding serialization for meshes and materials, random fixes 2026-03-03 08:51:02 +01:00
Erris
7da00008e0 Merge branch '3d' 2026-03-02 21:28:20 +01:00
Erris
b7e5ceb1d1 added quad primitive, shortcuts and safe entity deletion 2026-03-02 21:27:42 +01:00
Erris
f26ee2bca8 Merge branch '3d' 2026-03-02 13:12:56 +01:00
Erris
c189b12365 adding missing changes 2026-03-02 13:12:32 +01:00
Erris
03bca252d3 setting up 3d 2026-03-02 00:49:08 +01:00
Erris
90a6ea00c0 3d renderer 2026-03-01 17:06:15 +01:00
Erris
abe8016f84 adding icons to repo 2026-02-28 09:43:21 +01:00
Erris
3192d7b9a0 added play/pause and basic icon storage 2026-02-28 09:42:20 +01:00
Erris
9de9609dee content browser and textures on entity sprites 2026-02-27 10:45:44 +01:00
Erris
cee0f42164 Merge branch 'dynamic_property_display' 2026-02-24 19:15:39 +01:00
69 changed files with 3084 additions and 643 deletions

4
.envrc Normal file
View File

@@ -0,0 +1,4 @@
export CC=clang
export CXX=clang++
export COMPILE_COMMANDS=ON
export BUILD_TYPE=Debug

6
.gitmodules vendored Normal file
View File

@@ -0,0 +1,6 @@
[submodule "vendor/nativefiledialog-extended"]
path = vendor/nativefiledialog-extended
url = https://github.com/btzy/nativefiledialog-extended
[submodule "open_engine/vendor/nativefiledialog-extended"]
path = open_engine/vendor/nativefiledialog-extended
url = https://github.com/btzy/nativefiledialog-extended

69
.onedev-buildspec.yml Normal file
View File

@@ -0,0 +1,69 @@
version: 46
jobs:
- name: Push to Gitea
steps:
- type: PushRepository
name: Push to Gitea
remoteUrl: https://gitea.anfer.fr/anfer/OpenEngine
passwordSecret: Gitea
force: false
condition: SUCCESSFUL
optional: false
triggers:
- type: BranchUpdateTrigger
branches: main
userMatch: anyone
projects: OpenEngine
- type: TagCreateTrigger
branches: main
projects: OpenEngine
retryCondition: never
maxRetries: 3
retryDelay: 30
timeout: 14400
- name: Compile for Linux
steps:
- type: SetupCacheStep
name: conan_cache
key: conan-cache
paths:
- /root/.conan2
uploadStrategy: UPLOAD_IF_CHANGED
changeDetectionExcludes: .onedev-buildspec.yml open_engine/** editor/**
uploadProjectPath: OpenEngine
condition: SUCCESSFUL
optional: false
- type: CheckoutStep
name: Checkout
cloneCredential:
type: DefaultCredential
withLfs: false
withSubmodules: false
condition: SUCCESSFUL
optional: false
- type: CommandStep
name: Compile for Linux
runInContainer: true
image: erriss/erris-build_tools:V0.3
interpreter:
type: DefaultInterpreter
commands: |
conan profile detect --force
sed -i 's/cmake_minimum_required(VERSION 3.28)/cmake_minimum_required(VERSION 3.25)/' CMakeLists.txt
conan install . --output-folder=. --build=missing -s build_type=${BUILD_TYPE}
cmake -S . -G Ninja -B build -DCMAKE_BUILD_TYPE=${BUILD_TYPE} -DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake
cmake --build . --config ${BUILD_TYPE}
envVars:
- name: BUILD_TYPE
value: Debug
- name: CC
value: clang
- name: CXX
value: clang++
useTTY: true
condition: SUCCESSFUL
optional: false
retryCondition: never
maxRetries: 3
retryDelay: 30
timeout: 14400

View File

@@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.28)
cmake_minimum_required(VERSION 3.25.1)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)

1
README.md Normal file
View File

@@ -0,0 +1 @@
Readme

101
assets/shaders/color3d.glsl Normal file
View File

@@ -0,0 +1,101 @@
#type vertex
#version 450 core
layout(location = 0) in vec3 a_Position;
layout(location = 1) in vec3 a_Normal;
layout(location = 2) in vec2 a_TexCoord;
layout(std140, binding = 0) uniform Camera
{
mat4 u_ViewProjection;
vec3 u_ViewPosition;
};
layout(std140, binding = 1) uniform Transform
{
mat4 u_Transform;
};
struct VertexOutput
{
vec2 TexCoord;
vec3 Normal;
vec3 ViewPos;
};
layout (location = 0) out VertexOutput Output;
layout (location = 5) out vec4 v_Pos;
void main()
{
Output.TexCoord = a_TexCoord;
Output.Normal = mat3(transpose(inverse(u_Transform))) * a_Normal;
Output.ViewPos = u_ViewPosition;
v_Pos = u_Transform * vec4(a_Position, 1.0);
gl_Position = u_ViewProjection * v_Pos;
}
#type fragment
#version 450 core
layout (location = 0) out vec4 color;
layout (location = 1) out int color2;
layout (std140, binding = 2) uniform Material
{
vec4 u_Albedo;
float u_Roughness;
float u_Metallic;
float u_AmbientStrength;
float u_SpecularStrength;
};
layout(std140, binding = 3) uniform EditorID
{
int u_EntityID;
};
struct VertexOutput
{
vec2 TexCoord;
vec3 Normal;
vec3 ViewPos;
};
layout (location = 0) in VertexOutput Input;
layout (location = 4) in flat int v_EntityID;
layout (location = 5) in vec4 v_Pos;
void main()
{
vec3 lightPos = vec3(0.0f, 1.0f, 0.0f);
vec3 lightColor = vec3(1.0f, 1.0f, 1.0f);
// Ambiant lighting
vec3 ambient = lightColor * u_AmbientStrength;
// Diffuse lighting
vec3 norm = normalize(Input.Normal);
vec3 lightDir = normalize(lightPos - v_Pos.xyz);
float diff = max(dot(norm, lightDir), 0.0);
vec3 diffuse = diff * lightColor;
// Specular highlight
vec3 viewDir = normalize(Input.ViewPos - v_Pos.xyz); // .xyz here too
vec3 reflectDir = reflect(-lightDir, norm);
float shininess = mix(2.0, 256.0, 1.0 - u_Roughness);
float spec = pow(max(dot(viewDir, reflectDir), 0.0), shininess);
vec3 specularColor = mix(vec3(1.0), u_Albedo.rgb, u_Metallic);
vec3 specular = u_SpecularStrength * spec * lightColor * specularColor;
// Total
//vec3 result = (ambient + diffuse + specular) * Input.Color.rgb; // objectColor → Input.Color.rgb
vec3 result = (ambient + diffuse + specular) * u_Albedo.rgb; // objectColor → Input.Color.rgb
// Output
color = vec4(result, u_Albedo.w); // vec3 → vec4
color2 = u_EntityID;
}

View File

@@ -3,6 +3,8 @@ imgui/1.92.5-docking
spdlog/1.16.0
entt/3.16.0
yaml-cpp/0.8.0
joltphysics/5.2.0
fastgltf/0.9.0
[generators]
CMakeDeps

View File

@@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.28)
cmake_minimum_required(VERSION 3.25.1)
set(CMAKE_CXX_STANDARD 20)

View File

@@ -3,8 +3,19 @@
#include <open_engine.hpp>
#include "open_engine/fastgltf.hpp"
#include "open_engine/logging.hpp"
#include "open_engine/ref_scope.hpp"
#include "open_engine/renderer/model3d.hpp"
#include "open_engine/renderer/renderer3d.hpp"
#include "open_engine/scene/components.hpp"
#include "panels/content_browser.hpp"
#include "panels/scene_hierarchy.hpp"
#include <Jolt/Physics/Collision/Shape/Shape.h>
#include <Jolt/Math/Real.h>
#include <Jolt/Math/Vec3.h>
#include <Jolt/Physics/Body/BodyCreationSettings.h>
#include <glm/ext/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <glm/matrix.hpp>
@@ -12,6 +23,7 @@
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <ImGuizmo.h>
#include <filesystem>
#include <cstdint>
#include <imgui.h>
#include <vector>
@@ -19,6 +31,12 @@
namespace OpenEngine {
enum class PlayState
{
Edit = 0,
Play = 1
};
class CameraController : public NativeScriptableEntity
{
public:
@@ -71,8 +89,76 @@ namespace OpenEngine {
scene = CreateRef<Scene>();
auto command_line_args = Application::Get().GetCommandLineArgs();
if (command_line_args.count > 1) {
auto scene_path = command_line_args[1];
SceneSerializer serializer(scene);
serializer.Deserialize(scene_path);
}
editor_camera = EditorCamera(30.0f, 1920.0f/1080.0f, 0.1f, 1000.0f);
// TODO: Add license
icons["play"] = Texture2D::Create("resources/textures/icons/play.png");
icons["stop"] = Texture2D::Create("resources/textures/icons/stop.png");
// =============================================
Entity cube = scene->CreateEntity("cube");
auto& tc = cube.AddComponent<TransformComponent>();
Ref<Mesh> mesh = CreateCube(cube);
auto& mc = cube.AddComponent<MeshComponent>(mesh);
mc.primitive_type = PrimitiveType::Cube;
// =============================================
Entity quad = scene->CreateEntity("quad");
quad.AddComponent<TransformComponent>();
quad.GetComponents<TransformComponent>().translation = {0, 0, 0};
Ref<Mesh> quad_mesh = CreateQuad(quad, true);
auto& mc3 = quad.AddComponent<MeshComponent>(quad_mesh);
mc3.primitive_type = PrimitiveType::Quad;
// =============================================
Entity cube2 = scene->CreateEntity("cube2");
cube2.AddComponent<TransformComponent>();
cube2.GetComponents<TransformComponent>().translation = {2, 0, 0};
Ref<Mesh> mesh2 = CreateCube(cube2);
auto& mc2 = cube2.AddComponent<MeshComponent>(mesh2);
mc2.primitive_type = PrimitiveType::Cube;
// ============================================================
Entity cube3 = scene->CreateEntity("glb");
Entity cube4 = scene->CreateEntity("glb2");
Entity cube5 = scene->CreateEntity("glb2");
cube3.AddComponent<TransformComponent>();
cube4.AddComponent<TransformComponent>();
cube5.AddComponent<TransformComponent>();
Ref<Model3D> model = Model3D::Create("./assets/models/cubes.glb");
Ref<Model3D> model2 = Model3D::Create("./assets/models/cube_legs.glb");
Ref<Model3D> monkey = Model3D::Create("./assets/models/monkey.glb");
cube3.AddComponent<ModelComponent>(model);
cube3.AddComponent<ModelComponent>(model2);
cube4.AddComponent<ModelComponent>(monkey);
/*
auto view = scene->GetRegistry().view<TagComponent>();
for (auto& entity : view) {
auto tag = view->get(entity);
OE_DEBUG("entity: {}, tag: {}", (uint32_t)entity, tag.tag);
}
*/
//icons["folder"] = Texture2D::Create("resources/textures/icons/folder.png");
/*
for (float i = 0; i < 200; i++) {
for (float y = 0; y < 200; y++) {
@@ -90,6 +176,13 @@ namespace OpenEngine {
scene_hierarchy.Init(scene);
}
Ref<Texture2D> GetIcon(const char* name)
{
if (icons.contains(name))
return icons[name];
return nullptr;
}
void OnDetach() override
{
}
@@ -109,14 +202,23 @@ namespace OpenEngine {
}
framebuffer->Bind();
Renderer2D::ResetStats();
//Renderer2D::ResetStats();
RenderCommand::SetClearColor({0.11f, 0.11f, 0.15f, 1.0f});
RenderCommand::Clear();
framebuffer->ClearBufferI(1, -1);
editor_camera.OnUpdate();
scene->OnUpdateEditor(editor_camera);
switch (state) {
case PlayState::Play: {
scene->OnUpdateRuntime();
break;
}
case PlayState::Edit: {
if (viewport_focused)
editor_camera.OnUpdate();
scene->OnUpdateEditor(editor_camera);
break;
}
}
auto [mx, my] = ImGui::GetMousePos();
@@ -131,9 +233,12 @@ namespace OpenEngine {
static bool clicked = false;
// Mouse Picking
if (Input::IsMouseButtonPressed(MouseCode::ButtonLeft)
&& !Application::Get().GetImGuiLayer()->GetBlockEvents()
&& mouse_x >= 0 && mouse_y >= 0
&& mouse_x < (int)viewport_size.x && (int)viewport_size.y &&
!ImGuizmo::IsOver() && !Input::IsKeyPressed(KeyCode::LeftAlt)) {
&& mouse_x < (int)viewport_size.x
&& mouse_y < (int)viewport_size.y
&& !ImGuizmo::IsOver()
&& !Input::IsKeyPressed(KeyCode::LeftAlt)) {
if (!clicked) {
int id = framebuffer->ReadPixel(1, mouse_x, mouse_y);
@@ -143,7 +248,6 @@ namespace OpenEngine {
scene_hierarchy.SetSelectedEntity(selected_entity);
}
clicked = true;
} else {
clicked = false;
@@ -151,6 +255,8 @@ namespace OpenEngine {
}
framebuffer->Unbind();
scene->UpdateEntities();
}
bool EditorKeyBinds(KeyPressedEvent& event)
@@ -161,6 +267,29 @@ namespace OpenEngine {
bool shift = Input::IsKeyPressed(Key::LeftShift) || Input::IsKeyPressed(Key::RightShift);
switch(event.GetKeyCode()) {
case KeyCode::S: {
if (control) {
std::string file = FileDialogs::SaveFile("useless");
OE_TRACE("saving to filename: {}", file);
SaveScene(file);
}
break;
}
case KeyCode::N: {
if (control) {
scene = CreateRef<Scene>();
scene->OnViewportResize((uint32_t)viewport_size.x, (uint32_t)viewport_size.y);
scene_hierarchy.Init(scene);
}
break;
}
case KeyCode::O: {
if (control) {
std::string file = FileDialogs::OpenFile("useless");
OE_DEBUG("loading scene: {}", file);
OpenScene(file);}
break;
}
case KeyCode::Q: {
guizmo_operation = -1;
break;
@@ -177,6 +306,16 @@ namespace OpenEngine {
guizmo_operation = ImGuizmo::OPERATION::SCALE;
break;
}
case KeyCode::T: {
guizmo_operation = ImGuizmo::OPERATION::UNIVERSAL;
break;
}
case KeyCode::Delete: {
scene->MarkEntityForDeletion(selected_entity);
scene_hierarchy.ClearSelection();
selected_entity = {};
break;
}
default:
break;
}
@@ -240,11 +379,15 @@ namespace OpenEngine {
void DrawViewport()
{
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2{ 0, 0 });
ImGui::Begin("Viewport");
bool focused = ImGui::IsWindowFocused();
bool hovered = ImGui::IsWindowHovered();
Application::Get().GetImGuiLayer()->SetBlockEvents((!focused && !hovered) || ImGui::IsAnyItemActive());
bool was_focused = viewport_focused;
viewport_focused = ImGui::IsWindowFocused(ImGuiFocusedFlags_RootWindow);
viewport_hovered = ImGui::IsWindowHovered(ImGuiHoveredFlags_RootWindow);
Application::Get().GetImGuiLayer()->SetBlockEvents(ImGui::IsAnyItemActive());
if (viewport_focused && !was_focused)
editor_camera.ResetMousePosition();
ImVec2 viewport_panel_size = ImGui::GetContentRegionAvail();
@@ -255,6 +398,15 @@ namespace OpenEngine {
uint32_t texture_id = framebuffer->GetColorAttachmentRendererID();
ImGui::Image((void*)(uint64_t)texture_id, ImVec2{ viewport_size.x, viewport_size.y }, ImVec2{ 0, 1 }, ImVec2{ 1, 0 });
if (ImGui::BeginDragDropTarget()) {
if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload("CONTENT_BROWSER_PAYLOAD")) {
std::filesystem::path path = (const char*)payload->Data;
if (path.extension() == ".oes")
OpenScene(path);
}
ImGui::EndDragDropTarget();
}
viewport_bounds[0] = { imgui_cursor_position.x, imgui_cursor_position.y };
viewport_bounds[1] = { imgui_cursor_position.x + viewport_size.x,
imgui_cursor_position.y + viewport_size.y };
@@ -267,7 +419,7 @@ namespace OpenEngine {
void DrawStats()
{
auto stats = Renderer2D::GetStats();
//auto stats = Renderer2D::GetStats();
static float time = 0;
time += Time::DeltaTime();
@@ -279,17 +431,17 @@ namespace OpenEngine {
ImGui::Begin("Statistics");
ImGui::SeparatorText("Performance");
ImGui::Text("FPS: %0.0f", 1 / Time::DeltaTime());
ImGui::Text("Renderer2D:");
ImGui::Text("\t\tDraw calls: %d", stats.draw_calls);
ImGui::Text("\t\tQuad count: %d", stats.quad_count);
ImGui::Text("\t\tVertices count: %d", stats.GetTotalVertexCount());
ImGui::Text("\t\tIndices count: %d", stats.GetTotalIndexCount());
if (selected_entity) {
ImGui::SeparatorText("Entities");
ImGui::Text("Selected entity:");
ImGui::Text("\t\tname: %s", selected_entity.GetComponents<TagComponent>().tag.c_str());
ImGui::Text("\t\tid: %d", (uint32_t)selected_entity);
}
//ImGui::Text("Renderer2D:");
//ImGui::Text("\t\tDraw calls: %d", stats.draw_calls);
//ImGui::Text("\t\tQuad count: %d", stats.quad_count);
//ImGui::Text("\t\tVertices count: %d", stats.GetTotalVertexCount());
//ImGui::Text("\t\tIndices count: %d", stats.GetTotalIndexCount());
//if (selected_entity) {
// ImGui::SeparatorText("Entities");
// ImGui::Text("Selected entity:");
// ImGui::Text("\t\tname: %s", selected_entity.GetComponents<TagComponent>().tag.c_str());
// ImGui::Text("\t\tid: %d", (uint32_t)selected_entity);
//}
ImGui::End();
};
@@ -337,33 +489,82 @@ namespace OpenEngine {
guizmo_operation = -1;
};
void OpenScene(const std::string& file)
{
if (!file.empty()) {
scene = CreateRef<Scene>();
scene->OnViewportResize((uint32_t)viewport_size.x, (uint32_t)viewport_size.y);
scene_hierarchy.Init(scene);
SceneSerializer serializer(scene);
serializer.Deserialize(file);
}
}
void SaveScene(const std::string& file)
{
if (!file.empty()) {
SceneSerializer serializer(scene);
serializer.Serialize(file);
}
}
void DrawPlayBar()
{
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, { 0, 2 });
ImGui::PushStyleVar(ImGuiStyleVar_ItemInnerSpacing, { 0, 0 });
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, { 0, 0 });
ImGui::PushStyleColor(ImGuiCol_Button, { 0, 0, 0, 0 });
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, { 0.200f, 0.207f, 0.286f, 1.0f });
ImGui::PushStyleColor(ImGuiCol_ButtonActive, { 0, 0, 0, 0 });
ImGui::Begin("##play_state_bar", nullptr, ImGuiWindowFlags_NoDecoration
| ImGuiWindowFlags_NoScrollWithMouse
| ImGuiWindowFlags_NoScrollbar
| ImGuiWindowFlags_NoTitleBar);
float size = ImGui::GetContentRegionAvail().y;
auto icon = state == PlayState::Play ? icons["stop"] : icons["play"];
ImGui::SetCursorPosX((ImGui::GetContentRegionAvail().x * 0.5) - (size * 0.5) );
if (ImGui::ImageButton("##play_button",
(ImTextureID)icon->GetID(), { size, size })) {
switch (state) {
case PlayState::Play : {
OnSceneStop();
break;
}
case PlayState::Edit : {
OnScenePlay();
break;
}
}
}
ImGui::End();
ImGui::PopStyleColor(3);
ImGui::PopStyleVar(3);
}
void OnImGuiRender() override
{
OE_PROFILE_FUNCTION();
ImGui::PushStyleVar(ImGuiStyleVar_WindowMinSize, ImVec2(450, 200));
ImGui::PushStyleVar(ImGuiStyleVar_WindowMinSize, ImVec2(450, 35));
{
if (ImGui::BeginMainMenuBar()) {
if (ImGui::BeginMenu("File")) {
if (ImGui::MenuItem("Save Scene As", "Ctrl+S")) {
std::string file = FileDialogs::SaveFile("useless");
OE_TRACE("saving to filename: {}", file);
if (!file.empty()) {
SceneSerializer serializer(scene);
serializer.Serialize(file);
}
SaveScene(file);
}
if (ImGui::MenuItem("Open Scene", "Ctrl+O")) {
std::string file = FileDialogs::OpenFile("useless");
OE_DEBUG("loading filename: {}", file);
if (!file.empty()) {
scene = CreateRef<Scene>();
scene->OnViewportResize((uint32_t)viewport_size.x, (uint32_t)viewport_size.y);
scene_hierarchy.Init(scene);
SceneSerializer serializer(scene);
serializer.Deserialize(file);
}
OE_DEBUG("loading scene: {}", file);
OpenScene(file);
}
if (ImGui::MenuItem("New Scene", "Ctrl+N")) {
scene = CreateRef<Scene>();
@@ -383,13 +584,27 @@ namespace OpenEngine {
DrawStats();
scene_hierarchy.OnImGuiRender();
browser.OnImGuiRender();
DrawViewport();
DrawPlayBar();
ImGui::ShowDemoWindow();
ImGui::PopStyleVar();
};
void OnScenePlay()
{
state = PlayState::Play;
scene->OnRuntimeStart();
}
void OnSceneStop()
{
state = PlayState::Edit;
scene->OnRuntimeStop();
}
private:
ContentBrowserPanel browser;
std::vector<Time::ProfilingResult> profiling_results;
glm::vec2 world_pos_cursor = { 0.0f, 0.0f };
@@ -398,43 +613,30 @@ namespace OpenEngine {
Ref<OpenEngine::FrameBuffer> framebuffer;
glm::vec2 viewport_bounds[2];
bool viewport_focused = false, viewport_hovered = false;
SceneHierarchy scene_hierarchy;
EditorCamera editor_camera;
int guizmo_operation = -1;
// TODO: Rename this to GameState
PlayState state = PlayState::Edit;
std::unordered_map<const char*, Ref<Texture2D>> icons;
Ref<Scene> scene;
Entity selected_entity;
std::vector<Entity> entities;
};
}
class EditorApp : public OpenEngine::Application
{
public:
EditorApp();
EditorApp(OpenEngine::ApplicationCommandLineArgs args);
~EditorApp();
};
#endif // EDITOR_HPP
/*
#include <cstdio>
#include <string>
std::string OpenFile() {
char buffer[1024];
// This command opens a native GTK file picker and returns the path
FILE* pipe = popen("zenity --file-selection", "r");
if (!pipe) return "";
if (fgets(buffer, sizeof(buffer), pipe) != NULL) {
std::string path = buffer;
path.erase(path.find_last_not_of("\n") + 1); // Clean newline
pclose(pipe);
return path;
}
pclose(pipe);
return "";
}
*/

View File

@@ -13,12 +13,16 @@ namespace OpenEngine {
const std::array<const char*, 3> labels = {"x", "y", "z"});
void TagOnImGuiRender(entt::registry& registry, entt::entity entity);
void TransformOnImGuiRender(entt::registry& registry, entt::entity entity);
void SpriteOnImGuiRender(entt::registry& registry, entt::entity entity);
void CameraOnImGuiRender(entt::registry& registry, entt::entity entity);
void MeshOnImGuiRender(entt::registry&registry, entt::entity entity);
void MaterialOnImGuiRender(entt::registry& registry, entt::entity entity);
void BodyOnImGuiRender(entt::registry& registry, entt::entity entity);
void SphereShapeOnImGuiRender(entt::registry& registry, entt::entity entity);
void BoxShapeOnImGuiRender(entt::registry& registry, entt::entity entity);
void PlaneShapeOnImGuiRender(entt::registry& registry, entt::entity entity);
void ModelOnImGuiRender(entt::registry& registry, entt::entity entity);
}
#endif // EDITOR_COMPONENT_HPP

View File

@@ -0,0 +1,26 @@
#ifndef CONTENT_BROWSER_HPP
#define CONTENT_BROWSER_HPP
#include "open_engine/renderer/texture.hpp"
#include <filesystem>
namespace OpenEngine {
class EditorLayer;
class ContentBrowserPanel
{
public:
ContentBrowserPanel();
void OnImGuiRender();
private:
std::filesystem::path current_directory;
Ref<Texture2D> folder_icon;
Ref<Texture2D> file_icon;
};
}
#endif // CONTENT_BROWSER_HPP

View File

@@ -27,6 +27,7 @@ namespace OpenEngine {
Entity GetSelectedEntity() const { return selected_context; };
void SetSelectedEntity(Entity entity) { selected_context = entity; };
void ClearSelection() { selected_context = {}; };
private:
void DrawEntityNode(Entity& entity);

View File

@@ -1,3 +1,4 @@
#include "open_engine/application.hpp"
#include <open_engine/entry_point.hpp>
#include <open_engine.hpp>
@@ -9,8 +10,8 @@
#include <overlay.hpp>
#include <modding.hpp>
EditorApp::EditorApp()
: Application("OpenEngine Editor")
EditorApp::EditorApp(OpenEngine::ApplicationCommandLineArgs args)
: Application("OpenEngine Editor", args)
{
OpenEngine::Ref<OpenEngine::Layer> modding_layer = OpenEngine::CreateRef<Modding>();
OpenEngine::Ref<OpenEngine::Layer> editor_layer = OpenEngine::CreateRef<OpenEngine::EditorLayer>();
@@ -25,8 +26,8 @@ EditorApp::~EditorApp()
{
}
OpenEngine::Application* OpenEngine::CreateApplication()
OpenEngine::Application* OpenEngine::CreateApplication(OpenEngine::ApplicationCommandLineArgs args)
{
OE_INFO("Editor Starting...");
return new EditorApp();
return new EditorApp(args);
}

View File

@@ -1,4 +1,11 @@
#include "imgui.h"
#include "open_engine/renderer/renderer3d.hpp"
#include "open_engine/scene/components.hpp"
#include <Jolt/Physics/Body/MotionType.h>
#include <cstdint>
#include <editor_component.hpp>
#include <entt/entity/fwd.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <open_engine.hpp>
namespace OpenEngine {
@@ -90,6 +97,7 @@ namespace OpenEngine {
if (ImGui::InputText("##tagEditor", buffer, sizeof(buffer), ImGuiInputTextFlags_EnterReturnsTrue | ImGuiInputTextFlags_AutoSelectAll)
|| (!ImGui::IsItemActive() && ImGui::IsMouseClicked(0)))
tag = buffer;
ImGui::Spacing();
};
void TransformOnImGuiRender(entt::registry& registry, entt::entity entity)
@@ -100,12 +108,23 @@ namespace OpenEngine {
DrawVec3Control("Rotation", rotation_comp);
transform.rotation = glm::radians(rotation_comp);
DrawVec3Control("Scale", transform.scale);
ImGui::Spacing();
};
void SpriteOnImGuiRender(entt::registry& registry, entt::entity entity)
{
auto& sprite = registry.get<SpriteRendererComponent>(entity);
ImGui::ColorEdit4("color", glm::value_ptr(sprite.color));
ImGui::Button("Texture", { 100, 0 });
if (ImGui::BeginDragDropTarget()) {
if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload("CONTENT_BROWSER_PAYLOAD"))
sprite.texture = Texture2D::Create(((const char*)payload->Data));
ImGui::EndDragDropTarget();
}
ImGui::DragFloat("Tiling factor", &sprite.tiling_factor);
};
void CameraOnImGuiRender(entt::registry& registry, entt::entity entity)
@@ -159,4 +178,149 @@ namespace OpenEngine {
}
};
void MeshOnImGuiRender(entt::registry& registry, entt::entity entity)
{
auto& mesh_component = registry.get<MeshComponent>(entity);
const char* items[] = { "None", "Quad", "Cube" };
int item_selected_idx = (int)mesh_component.primitive_type;
if (ImGui::BeginCombo("Mesh", items[item_selected_idx])) {
for (int n = 0; n < 3; n++) {
const bool is_selected = (item_selected_idx == n);
if (ImGui::Selectable(items[n], is_selected))
item_selected_idx = n;
// Set the initial focus when opening the combo (scrolling + keyboard navigation focus)
if (is_selected)
ImGui::SetItemDefaultFocus();
}
ImGui::EndCombo();
}
if ((int)mesh_component.primitive_type == (item_selected_idx))
return;
mesh_component.primitive_type = (PrimitiveType)(item_selected_idx);
switch (mesh_component.primitive_type) {
case OpenEngine::PrimitiveType::Quad:
{
mesh_component.mesh = CreateQuad((uint32_t)entity);
break;
}
case OpenEngine::PrimitiveType::Cube:
{
mesh_component.mesh = CreateCube((uint32_t)entity);
break;
}
default:
mesh_component.mesh = nullptr;
break;
}
}
void MaterialOnImGuiRender(entt::registry& registry, entt::entity entity)
{
auto& material = registry.get<MaterialComponent>(entity).material;
ImGui::SliderFloat4("Albedo", glm::value_ptr(material.albedo), 0, 1);
ImGui::SliderFloat("Roughness", &material.roughness, 0, 1);
ImGui::SliderFloat("Metallic", &material.metallic, 0, 1);
ImGui::SliderFloat("Ambient strength", &material.ambient_strength, 0, 1);
ImGui::SliderFloat("Specular strength", &material.specular_strength, 0, 10);
}
void BodyOnImGuiRender(entt::registry &registry, entt::entity entity)
{
auto& body_comp = registry.get<PhysicsBodyComponent>(entity);
const char* items[] = { "Static", "Kinematic", "Dynamic" };
int item_selected_idx = body_comp.type;
if (ImGui::BeginCombo("Body type", items[item_selected_idx])) {
for (int n = 0; n < 3; n++)
{
const bool is_selected = (item_selected_idx == n);
if (ImGui::Selectable(items[n], is_selected))
item_selected_idx = n;
// Set the initial focus when opening the combo (scrolling + keyboard navigation focus)
if (is_selected)
ImGui::SetItemDefaultFocus();
}
ImGui::EndCombo();
}
body_comp.type = item_selected_idx;
ImGui::SliderFloat("Linear damping", &body_comp.linear_damping, 0, 1);
ImGui::SliderFloat("Angular damping", &body_comp.angular_damping, 0, 1);
ImGui::SliderFloat("Gravity factor", &body_comp.gravity_factor, 0, 1);
ImGui::SliderFloat("Bounciness", &body_comp.restitution, 0, 1);
ImGui::SliderFloat("Friction", &body_comp.friction, 0, 1);
}
void SphereShapeOnImGuiRender(entt::registry &registry, entt::entity entity)
{
auto& sphere_comp = registry.get<SphereShapeComponent>(entity);
ImGui::DragFloat("Radius",
&sphere_comp.radius,
0.1f,
0.11f, FLT_MAX,
"%.2f",
ImGuiSliderFlags_AlwaysClamp);
}
void BoxShapeOnImGuiRender(entt::registry &registry, entt::entity entity)
{
auto& box_comp = registry.get<BoxShapeComponent>(entity);
ImGui::DragFloat3("Size",
glm::value_ptr(box_comp.size),
0.1f,
0.11f, FLT_MAX,
"%.2f",
ImGuiSliderFlags_AlwaysClamp);
}
void PlaneShapeOnImGuiRender(entt::registry& registry, entt::entity entity)
{
auto& planed_comp = registry.get<PlaneShapeComponent>(entity);
ImGui::DragFloat("Size",
&planed_comp.extent,
0.1f,
0.01f, FLT_MAX,
"%.2f",
ImGuiSliderFlags_AlwaysClamp);
}
void ModelOnImGuiRender(entt::registry& registry, entt::entity entity)
{
auto& model_comp = registry.get<ModelComponent>(entity);
bool opened = ImGui::TreeNodeEx(
(void*)(intptr_t)entity,
ImGuiTreeNodeFlags_None,
"Meshes");
if (opened) {
unsigned int i = 0;
for (auto& mesh : model_comp.model->GetMeshes())
ImGui::Text("Mesh: %i", i++);
ImGui::PushStyleColor(ImGuiCol_ChildBg, {1, 1, 1, 1});
if (ImGui::BeginChild("Material list")) {
for (auto& mesh : model_comp.model->GetMeshes())
ImGui::Text("Material: %s", mesh.material.name.c_str());
ImGui::EndChild();
}
ImGui::PopStyleColor();
ImGui::TreePop();
}
}
}

View File

@@ -0,0 +1,100 @@
#include "imgui_internal.h"
#include <cstdint>
#include <cstring>
#include <panels/content_browser.hpp>
#include <open_engine/renderer/texture.hpp>
#include <open_engine/logging.hpp>
#include <filesystem>
#include <imgui.h>
namespace OpenEngine {
const std::filesystem::path assets_directory = "assets";
ContentBrowserPanel::ContentBrowserPanel()
: current_directory(assets_directory)
{
// TODO: Add license
folder_icon = Texture2D::Create("resources/textures/icons/folder2.png");
file_icon = Texture2D::Create("resources/textures/icons/file.png");
}
void ContentBrowserPanel::OnImGuiRender()
{
ImGui::Begin("Assets");
ImGui::Text("%s", current_directory.c_str());
if (current_directory != assets_directory)
if (ImGui::Button(".."))
current_directory = current_directory.parent_path();
auto directory_it = std::filesystem::directory_iterator(current_directory);
std::vector<std::filesystem::directory_entry> entries;
for (auto entry : directory_it)
entries.emplace_back(entry);
std::sort(entries.begin(), entries.end(),
[](const std::filesystem::directory_entry& a,
const std::filesystem::directory_entry& b) {
return (a.is_directory() && !b.is_directory());
});
ImVec2 button_size = { 100, 100 };
auto panel_width = ImGui::GetContentRegionAvail().x;
uint32_t table_columns = (int)(panel_width / button_size.x) - 1;
if (table_columns <= 0)
table_columns = 1;
ImVec2 padding( 9, 9 );
ImGui::PushStyleVar(ImGuiStyleVar_CellPadding, padding);
float margin = 20.0f;
ImGui::Indent(margin);
if (ImGui::BeginTable("table1", table_columns, ImGuiTableFlags_SizingFixedSame))
{
for (auto& entry : entries) {
auto file_name = entry.path().filename().string();
ImGui::PushID(file_name.c_str());
ImGui::TableNextColumn();
ImGui::PushStyleColor(ImGuiCol_Button, { 0.0f, 0.0f, 0.0f, 0.0f });
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, { 0.192f, 0.196f, 0.266f, 1.0f });
ImGui::PushStyleColor(ImGuiCol_ButtonActive, { 0.270f, 0.278f, 0.352f, 1.0f });
ImGui::BeginGroup();
Ref<Texture2D> icon = entry.is_directory() ? folder_icon : file_icon;
ImGui::ImageButton("##X", (ImTextureID)icon->GetID(), button_size, { 0, 1 }, { 1, 0 });
if (entry.is_regular_file() && ImGui::BeginDragDropSource()) {
const char* source = entry.path().c_str();
ImGui::SetDragDropPayload("CONTENT_BROWSER_PAYLOAD", source, (strlen(source) + 1) * sizeof(char), ImGuiCond_Once);
ImGui::EndDragDropSource();
}
ImGui::TextWrapped("%s", file_name.c_str());
ImGui::EndGroup();
if (entry.is_directory()) {
if (ImGui::IsItemHovered() && ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left))
current_directory = entry.path().c_str();
}
ImGui::PopStyleColor(3);
ImGui::PopID();
}
ImGui::EndTable();
}
ImGui::Unindent();
ImGui::PopStyleVar();
ImGui::End();
}
}

View File

@@ -22,6 +22,13 @@ namespace OpenEngine {
RegisterDrawer<TransformComponent>("Transform", &TransformOnImGuiRender);
RegisterDrawer<SpriteRendererComponent>("Sprite Renderer", &SpriteOnImGuiRender);
RegisterDrawer<CameraComponent>("Camera", &CameraOnImGuiRender);
RegisterDrawer<MeshComponent>("Mesh", &MeshOnImGuiRender);
RegisterDrawer<MaterialComponent>("Material", &MaterialOnImGuiRender);
RegisterDrawer<PhysicsBodyComponent>("Physics Body", &BodyOnImGuiRender);
RegisterDrawer<SphereShapeComponent>("Sphere Shape", &SphereShapeOnImGuiRender);
RegisterDrawer<BoxShapeComponent>("Box Shape", &BoxShapeOnImGuiRender);
RegisterDrawer<PlaneShapeComponent>("Plane Shape", &PlaneShapeOnImGuiRender);
RegisterDrawer<ModelComponent>("Model", &ModelOnImGuiRender);
scene = context;
selected_context = {};
@@ -32,17 +39,52 @@ namespace OpenEngine {
ImGui::SeparatorText("Add");
if (!selected_context.HasComponent<TransformComponent>())
if (ImGui::MenuItem("Transform")) {
selected_context.AddComponents<TransformComponent>();
selected_context.AddComponent<TransformComponent>();
ImGui::CloseCurrentPopup();
}
if (!selected_context.HasComponent<SpriteRendererComponent>())
if (ImGui::MenuItem("Sprite")) {
selected_context.AddComponents<SpriteRendererComponent>();
selected_context.AddComponent<SpriteRendererComponent>();
ImGui::CloseCurrentPopup();
}
if (!selected_context.HasComponent<CameraComponent>())
if (ImGui::MenuItem("Camera")) {
selected_context.AddComponents<CameraComponent>();
selected_context.AddComponent<CameraComponent>();
ImGui::CloseCurrentPopup();
}
if (!selected_context.HasComponent<MeshComponent>())
if (ImGui::MenuItem("Mesh")) {
selected_context.AddComponent<MeshComponent>();
ImGui::CloseCurrentPopup();
}
if (!selected_context.HasComponent<MaterialComponent>())
if (ImGui::MenuItem("Material")) {
selected_context.AddComponent<MaterialComponent>();
ImGui::CloseCurrentPopup();
}
if (!selected_context.HasComponent<PhysicsBodyComponent>())
if (ImGui::MenuItem("Physics body")) {
selected_context.AddComponent<PhysicsBodyComponent>();
ImGui::CloseCurrentPopup();
}
if (!selected_context.HasComponent<SphereShapeComponent>())
if (ImGui::MenuItem("Sphere shape")) {
selected_context.AddComponent<SphereShapeComponent>();
ImGui::CloseCurrentPopup();
}
if (!selected_context.HasComponent<BoxShapeComponent>())
if (ImGui::MenuItem("Box shape")) {
selected_context.AddComponent<BoxShapeComponent>();
ImGui::CloseCurrentPopup();
}
if (!selected_context.HasComponent<PlaneShapeComponent>())
if (ImGui::MenuItem("Plane shape")) {
selected_context.AddComponent<PlaneShapeComponent>();
ImGui::CloseCurrentPopup();
}
if (!selected_context.HasComponent<ModelComponent>())
if (ImGui::MenuItem("Model")) {
selected_context.AddComponent<ModelComponent>();
ImGui::CloseCurrentPopup();
}
}
@@ -127,7 +169,6 @@ namespace OpenEngine {
{
auto& tag = entity.GetComponents<TagComponent>().tag;
bool entity_marked_deletion = false;
if (renamed_entity == entity && selected_context == entity) {
char buffer[255];
std::memset(buffer, 0, sizeof(buffer));
@@ -155,8 +196,10 @@ namespace OpenEngine {
bool opened = ImGui::TreeNodeEx((void*)(uint64_t)(uint32_t)entity, flags, "%s", tag.c_str());
if (ImGui::BeginPopupContextItem()) {
if (ImGui::MenuItem("Delete entity"))
entity_marked_deletion = true;
if (ImGui::MenuItem("Delete entity")) {
scene->MarkEntityForDeletion(entity);
selected_context = {};
}
ImGui::EndPopup();
}
@@ -183,27 +226,23 @@ namespace OpenEngine {
if (opened)
ImGui::TreePop();
}
if (entity_marked_deletion) {
scene->DeleteEntity(entity);
if (selected_context == entity)
selected_context = {};
}
}
void SceneHierarchy::DrawComponents(Entity& entity)
{
auto& reg = scene->GetRegistry();
entt::entity handle = selected_context;
entt::entity handle = entity;
if (!selected_context || !entity)
if (!entity)
return;
entity.GetComponents<TagComponent>();
TagOnImGuiRender(reg, entity);
std::vector<entt::id_type> component_to_delete; // 0 is null/invalid in entt usually
// Iterate through every component type entt knows about
// TODO: Defer deletion like the entities?
std::vector<entt::id_type> pending_deletion; // 0 is null/invalid in entt usually
// Iterate through every component type entt knows about
for (auto [id, storage] : reg.storage()) {
if (storage.contains(handle)) {
if (drawers.contains(id)) {
@@ -226,20 +265,24 @@ namespace OpenEngine {
if (ImGui::BeginPopup("component_settings")) {
if (ImGui::MenuItem("Remove component"))
component_to_delete.emplace_back(id);
pending_deletion.emplace_back(id);
ImGui::EndPopup();
}
if (opened) {
ImGui::Spacing();
drawers[id].draw_func(reg, handle);
ImGui::Spacing();
ImGui::TreePop();
}
}
}
}
for (auto& id : component_to_delete)
for (auto& id : pending_deletion) {
drawers[id].remove_func(reg, entity);
pending_deletion.clear();
}
}
}

View File

@@ -10,38 +10,39 @@ Collapsed=0
[Window][Statistics]
Pos=0,24
Size=409,300
Size=409,437
Collapsed=0
DockId=0x00000003,0
[Window][Properties]
Pos=822,24
Size=450,739
Size=450,805
Collapsed=0
DockId=0x00000007,0
[Window][Viewport]
Pos=411,24
Size=409,1363
Pos=411,61
Size=409,956
Collapsed=0
DockId=0x00000009,0
DockId=0x00000012,0
[Window][Dear ImGui Demo]
Pos=822,765
Size=450,622
Pos=822,831
Size=450,556
Collapsed=0
DockId=0x00000008,0
[Window][Scene]
Pos=0,326
Size=409,1061
Pos=0,463
Size=409,924
Collapsed=0
DockId=0x00000004,0
[Window][Dear ImGui Style Editor]
Pos=60,60
Size=591,1380
Pos=1308,24
Size=800,1001
Collapsed=0
DockId=0x0000000E,0
[Window][Example: Console]
Pos=345,786
@@ -133,24 +134,50 @@ Collapsed=0
Pos=343,24
Size=1665,1371
Collapsed=0
DockId=0x00000009,1
DockId=0x00000012,1
[Window][Graph Editor]
Pos=343,24
Size=1665,1371
Collapsed=0
DockId=0x00000009,1
DockId=0x00000012,1
[Window][Assets]
Pos=411,1019
Size=409,368
Collapsed=0
DockId=0x0000000C,0
[Window][##play]
Pos=226,24
Size=594,60
Collapsed=0
DockId=0x0000000F,0
[Window][##play_state_bar]
Pos=411,24
Size=409,35
Collapsed=0
DockId=0x00000011,0
[Docking][Data]
DockSpace ID=0x08BD597D Window=0x1BBC0F80 Pos=0,24 Size=1272,1363 Split=X
DockNode ID=0x00000005 Parent=0x08BD597D SizeRef=820,1386 Split=X
DockNode ID=0x00000001 Parent=0x00000005 SizeRef=409,1386 Split=Y Selected=0xE601B12F
DockNode ID=0x00000003 Parent=0x00000001 SizeRef=255,300 Selected=0x553E127E
DockNode ID=0x00000004 Parent=0x00000001 SizeRef=255,1061 Selected=0xE601B12F
DockNode ID=0x00000002 Parent=0x00000005 SizeRef=1697,1386 Split=Y Selected=0xC450F867
DockNode ID=0x00000009 Parent=0x00000002 SizeRef=483,784 CentralNode=1 Selected=0xC450F867
DockNode ID=0x0000000A Parent=0x00000002 SizeRef=483,600 Selected=0x1BCA3180
DockNode ID=0x00000006 Parent=0x08BD597D SizeRef=450,1386 Split=Y Selected=0x8C72BEA8
DockNode ID=0x00000007 Parent=0x00000006 SizeRef=444,738 Selected=0x8C72BEA8
DockNode ID=0x00000008 Parent=0x00000006 SizeRef=444,622 Selected=0x5E5F7166
DockSpace ID=0x08BD597D Window=0x1BBC0F80 Pos=0,24 Size=1272,1363 Split=X
DockNode ID=0x00000005 Parent=0x08BD597D SizeRef=820,1386 Split=X
DockNode ID=0x00000001 Parent=0x00000005 SizeRef=409,1386 Split=Y Selected=0xE601B12F
DockNode ID=0x00000003 Parent=0x00000001 SizeRef=255,417 Selected=0x553E127E
DockNode ID=0x00000004 Parent=0x00000001 SizeRef=255,883 Selected=0xE601B12F
DockNode ID=0x00000002 Parent=0x00000005 SizeRef=409,1386 Split=Y Selected=0xC450F867
DockNode ID=0x00000009 Parent=0x00000002 SizeRef=483,784 Split=Y Selected=0xC450F867
DockNode ID=0x0000000B Parent=0x00000009 SizeRef=409,932 Split=X Selected=0xC450F867
DockNode ID=0x0000000D Parent=0x0000000B SizeRef=1080,993 Split=Y Selected=0xC450F867
DockNode ID=0x0000000F Parent=0x0000000D SizeRef=594,60 Selected=0x8325EBDA
DockNode ID=0x00000010 Parent=0x0000000D SizeRef=594,931 Split=Y Selected=0xC450F867
DockNode ID=0x00000011 Parent=0x00000010 SizeRef=594,35 HiddenTabBar=1 Selected=0xAB37695D
DockNode ID=0x00000012 Parent=0x00000010 SizeRef=594,964 CentralNode=1 Selected=0xC450F867
DockNode ID=0x0000000E Parent=0x0000000B SizeRef=800,993 Selected=0x3EEA4247
DockNode ID=0x0000000C Parent=0x00000009 SizeRef=409,368 Selected=0x42C24103
DockNode ID=0x0000000A Parent=0x00000002 SizeRef=483,600 Selected=0x1BCA3180
DockNode ID=0x00000006 Parent=0x08BD597D SizeRef=450,1386 Split=Y Selected=0x8C72BEA8
DockNode ID=0x00000007 Parent=0x00000006 SizeRef=444,805 Selected=0x8C72BEA8
DockNode ID=0x00000008 Parent=0x00000006 SizeRef=444,556 Selected=0x5E5F7166

View File

@@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.28)
cmake_minimum_required(VERSION 3.25.1)
set(CMAKE_CXX_STANDARD 23)
@@ -13,6 +13,8 @@ add_definitions( -DOE_ENABLE_ASSERTS )
find_package(imgui REQUIRED)
find_package(EnTT REQUIRED)
find_package(yaml-cpp REQUIRED)
find_package(Jolt REQUIRED)
find_package(fastgltf REQUIRED)
file(GLOB_RECURSE SRC_FILES "src/*.cpp")
file(GLOB IMGUIZMO_SRC_FILES "${CMAKE_SOURCE_DIR}/vendor/ImGuizmo/*.cpp")
@@ -52,6 +54,17 @@ target_link_libraries(${PROJECT_EXECUTABLE_NAME} PUBLIC
X11
yaml-cpp::yaml-cpp
nfd
shaderc_combined
glslang
glslang-default-resource-limits
SPIRV
SPIRV-Tools
SPIRV-Tools-opt
spirv-cross-core
spirv-cross-glsl
spirv-cross-reflect
Jolt::Jolt
fastgltf::fastgltf
)
#target_link_directories(${PROJECT_EXECUTABLE_NAME} PRIVATE
@@ -63,3 +76,5 @@ add_subdirectory(vendor/glad
)
add_subdirectory("vendor/nativefiledialog-extended")
target_compile_options(open_engine PRIVATE -msse4.1 -msse4.2 -mavx -mavx2)

View File

@@ -25,6 +25,7 @@
#include "open_engine/renderer/subtexture2d.hpp"
#include "open_engine/renderer/framebuffer.hpp"
#include "open_engine/renderer/renderer2d.hpp"
#include "open_engine/renderer/renderer3d.hpp"
#include "open_engine/renderer/renderer.hpp"
#include "open_engine/renderer/texture.hpp"
#include "open_engine/renderer/buffer.hpp"

View File

@@ -10,10 +10,25 @@
int main(int argc, char **argv);
namespace OpenEngine {
struct ApplicationCommandLineArgs
{
int count = 0;
char** args = nullptr;
const char* operator[](int index)
{
OE_CORE_ASSERT(index < count, "Index is higher than argument count.");
return args[index];
};
};
class Application
{
public:
Application(const std::string& name = "OpenEngine Project");
Application(const std::string& name,
ApplicationCommandLineArgs& args);
~Application();
virtual void OnEvent(Event& event);
@@ -25,6 +40,7 @@ namespace OpenEngine {
ImGuiLayer* GetImGuiLayer() { return imgui_layer.get(); };
inline static Application& Get() { return *instance; };
ApplicationCommandLineArgs GetCommandLineArgs() const { return arguments; };
inline Window& GetWindow() { return *window; };
@@ -36,6 +52,7 @@ namespace OpenEngine {
bool OnWindowResize(WindowResizeEvent& event);
private:
ApplicationCommandLineArgs arguments;
const std::string name;
std::unique_ptr<Window> window;
@@ -49,7 +66,7 @@ namespace OpenEngine {
};
// Is defined by client
Application* CreateApplication();
Application* CreateApplication(ApplicationCommandLineArgs args);
}
#endif // APPLICATION_HPP

View File

@@ -0,0 +1,36 @@
#ifndef UUID_HPP
#define UUID_HPP
#include <cstdint>
namespace OpenEngine {
class UUID
{
public:
UUID();
UUID(uint64_t uuid);
UUID(const UUID&) = default;
operator uint64_t() const { return uuid; };
private:
uint64_t uuid;
};
}
namespace std {
template<>
struct hash<OpenEngine::UUID>
{
std::size_t operator()(const OpenEngine::UUID& uuid) const
{
return hash<uint64_t>()((uint64_t)uuid);
}
};
}
#endif // UUID_HPP

View File

@@ -1,17 +1,16 @@
#ifndef ENTRY_POINT_HPP
#define ENTRY_POINT_HPP
#include "open_engine/core.hpp"
#include "open_engine/application.hpp"
#include "open_engine/logging.hpp"
extern OpenEngine::Application* OpenEngine::CreateApplication();
extern OpenEngine::Application* OpenEngine::CreateApplication(OpenEngine::ApplicationCommandLineArgs args);
int main(int argc, char** argv)
{
OE_PROFILE_BEGIN_SESSION("Startup", "open_engine-startup.json");
OpenEngine::Logger::Init();
auto app = OpenEngine::CreateApplication();
auto app = OpenEngine::CreateApplication({ argc, argv });
OE_PROFILE_END_SESSION();
OE_PROFILE_BEGIN_SESSION("Runtime", "open_engine-runtime.json");

View File

@@ -0,0 +1,13 @@
#ifndef FASTGLTF_HPP
#define FASTGLTF_HPP
#include "renderer/renderer3d.hpp"
#include "open_engine/ref_scope.hpp"
namespace OpenEngine {
Ref<Mesh> TestGLTF();
}
#endif // FASTGLTF_HPP

View File

@@ -0,0 +1,38 @@
#ifndef GLTF_MODEL3D_HPP
#define GLTF_MODEL3D_HPP
#include "open_engine/renderer/model3d.hpp"
#include <fastgltf/types.hpp>
#include <vector>
#include <cstddef>
namespace OpenEngine {
class GLTFModel3D : public Model3D
{
public:
GLTFModel3D(const char* path);
void loadPrimitive(fastgltf::Asset& asset,
fastgltf::Primitive& primitive,
Mesh& out);
virtual const Mesh& GetMesh(int index) const override;
virtual const std::vector<Mesh>& GetMeshes() const override;
virtual size_t GetMeshCount() const override { return meshes.size(); };
virtual std::vector<Mesh>::iterator begin() override { return meshes.begin(); };
virtual std::vector<Mesh>::iterator end() override { return meshes.end(); };
virtual std::vector<Mesh>::const_iterator begin() const override { return meshes.cbegin(); };
virtual std::vector<Mesh>::const_iterator end() const override { return meshes.end(); };
private:
std::string name;
std::vector<Mesh> meshes;
};
}
#endif // GLTF_MODEL3D_HPP

View File

@@ -19,6 +19,7 @@ namespace OpenEngine {
bool CloseWindow(OpenEngine::KeyPressedEvent& event);
void SetBlockEvents(bool block) { block_events = block; };
bool GetBlockEvents() { return block_events; };
void Begin();
void End();

View File

@@ -2,7 +2,6 @@
#define INPUT_HPP
#include "open_engine/input/mouse_codes.hpp"
#include "open_engine/ref_scope.hpp"
#include "open_engine/input/keycodes.hpp"
#include <string>

View File

@@ -29,13 +29,14 @@ namespace OpenEngine {
class OpenGLIndexBuffer : public IndexBuffer
{
public:
OpenGLIndexBuffer(uint32_t* indices, uint32_t count);
OpenGLIndexBuffer(const uint32_t* indices, uint32_t count);
virtual ~OpenGLIndexBuffer();
virtual void Bind() const override;
virtual void UnBind() const override;
virtual uint32_t GetCount() const override { return count; };
virtual uint32_t GetID() const override { return id; };
private:
unsigned int id;

View File

@@ -14,7 +14,7 @@ namespace OpenEngine {
public:
OpenGLShader(const std::string& shader_path);
OpenGLShader(const std::string& name, const std::string& vertex_src, const std::string& frament_src);
virtual ~OpenGLShader() = default;
virtual ~OpenGLShader();
virtual const std::string& GetName() const override { return name; };
@@ -44,11 +44,21 @@ namespace OpenEngine {
private:
std::string ReadFile(const std::string& shader_path);
std::unordered_map<GLenum, std::string> PreProcess(const std::string& shader_source);
void Compile(const std::unordered_map<GLenum, std::string> sources);
void CheckCompileErrors(unsigned int shader, const std::string& type);
void CompileOrGetVulkanBinaries(const std::unordered_map<GLenum, std::string>& shader_sources);
void CompileOrGetOpenGLBinaries();
void CreateProgram();
void Reflect(GLenum stage, const std::vector<uint32_t>& shader_data);
//void CheckCompileErrors(unsigned int shader, const std::string& type);
private:
std::string name;
std::string file_path;
std::unordered_map<GLenum, std::vector<uint32_t>> vulkan_spirv;
std::unordered_map<GLenum, std::vector<uint32_t>> opengl_spirv;
std::unordered_map<GLenum, std::string> m_OpenGLSourceCode;
u_int32_t id;
};

View File

@@ -0,0 +1,24 @@
#ifndef OPENGL_UNIFORM_BUFFER_HPP
#define OPENGL_UNIFORM_BUFFER_HPP
#include "open_engine/renderer/uniform_buffer.hpp"
#include <cstdint>
namespace OpenEngine {
class OpenGLUniformBuffer : public UniformBuffer
{
public:
OpenGLUniformBuffer(uint32_t size, uint32_t binding);
virtual ~OpenGLUniformBuffer();
virtual void SetData(const void* data, uint32_t size,
uint32_t offset = 0) override;
private:
uint32_t id = 0;
};
}
#endif // OPENGL_UNIFORM_BUFFER_HPP

View File

@@ -0,0 +1,191 @@
#ifndef PHYSICS_HPP
#define PHYSICS_HPP
#include "logging.hpp"
#include <Jolt/Jolt.h>
#include <Jolt/Physics/Body/BodyInterface.h>
#include <Jolt/RegisterTypes.h>
#include <Jolt/Core/Factory.h>
#include <Jolt/Core/TempAllocator.h>
#include <Jolt/Core/JobSystemThreadPool.h>
#include <Jolt/Physics/PhysicsSettings.h>
#include <Jolt/Physics/PhysicsSystem.h>
#include <Jolt/Physics/Collision/Shape/BoxShape.h>
#include <Jolt/Physics/Collision/Shape/SphereShape.h>
#include <Jolt/Physics/Body/BodyCreationSettings.h>
#include <Jolt/Physics/Body/BodyActivationListener.h>
#include <cstdarg>
#include <glm/glm.hpp>
using namespace JPH;
using namespace JPH::literals;
// Callback for traces, connect this to your own trace function if you have one
static void TraceImpl(const char *in_fmt, ...)
{
// Format the message
va_list list;
va_start(list, in_fmt);
char buffer[1024];
vsnprintf(buffer, sizeof(buffer), in_fmt, list);
va_end(list);
OE_CORE_TRACE("Jolt: {}", buffer);
}
#ifdef JPH_ENABLE_ASSERTS
// Callback for asserts, connect this to your own assert handler if you have one
static bool AssertFailedImpl(const char *in_expression, const char *in_message, const char *in_file, uint in_line)
{
OE_CORE_ERROR("Jolt: Assert in file: {}:{} :({}) {}", in_file, in_line, in_expression, (in_message != nullptr? in_message : ""));
// Breakpoint
return true;
};
#endif // JPH_ENABLE_ASSERTS
// Layer that objects can be in, determines which other objects it can collide with
// Typically you at least want to have 1 layer for moving bodies and 1 layer for static bodies, but you can have more
// layers if you want. E.g. you could have a layer for high detail collision (which is not used by the physics simulation
// but only if you do collision testing).
namespace Layers {
static constexpr ObjectLayer NON_MOVING = 0;
static constexpr ObjectLayer MOVING = 1;
static constexpr ObjectLayer NUM_LAYERS = 2;
};
class ObjectLayerPairFilterImpl : public ObjectLayerPairFilter
{
public:
virtual bool ShouldCollide(ObjectLayer object1, ObjectLayer object2) const override;
};
// Each broadphase layer results in a separate bounding volume tree in the broad phase. You at least want to have
// a layer for non-moving and moving objects to avoid having to update a tree full of static objects every frame.
// You can have a 1-on-1 mapping between object layers and broadphase layers (like in this case) but if you have
// many object layers you'll be creating many broad phase trees, which is not efficient. If you want to fine tune
// your broadphase layers define JPH_TRACK_BROADPHASE_STATS and look at the stats reported on the TTY.
namespace BroadPhaseLayers
{
static constexpr BroadPhaseLayer NON_MOVING(0);
static constexpr BroadPhaseLayer MOVING(1);
static constexpr uint NUM_LAYERS(2);
};
inline JPH::Vec3 ToJolt(const glm::vec3& v) { return JPH::Vec3(v.x, v.y, v.z); };
class BPLayerInterfaceImpl final : public BroadPhaseLayerInterface
{
public:
BPLayerInterfaceImpl()
{
object_to_broad_phase[Layers::NON_MOVING] = BroadPhaseLayers::NON_MOVING;
object_to_broad_phase[Layers::MOVING] = BroadPhaseLayers::MOVING;
}
virtual uint GetNumBroadPhaseLayers() const override { return BroadPhaseLayers::NUM_LAYERS; };
virtual BroadPhaseLayer GetBroadPhaseLayer(ObjectLayer layer) const override
{
JPH_ASSERT(layer < Layers::NUM_LAYERS);
return object_to_broad_phase[layer];
}
private:
BroadPhaseLayer object_to_broad_phase[Layers::NUM_LAYERS];
};
class ObjectVsBroadPhaseLayerFilterImpl : public ObjectVsBroadPhaseLayerFilter
{
public:
virtual bool ShouldCollide(ObjectLayer layer1, BroadPhaseLayer layer2) const override
{
switch (layer1)
{
case Layers::NON_MOVING:
return layer2 == BroadPhaseLayers::MOVING;
case Layers::MOVING:
return true;
default:
JPH_ASSERT(false);
return false;
}
}
};
// An example contact listener
class MyContactListener : public ContactListener
{
public:
// See: ContactListener
virtual ValidateResult OnContactValidate(const Body &inBody1, const Body &inBody2, RVec3Arg inBaseOffset, const CollideShapeResult &inCollisionResult) override
{
OE_CORE_TRACE("Jolt: Contact validate callback");
// Allows you to ignore a contact before it is created (using layers to not make objects collide is cheaper!)
return ValidateResult::AcceptAllContactsForThisBodyPair;
}
virtual void OnContactAdded(const Body &inBody1, const Body &inBody2, const ContactManifold &inManifold, ContactSettings &ioSettings) override
{
OE_CORE_TRACE("Jolt: A contact was added");
}
virtual void OnContactPersisted(const Body &inBody1, const Body &inBody2, const ContactManifold &inManifold, ContactSettings &ioSettings) override
{
OE_CORE_TRACE("Jolt: A contact was persisted");
}
virtual void OnContactRemoved(const SubShapeIDPair &inSubShapePair) override
{
OE_CORE_TRACE("Jolt: A contact was removed");
}
};
// An example activation listener
class MyBodyActivationListener : public BodyActivationListener
{
public:
virtual void OnBodyActivated(const BodyID &inBodyID, uint64 inBodyUserData) override
{
OE_CORE_TRACE("Jolt: A body got activated");
}
virtual void OnBodyDeactivated(const BodyID &inBodyID, uint64 inBodyUserData) override
{
OE_CORE_TRACE("Jolt: A body went to sleep");
}
};
namespace OpenEngine {
// Consider making this static like the renderer
class PhysicsEngine
{
public:
PhysicsEngine();
~PhysicsEngine();
// TODO: Temp, make abstract function to create a body
BodyInterface& GetBodyInterface() { return physics_system.GetBodyInterface(); };
void Update( float delta_time, int collision_steps);
private:
PhysicsSystem physics_system;
Ref<TempAllocatorImpl> tmp_allocator;
Ref<JobSystemThreadPool> job_system;
MyBodyActivationListener body_activation_listener;
MyContactListener contact_listener;
BPLayerInterfaceImpl broad_phase_layer_interface;
ObjectVsBroadPhaseLayerFilterImpl object_vs_broadphase_layer_filter;
ObjectLayerPairFilterImpl object_vs_object_layer_filter;
};
}
#endif // PHYSICS_HPP

View File

@@ -1,220 +0,0 @@
let SessionLoad = 1
let s:so_save = &g:so | let s:siso_save = &g:siso | setg so=0 siso=0 | setl so=-1 siso=-1
let v:this_session=expand("<sfile>:p")
silent only
silent tabonly
cd ~/projects/open_engine/open_engine
if expand('%') == '' && !&modified && line('$') <= 1 && getline(1) == ''
let s:wipebuf = bufnr('%')
endif
let s:shortmess_save = &shortmess
if &shortmess =~ 'A'
set shortmess=aoOA
else
set shortmess=aoO
endif
badd +1 ~/projects/open_engine/open_engine
badd +170 ~/projects/open_engine/open_engine/src/open_engine/imgui/imgui_layer.cpp
badd +4 ~/projects/open_engine/open_engine/include/open_engine/opengl/imgui_glfw.h
badd +35 ~/projects/open_engine/open_engine/include/open_engine/opengl/imgui_opengl.h
badd +23 ~/projects/open_engine/open_engine/src/open_engine/application.cpp
badd +47 ~/projects/open_engine/open_engine/CMakeLists.txt
badd +12 ~/projects/open_engine/open_engine/include/open_engine/imgui/imgui_layer.hpp
badd +123 ~/projects/open_engine/open_engine/src/open_engine/opengl/imgui_opengl.cpp
badd +89 ~/.conan2/p/b/imgui15e51a8fb5246/p/include/imgui.h
badd +7 ~/projects/open_engine/open_engine/.envrc
badd +5 ~/projects/open_engine/open_engine/include/open_engine/core.hpp
badd +11 ~/.conan2/p/b/imgui15e51a8fb5246/p/include/imgui_export_headers.h
badd +1 ~/projects/open_engine/open_engine/src/open_engine/opengl/build_opengl.cpp
badd +4 ~/projects/open_engine/open_engine/src/open_engine/opengl/imgui_build.cpp
badd +1 ~/projects/open_engine/open_engine/conanfile.txt
badd +1 ~/projects/open_engine/open_engine/build/imguiTargets.cmake
badd +8 ~/projects/open_engine/open_engine/include/open_engine/logging.hpp
badd +4 ~/projects/open_engine/open_engine/src/open_engine/logging.cpp
badd +110 ~/projects/open_engine/open_engine/src/open_engine/opengl/imgui_glfw.cpp
badd +1 ~/projects/open_engine/open_engine/include/open_engine/application.hpp
badd +21 ~/projects/open_engine/open_engine/src/open_engine/window/linux_window.cpp
badd +24 ~/projects/open_engine/open_engine/include/open_engine/window/window.hpp
badd +27 ~/projects/open_engine/open_engine/include/open_engine/window/linux_window.hpp
badd +7 ~/projects/open_engine/open_engine/include/open_engine/renderer/GraphicsContext.hpp
badd +12 ~/projects/open_engine/open_engine/include/open_engine/opengl/opengl_context.hpp
badd +10 ~/projects/open_engine/open_engine/src/open_engine/input/linux_input.cpp
badd +17 ~/projects/open_engine/open_engine/src/open_engine/opengl/opengl_context.cpp
badd +3295 ~/projects/open_engine/open_engine/vendor/glad/include/glad/glad.h
badd +148 ~/projects/open_engine/open_engine/vendor/glad/src/glad/glad.c
badd +13 ~/projects/open_engine/open_engine/include/open_engine/renderer/graphics_context.hpp
badd +80 ~/projects/open_engine/open_engine/src/open_engine/opengl/opengl_shader.cpp
badd +8 ~/projects/open_engine/open_engine/include/open_engine/opengl/opengl_shader.hpp
badd +8 ~/projects/open_engine/open_engine/include/open_engine/renderer/shader.hpp
badd +1 ~/projects/open_engine/open_engine/src/open_engine/renderer/shader.cpp
badd +1 ~/projects/open_engine/open_engine/include/open_engine/pch.hpp
badd +3 ~/projects/open_engine/open_engine/assets/shaders/fragment.frag.old
badd +1 ~/projects/open_engine/open_engine/assets/shaders/fragment.frag
badd +5 ~/projects/open_engine/open_engine/assets/shaders/vertex.vert
badd +1 ~/projects/open_engine/open_engine/\'
badd +66 ~/projects/open_engine/open_engine/include/open_engine/renderer/buffer.hpp
badd +56 ~/projects/open_engine/open_engine/src/open_engine/renderer/buffer.cpp
badd +18 ~/projects/open_engine/open_engine/include/open_engine/opengl/opengl_buffer.hpp
badd +34 ~/projects/open_engine/open_engine/src/open_engine/opengl/opengl_buffer.cpp
badd +2 ~/projects/open_engine/open_engine/src/open_engine/renderer/renderer.cpp
badd +5 ~/projects/open_engine/open_engine/include/open_engine/renderer/renderer.hpp
badd +1 ~/projects/open_engine/open_engine/src/open_engine/layer.cpp
badd +12 ~/projects/open_engine/open_engine/include/open_engine/layer.hpp
badd +21 ~/projects/open_engine/open_engine/include/open_engine/events/event.hpp
badd +11 ~/projects/open_engine/open_engine/src/open_engine/renderer/vertex_array.cpp
badd +8 ~/projects/open_engine/open_engine/include/open_engine/renderer/vertex_array.hpp
badd +27 ~/projects/open_engine/open_engine/src/open_engine/layer_stack.cpp
badd +1 ~/projects/open_engine/open_engine/include/open_engine/layer_stack.hpp
argglobal
%argdel
$argadd ~/projects/open_engine/open_engine
set stal=2
tabnew +setlocal\ bufhidden=wipe
tabrewind
edit ~/projects/open_engine/open_engine/include/open_engine/renderer/vertex_array.hpp
let s:save_splitbelow = &splitbelow
let s:save_splitright = &splitright
set splitbelow splitright
wincmd _ | wincmd |
vsplit
1wincmd h
wincmd w
let &splitbelow = s:save_splitbelow
let &splitright = s:save_splitright
wincmd t
let s:save_winminheight = &winminheight
let s:save_winminwidth = &winminwidth
set winminheight=0
set winheight=1
set winminwidth=0
set winwidth=1
exe 'vert 1resize ' . ((&columns * 127 + 127) / 255)
exe 'vert 2resize ' . ((&columns * 127 + 127) / 255)
argglobal
setlocal foldmethod=manual
setlocal foldexpr=0
setlocal foldmarker={{{,}}}
setlocal foldignore=#
setlocal foldlevel=0
setlocal foldminlines=1
setlocal foldnestmax=20
setlocal foldenable
silent! normal! zE
let &fdl = &fdl
let s:l = 8 - ((7 * winheight(0) + 13) / 27)
if s:l < 1 | let s:l = 1 | endif
keepjumps exe s:l
normal! zt
keepjumps 8
normal! 0
lcd ~/projects/open_engine/open_engine
wincmd w
argglobal
if bufexists(fnamemodify("~/projects/open_engine/open_engine/include/open_engine/renderer/vertex_array.hpp", ":p")) | buffer ~/projects/open_engine/open_engine/include/open_engine/renderer/vertex_array.hpp | else | edit ~/projects/open_engine/open_engine/include/open_engine/renderer/vertex_array.hpp | endif
if &buftype ==# 'terminal'
silent file ~/projects/open_engine/open_engine/include/open_engine/renderer/vertex_array.hpp
endif
setlocal foldmethod=manual
setlocal foldexpr=0
setlocal foldmarker={{{,}}}
setlocal foldignore=#
setlocal foldlevel=0
setlocal foldminlines=1
setlocal foldnestmax=20
setlocal foldenable
silent! normal! zE
let &fdl = &fdl
let s:l = 1 - ((0 * winheight(0) + 13) / 27)
if s:l < 1 | let s:l = 1 | endif
keepjumps exe s:l
normal! zt
keepjumps 1
normal! 0
lcd ~/projects/open_engine/open_engine
wincmd w
exe 'vert 1resize ' . ((&columns * 127 + 127) / 255)
exe 'vert 2resize ' . ((&columns * 127 + 127) / 255)
tabnext
edit ~/projects/open_engine/open_engine/assets/shaders/fragment.frag
let s:save_splitbelow = &splitbelow
let s:save_splitright = &splitright
set splitbelow splitright
wincmd _ | wincmd |
vsplit
1wincmd h
wincmd w
let &splitbelow = s:save_splitbelow
let &splitright = s:save_splitright
wincmd t
let s:save_winminheight = &winminheight
let s:save_winminwidth = &winminwidth
set winminheight=0
set winheight=1
set winminwidth=0
set winwidth=1
exe 'vert 1resize ' . ((&columns * 254 + 127) / 255)
exe 'vert 2resize ' . ((&columns * 0 + 127) / 255)
argglobal
setlocal foldmethod=manual
setlocal foldexpr=0
setlocal foldmarker={{{,}}}
setlocal foldignore=#
setlocal foldlevel=0
setlocal foldminlines=1
setlocal foldnestmax=20
setlocal foldenable
silent! normal! zE
let &fdl = &fdl
let s:l = 11 - ((8 * winheight(0) + 13) / 27)
if s:l < 1 | let s:l = 1 | endif
keepjumps exe s:l
normal! zt
keepjumps 11
normal! 020|
lcd ~/projects/open_engine/open_engine
wincmd w
argglobal
if bufexists(fnamemodify("~/projects/open_engine/open_engine/assets/shaders/vertex.vert", ":p")) | buffer ~/projects/open_engine/open_engine/assets/shaders/vertex.vert | else | edit ~/projects/open_engine/open_engine/assets/shaders/vertex.vert | endif
if &buftype ==# 'terminal'
silent file ~/projects/open_engine/open_engine/assets/shaders/vertex.vert
endif
balt ~/projects/open_engine/open_engine/assets/shaders/fragment.frag
setlocal foldmethod=manual
setlocal foldexpr=0
setlocal foldmarker={{{,}}}
setlocal foldignore=#
setlocal foldlevel=0
setlocal foldminlines=1
setlocal foldnestmax=20
setlocal foldenable
silent! normal! zE
let &fdl = &fdl
let s:l = 12 - ((11 * winheight(0) + 13) / 27)
if s:l < 1 | let s:l = 1 | endif
keepjumps exe s:l
normal! zt
keepjumps 12
normal! 022|
lcd ~/projects/open_engine/open_engine
wincmd w
exe 'vert 1resize ' . ((&columns * 254 + 127) / 255)
exe 'vert 2resize ' . ((&columns * 0 + 127) / 255)
tabnext 1
set stal=1
if exists('s:wipebuf') && len(win_findbuf(s:wipebuf)) == 0 && getbufvar(s:wipebuf, '&buftype') isnot# 'terminal'
silent exe 'bwipe ' . s:wipebuf
endif
unlet! s:wipebuf
set winheight=1 winwidth=20
let &shortmess = s:shortmess_save
let &winminheight = s:save_winminheight
let &winminwidth = s:save_winminwidth
let s:sx = expand("<sfile>:p:r")."x.vim"
if filereadable(s:sx)
exe "source " . fnameescape(s:sx)
endif
let &g:so = s:so_save | let &g:siso = s:siso_save
set hlsearch
doautoall SessionLoadPost
unlet SessionLoad
" vim: set ft=vim :

View File

@@ -1,6 +1,8 @@
#ifndef BUFFER_HPP
#define BUFFER_HPP
#include "open_engine/ref_scope.hpp"
#include <cstdint>
#include <vector>
#include <string>
@@ -82,8 +84,9 @@ namespace OpenEngine {
virtual void UnBind() const = 0;
virtual uint32_t GetCount() const = 0;
virtual uint32_t GetID() const = 0;
static Ref<IndexBuffer> Create(uint32_t* indices, uint32_t count);
static Ref<IndexBuffer> Create(const uint32_t* indices, uint32_t count);
};
}

View File

@@ -31,6 +31,7 @@ namespace OpenEngine {
glm::vec3 GetForwardDirection() const;
const glm::vec3& GetPosition() const { return position; }
glm::quat GetOrientation() const;
void ResetMousePosition();
float GetPitch() const { return pitch; }
float GetYaw() const { return yaw; }
@@ -61,6 +62,7 @@ namespace OpenEngine {
glm::vec3 focal_point = { 0.0f, 0.0f, 0.0f };
glm::vec2 initial_mouse_position = { 0.0f, 0.0f };
bool mouse_button_was_pressed = false;
float distance = 10.0f;
float pitch = 0.0f, yaw = 0.0f;

View File

@@ -0,0 +1,69 @@
#ifndef MODEL3D_HPP
#define MODEL3D_HPP
#include "open_engine/core/uuid.hpp"
#include "open_engine/renderer/vertex_array.hpp"
#include <cstddef>
#include <cstdint>
#include <glm/glm.hpp>
#include <vector>
namespace OpenEngine {
struct Material
{
glm::vec4 albedo = { 1.0f, 0.0f, 0.8f, 1.0f };
float roughness = 1.0f;
float metallic = 1.0f;
float ambient_strength = 1.0f;
float specular_strength = 1.0f;
std::string name = "un-named material";
};
struct MeshVertex
{
glm::vec3 position;
glm::vec3 normal;
glm::vec2 text_coords;
};
struct Mesh
{
UUID uuid;
Material material;
Ref<VertexArray> vertex_array;
Ref<VertexBuffer> vertex_buffer;
Ref<IndexBuffer> index_buffer;
// TODO: Make them a ptr or something
std::vector<MeshVertex> vertices;
std::vector<uint32_t> indices;
};
// TODO: Model3D.Instanciate();
// Or Model3D.GetVertices() {return iterateaccessorwithindex bla bla bla}
// What data should Model3D hold in the end if it is not a renderable object?
class Model3D
{
public:
virtual ~Model3D() = default;
static Ref<Model3D> Create(const char* path);
virtual const Mesh& GetMesh(int index) const = 0;
virtual const std::vector<Mesh>& GetMeshes() const = 0;
virtual size_t GetMeshCount() const = 0;
virtual std::vector<Mesh>::iterator begin() = 0;
virtual std::vector<Mesh>::iterator end() = 0;
virtual std::vector<Mesh>::const_iterator begin() const = 0;
virtual std::vector<Mesh>::const_iterator end() const = 0;
};
}
#endif // MODEL3D_HPP

View File

@@ -44,6 +44,9 @@ namespace OpenEngine {
static void DrawQuad(const Transform& transform_data,
const Ref<Texture2D>& texture, int entity_id,
float tiling_factor = 1.0f);
static void DrawQuad(const Transform& transform_data,
const Ref<Texture2D>& texture, const glm::vec4& color,
int entity_id, float tiling_factor = 1.0f);
static void DrawQuad(const Transform& transform_data,
const Ref<Subtexture2D>& subtexture, int entity_id,
float tiling_factor = 1.0f);
@@ -53,6 +56,9 @@ namespace OpenEngine {
static void DrawQuad(const glm::mat4& transform,
const Ref<Texture2D>& texture, int entity_id,
float tiling_factor = 1.0f);
static void DrawQuad(const glm::mat4& transform,
const Ref<Texture2D>& texture, const glm::vec4& color,
int entity_id, float tiling_factor = 1.0f);
static void DrawQuad(const glm::mat4& transform,
const Ref<Subtexture2D>& subtexture, int entity_id,
float tiling_factor = 1.0f);

View File

@@ -0,0 +1,49 @@
#ifndef RENDERER3D_HPP
#define RENDERER3D_HPP
#include "open_engine/renderer/editor_camera.hpp"
#include "open_engine/scene/scene_camera.hpp"
#include "open_engine/renderer/model3d.hpp"
#include <cstdint>
namespace OpenEngine {
// SHOULD BE MOVED ==================================
enum class PrimitiveType
{
None = 0,
Quad,
Cube
};
Ref<Mesh> CreateMesh(const std::vector<MeshVertex>& vertices,
const std::vector<uint32_t>& indices);
void PopulateMesh(Mesh& mesh);
Ref<Mesh> CreateCube(uint32_t id = -1);
Ref<Mesh> CreateQuad(uint32_t id = -1, bool back_face = false);
// ==================================================
class Renderer3D
{
public:
static void Init();
static void Shutdown();
static void BeginScene(const SceneCamera& camera, const glm::mat4& transform);
static void BeginScene(const EditorCamera& camera);
static void EndScene();
static void DrawMesh(const Ref<Mesh>& mesh, Material& material,
const glm::mat4& transform);
static void DrawMesh(const Ref<Mesh>& mesh, Material& material,
const glm::mat4& transform,
uint32_t entity_id);
static void DrawModel(const Ref<Model3D>& model,
const glm::mat4& transform,
uint32_t entity_id);
};
}
#endif // RENDERER3D_HPP

View File

@@ -0,0 +1,20 @@
#ifndef UNIFORM_BUFFER_HPP
#define UNIFORM_BUFFER_HPP
#include <cstdint>
#include <glm/fwd.hpp>
namespace OpenEngine {
class UniformBuffer
{
public:
virtual ~UniformBuffer() = default;
virtual void SetData(const void* data, uint32_t size,
uint32_t offset = 0) = 0;
static Ref<UniformBuffer> Create(uint32_t size, uint32_t binding);
};
}
#endif // UNIFORM_BUFFER_HPP

View File

@@ -2,6 +2,7 @@
#define VERTEX_ARRAY_HPP
#include "open_engine/renderer/buffer.hpp"
#include "open_engine/ref_scope.hpp"
#include <vector>

View File

@@ -1,9 +1,21 @@
#ifndef COMPONENTS_HPP
#define COMPONENTS_HPP
#include "open_engine/scene/native_scriptable_entity.hpp"
#include "open_engine/renderer/renderer3d.hpp"
#include "open_engine/scene/scene_camera.hpp"
#include "open_engine/renderer/texture.hpp"
#include "open_engine/renderer/renderer3d.hpp"
#include "open_engine/physics.hpp"
#include "open_engine/core/uuid.hpp"
#include "open_engine/ref_scope.hpp"
#include "open_engine/renderer/model3d.hpp"
#include <Jolt/Physics/Body/BodyCreationSettings.h>
#include <Jolt/Physics/Body/BodyInterface.h>
#include <Jolt/Physics/Body/MotionType.h>
#include <Jolt/Physics/Collision/ObjectLayer.h>
#include <Jolt/Physics/Collision/Shape/Shape.h>
#include <Jolt/Physics/EActivation.h>
#include <glm/ext/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <glm/fwd.hpp>
@@ -18,6 +30,15 @@
namespace OpenEngine {
struct IDComponent
{
UUID id;
IDComponent() = default;
IDComponent(const IDComponent&) = default;
IDComponent(const UUID& uuid) : id(uuid) {};
};
struct TagComponent
{
std::string tag;
@@ -45,6 +66,8 @@ namespace OpenEngine {
struct SpriteRendererComponent
{
glm::vec4 color{ 1.0f, 1.0f, 1.0f, 1.0f };
Ref<Texture2D> texture;
float tiling_factor = 1.0f;
SpriteRendererComponent() = default;
SpriteRendererComponent(const SpriteRendererComponent&) = default;
@@ -62,6 +85,8 @@ namespace OpenEngine {
CameraComponent(const CameraComponent&) = default;
};
class NativeScriptableEntity;
struct NativeScriptComponent
{
NativeScriptableEntity* instance = nullptr;
@@ -69,9 +94,6 @@ namespace OpenEngine {
NativeScriptableEntity* (*InstanciateScript)();
void (*DestroyInstanceScript)(NativeScriptComponent*);
void OnImGuiRender(Entity& entity)
{};
template <typename T>
void Bind()
{
@@ -81,9 +103,83 @@ namespace OpenEngine {
(delete nsc->instance);
nsc->instance = nullptr;
};
}
};
};
struct MeshComponent
{
Ref<Mesh> mesh;
PrimitiveType primitive_type = PrimitiveType::None;
MeshComponent() = default;
MeshComponent(const MeshComponent&) = default;
MeshComponent(const Ref<Mesh>& mesh)
: mesh(mesh) {};
};
struct MaterialComponent
{
Material material;
MaterialComponent() = default;
MaterialComponent(const MaterialComponent&) = default;
MaterialComponent(const Material& material)
: material(material) {};
};
struct PhysicsBodyComponent
{
BodyID body;
float linear_damping = 0.05f;
float angular_damping = 0.05f;
float gravity_factor = 1.0f;
float restitution = 0.8f;
float friction = 0.5f;
int type = (int)EMotionType::Static;
int initial_activation_state = (int)EActivation::Activate;
int layer = (int)Layers::MOVING;
PhysicsBodyComponent() = default;
PhysicsBodyComponent(const PhysicsBodyComponent&) = default;
};
// TODO: Let's add more shapes
struct BoxShapeComponent
{
glm::vec3 size = { 1.0f, 1.0f, 1.0f };
BoxShapeComponent() = default;
BoxShapeComponent(const BoxShapeComponent&) = default;
};
struct SphereShapeComponent
{
float radius = 1.0f;
SphereShapeComponent() = default;
SphereShapeComponent(const SphereShapeComponent&) = default;
};
struct PlaneShapeComponent
{
float extent = 1.0f;
PlaneShapeComponent() = default;
PlaneShapeComponent(const PlaneShapeComponent&) = default;
};
struct ModelComponent
{
Ref<Model3D> model;
ModelComponent() = default;
ModelComponent(const ModelComponent&) = default;
ModelComponent(Ref<Model3D>& model)
: model(model)
{}
};
}
#endif // COMPONENTS_HPP

View File

@@ -3,6 +3,8 @@
#include "open_engine/core.hpp"
#include "open_engine/core/uuid.hpp"
#include "open_engine/scene/components.hpp"
#include "open_engine/scene/scene.hpp"
#include <cstdint>
@@ -19,10 +21,13 @@ namespace OpenEngine {
Entity(const Entity& other) = default;
template<typename T, typename ... Args>
T& AddComponents(Args&&... args)
T& AddComponent(Args&&... args)
{
OE_ASSERT(!HasComponent<T>(), "Entity already has component.");
return scene->registry.emplace<T>(handle, std::forward<Args>(args)...);
T& component = scene->registry.emplace<T>(handle, std::forward<Args>(args)...);
scene->OnComponentAdded(*this, component);
return component;
};
template<typename T, typename ... Args>
@@ -45,6 +50,8 @@ namespace OpenEngine {
return scene->registry.all_of<T>(handle);
};
UUID GetUUID() { return GetComponents<IDComponent>().id; };
operator bool() const { return handle != entt::null; };
operator entt::entity() const { return handle; };
operator uint32_t() const { return (uint32_t)handle; };

View File

@@ -1,6 +1,7 @@
#ifndef NATIVE_SCRIPTABLE_ENTITY_HPP
#define NATIVE_SCRIPTABLE_ENTITY_HPP
#include "open_engine/scene/native_scriptable_entity.hpp"
#include "open_engine/scene/entity.hpp"
namespace OpenEngine {

View File

@@ -1,8 +1,12 @@
#ifndef SCENE_HPP
#define SCENE_HPP
#include "open_engine/core/uuid.hpp"
#include "open_engine/renderer/editor_camera.hpp"
#include "open_engine/physics.hpp"
#include <Jolt/Physics/Body/BodyInterface.h>
#include <entt/entity/fwd.hpp>
#include <entt/entt.hpp>
#include <cstdint>
@@ -13,25 +17,44 @@ namespace OpenEngine {
class Scene
{
public:
Scene() {};
Scene() = default;
~Scene() = default;
Scene(Scene& other) {};
void OnRuntimeStart();
void OnRuntimeStop();
Entity CreateEntity(const std::string& name = std::string());
void DeleteEntity(Entity entity);
Entity CreateEntityWithUUID(UUID uuid, const std::string& name = std::string());
void DeleteEntity(entt::entity entity);
void MarkEntityForDeletion(Entity entity);
void UpdateEntities();
void OnUpdateRuntime();
void OnUpdateEditor(EditorCamera& camera);
void OnViewportResize(uint32_t width, uint32_t height);
entt::registry& GetRegistry() { return registry; };
PhysicsEngine& GetPhysicsEngine() { return physics_engine; };
Entity GetPrimaryCamera();
private:
void OnUpdatePhysics();
template<typename T>
void OnComponentAdded(Entity entity, T& component);
private:
entt::registry registry;
PhysicsEngine physics_engine;
BodyInterface* body_interface;
uint32_t viewport_width = 0, viewport_height = 0;
std::vector<entt::entity> pending_deletion;
friend class SceneSerializer;
friend class Entity;
};

View File

@@ -4,6 +4,7 @@
#include <core.hpp>
#include <events/application_event.hpp>
#include <renderer/renderer3d.hpp>
#include <renderer/renderer2d.hpp>
#include <input/input_system.hpp>
#include <imgui/imgui_layer.hpp>
@@ -13,8 +14,9 @@
#include <imgui.h>
namespace OpenEngine {
Application::Application(const std::string& name)
: name(name)
Application::Application(const std::string& name,
ApplicationCommandLineArgs& args)
: name(name), arguments(args)
{
OE_PROFILE_FUNCTION();
@@ -27,7 +29,8 @@ namespace OpenEngine {
{
OE_PROFILE_SCOPE("Initializing Renderers");
Renderer::Init();
Renderer2D::Init();
//Renderer2D::Init();
Renderer3D::Init();
}
imgui_layer = std::make_shared<ImGuiLayer>();
@@ -38,7 +41,8 @@ namespace OpenEngine {
Application::~Application()
{
OpenEngine::Renderer2D::Shutdown();
//OpenEngine::Renderer2D::Shutdown();
Renderer3D::Shutdown();
}
void Application::Run()

View File

@@ -0,0 +1,24 @@
#include <cstdint>
#include <pch.hpp>
#include <core/uuid.hpp>
#include <random>
namespace OpenEngine {
static std::random_device s_random_device;
static std::mt19937_64 s_engine(s_random_device());
static std::uniform_int_distribution<uint64_t> s_uniform_distribution;
UUID::UUID()
: uuid(s_uniform_distribution(s_engine))
{
}
UUID::UUID(uint64_t uuid)
: uuid(uuid)
{
}
}

View File

@@ -0,0 +1,86 @@
#include <pch.hpp>
#include "logging.hpp"
#include <fastgltf.hpp>
#include "ref_scope.hpp"
#include <cstddef>
#include <cstdint>
#include <glm/fwd.hpp>
#include <fastgltf/core.hpp>
#include <fastgltf/types.hpp>
#include <fastgltf/tools.hpp>
#include <fastgltf/glm_element_traits.hpp>
#include <vector>
namespace OpenEngine {
void loadPrimitive(fastgltf::Asset& asset,
fastgltf::Primitive& primitive,
Mesh& out)
{
if (primitive.indicesAccessor.has_value()) {
auto& accessor = asset.accessors[primitive.indicesAccessor.value()];
out.indices.resize(accessor.count);
fastgltf::iterateAccessorWithIndex<uint32_t>(asset, accessor,
[&](uint32_t index, size_t i) {
out.indices[i] = index;
});
}
{
auto* position_iterator = primitive.findAttribute("POSITION");
auto& accessor = asset.accessors[position_iterator->accessorIndex];
out.vertices.resize(accessor.count);
fastgltf::iterateAccessorWithIndex<glm::vec3>(asset, accessor,
[&](glm::vec3 pos, size_t i) {
out.vertices[i].position = pos;
});
}
if (auto* normal_iterator = primitive.findAttribute("NORMAL");
normal_iterator != primitive.attributes.end()) {
auto& accessor = asset.accessors[normal_iterator->accessorIndex];
fastgltf::iterateAccessorWithIndex<glm::vec3>(asset, accessor,
[&](glm::vec3 norm, size_t i) {
out.vertices[i].normal = norm;
});
}
{
if (primitive.materialIndex.has_value()) {
auto& material = asset.materials[primitive.materialIndex.value()];
auto& pbr = material.pbrData;
auto& c = pbr.baseColorFactor;
}
}
}
Ref<Mesh> TestGLTF()
{
fastgltf::Parser parser;
Ref<Mesh> new_mesh = CreateRef<Mesh>();
auto data = fastgltf::GltfDataBuffer::FromPath("assets/models/cube.glb");
if (data.error() != fastgltf::Error::None)
OE_CORE_ERROR("Could not parse model");
auto asset = parser.loadGltfBinary(data.get(), ".",
fastgltf::Options::LoadExternalBuffers
);
if (asset.error() != fastgltf::Error::None)
OE_CORE_ERROR("Could not optain asset");
for (auto& mesh : asset->meshes)
for (auto& primitive : mesh.primitives)
loadPrimitive(asset.get(), primitive, *new_mesh);
return new_mesh;
}
}

View File

@@ -0,0 +1,137 @@
#include "logging.hpp"
#include <pch.hpp>
#include <gltf/gltf_model3d.hpp>
#include <fastgltf/core.hpp>
#include <fastgltf/types.hpp>
#include <fastgltf/tools.hpp>
#include <fastgltf/glm_element_traits.hpp>
namespace OpenEngine {
void PopulateMesh(Mesh& mesh)
{
mesh.vertex_array = VertexArray::Create();
mesh.vertex_buffer = VertexBuffer::Create(mesh.vertices.size() * sizeof(MeshVertex));
mesh.vertex_buffer->SetData(mesh.vertices.data(), mesh.vertices.size() * sizeof(MeshVertex));
BufferLayout layout = {
{ ShaderDataType::Float3, "a_Position" },
{ ShaderDataType::Float3, "a_Normal" },
{ ShaderDataType::Float2, "a_TexCoord" }
};
mesh.vertex_buffer->SetLayout(layout);
mesh.vertex_array->AddVertexBuffer(mesh.vertex_buffer);
mesh.index_buffer = IndexBuffer::Create(mesh.indices.data(), mesh.indices.size());
mesh.vertex_array->SetIndexBuffer(mesh.index_buffer);
}
Ref<Mesh> CreateMesh(const std::vector<MeshVertex>& vertices,
const std::vector<uint32_t>& indices)
{
Ref<Mesh> mesh = CreateRef<Mesh>();
mesh->vertices = vertices;
mesh->indices = indices;
PopulateMesh(*mesh);
return mesh;
}
void GLTFModel3D::loadPrimitive(fastgltf::Asset& asset,
fastgltf::Primitive& primitive,
Mesh& out)
{
if (primitive.indicesAccessor.has_value()) {
auto& accessor = asset.accessors[primitive.indicesAccessor.value()];
out.indices.resize(accessor.count);
fastgltf::iterateAccessorWithIndex<uint32_t>(asset, accessor,
[&](uint32_t index, size_t i) {
out.indices[i] = index;
});
}
{
auto* position_iterator = primitive.findAttribute("POSITION");
auto& accessor = asset.accessors[position_iterator->accessorIndex];
out.vertices.resize(accessor.count);
fastgltf::iterateAccessorWithIndex<glm::vec3>(asset, accessor,
[&](glm::vec3 pos, size_t i) {
out.vertices[i].position = pos;
});
}
if (auto* normal_iterator = primitive.findAttribute("NORMAL");
normal_iterator != primitive.attributes.end()) {
auto& accessor = asset.accessors[normal_iterator->accessorIndex];
fastgltf::iterateAccessorWithIndex<glm::vec3>(asset, accessor,
[&](glm::vec3 norm, size_t i) {
out.vertices[i].normal = norm;
});
}
{
if (primitive.materialIndex.has_value()) {
auto& material = asset.materials[primitive.materialIndex.value()];
auto& pbr = material.pbrData;
auto& color = pbr.baseColorFactor;
auto& roughness = pbr.roughnessFactor;
auto& metallic = pbr.metallicFactor;
out.material.name = material.name;
out.material.albedo = glm::vec4(color[0], color[1], color[2], color[3]);
out.material.roughness = roughness;
out.material.metallic = metallic;
}
}
}
GLTFModel3D::GLTFModel3D(const char* path)
{
fastgltf::Parser parser;
auto data = fastgltf::GltfDataBuffer::FromPath(path);
if (data.error() != fastgltf::Error::None)
OE_CORE_ERROR("Could not parse model");
auto asset = parser.loadGltfBinary(data.get(), ".",
fastgltf::Options::LoadExternalBuffers
);
if (asset.error() != fastgltf::Error::None)
OE_CORE_ERROR("Could not optain asset");
for (auto& mesh : asset->meshes) {
name = mesh.name;
for (auto& primitive : mesh.primitives) {
Mesh prim_mesh;
loadPrimitive(asset.get(), primitive, prim_mesh);
PopulateMesh(prim_mesh);
meshes.emplace_back(prim_mesh);
}
}
};
const Mesh& GLTFModel3D::GetMesh(int index) const
{
return meshes[index];
}
const std::vector<Mesh>& GLTFModel3D::GetMeshes() const
{
return meshes;
}
}

View File

@@ -52,7 +52,7 @@ namespace OpenEngine {
// Index Buffer =====================================================
// ==================================================================
OpenGLIndexBuffer::OpenGLIndexBuffer(uint32_t* indices, uint32_t count)
OpenGLIndexBuffer::OpenGLIndexBuffer(const uint32_t* indices, uint32_t count)
: count(count)
{
OE_PROFILE_FUNCTION();
@@ -68,7 +68,7 @@ namespace OpenEngine {
void OpenGLIndexBuffer::Bind() const
{
glBindBuffer(GL_ARRAY_BUFFER, id);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, id);
}
void OpenGLIndexBuffer::UnBind() const
{

View File

@@ -45,6 +45,7 @@ namespace OpenEngine {
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
}
void OpenGLRendererAPI::SetViewport(uint32_t x, uint32_t y, uint32_t width, uint32_t height)
@@ -66,6 +67,9 @@ namespace OpenEngine {
{
OE_PROFILE_FUNCTION();
OE_CORE_ASSERT(vertex_array, "VertexArray is null!");
OE_CORE_ASSERT(vertex_array->GetIndexBuffer(), "IndexBuffer is null!");
uint32_t count = index_count? index_count : vertex_array->GetIndexBuffer()->GetCount();
glDrawElements(GL_TRIANGLES, count, GL_UNSIGNED_INT, nullptr);
glBindTexture(GL_TEXTURE_2D, 0);

View File

@@ -1,28 +1,117 @@
#include <pch.hpp>
#include <opengl/opengl_shader.hpp>
#include <core.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <opengl/opengl_shader.hpp>
#include <instrumentor.hpp>
#include <core/time.hpp>
#include <logging.hpp>
#include <glm/glm.hpp>
#include <shaderc/shaderc.hpp>
#include <spirv_cross/spirv_cross.hpp>
#include <spirv_cross/spirv_glsl.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <glm/glm.hpp>
#include <filesystem>
#include <glad/glad.h>
#include <alloca.h>
#include <cstddef>
#include <fstream>
//#include <alloca.h>
namespace OpenEngine {
static GLenum ShaderTypeFromString(const std::string& type)
namespace Utils {
static GLenum ShaderTypeFromString(const std::string& type)
{
if (type == "vertex")
return GL_VERTEX_SHADER;
if (type == "fragment" || type == "pixel")
return GL_FRAGMENT_SHADER;
OE_CORE_ASSERT(false, "Unknown shader type!");
return 0;
}
static shaderc_shader_kind GLShaderStageToShaderC(GLenum stage)
{
switch (stage)
{
case GL_VERTEX_SHADER: return shaderc_glsl_vertex_shader;
case GL_FRAGMENT_SHADER: return shaderc_glsl_fragment_shader;
}
OE_CORE_ASSERT(false, "No");
return (shaderc_shader_kind)0;
}
static const char* GLShaderStageToString(GLenum stage)
{
switch (stage)
{
case GL_VERTEX_SHADER: return "GL_VERTEX_SHADER";
case GL_FRAGMENT_SHADER: return "GL_FRAGMENT_SHADER";
}
OE_CORE_ASSERT(false, "No");
return nullptr;
}
static const char* GetCacheDirectory()
{
// TODO: make sure the assets directory is valid
return "assets/cache/shader/opengl";
}
static void CreateCacheDirectoryIfNeeded()
{
std::string cache_directory = GetCacheDirectory();
if (!std::filesystem::exists(cache_directory))
std::filesystem::create_directories(cache_directory);
}
static const char* GLShaderStageCachedOpenGLFileExtension(uint32_t stage)
{
switch (stage)
{
case GL_VERTEX_SHADER: return ".cached_opengl.vert";
case GL_FRAGMENT_SHADER: return ".cached_opengl.frag";
}
OE_CORE_ASSERT(false, "No");
return "";
}
static const char* GLShaderStageCachedVulkanFileExtension(uint32_t stage)
{
switch (stage)
{
case GL_VERTEX_SHADER: return ".cached_vulkan.vert";
case GL_FRAGMENT_SHADER: return ".cached_vulkan.frag";
}
OE_CORE_ASSERT(false, "No");
return "";
}
}
OpenGLShader::OpenGLShader(const std::string& filepath)
: file_path(filepath)
{
if (type == "vertex")
return GL_VERTEX_SHADER;
if (type == "fragment" || type == "pixel")
return GL_FRAGMENT_SHADER;
OE_PROFILE_FUNCTION();
OE_CORE_ERROR("Could not compile shader! Unkown shader type: {}", type);
Utils::CreateCacheDirectoryIfNeeded();
return 0;
std::string source = ReadFile(filepath);
auto shader_sources = PreProcess(source);
{
CompileOrGetVulkanBinaries(shader_sources);
CompileOrGetOpenGLBinaries();
CreateProgram();
}
// Extract name from filepath
auto last_slash = filepath.find_last_of("/\\");
last_slash = last_slash == std::string::npos ? 0 : last_slash + 1;
auto lastDot = filepath.rfind('.');
auto count = lastDot == std::string::npos ? filepath.size() - last_slash : lastDot - last_slash;
name = filepath.substr(last_slash, count);
}
OpenGLShader::OpenGLShader(const std::string& name, const std::string& vertex_src, const std::string& fragment_src)
@@ -34,163 +123,263 @@ namespace OpenEngine {
sources[GL_VERTEX_SHADER] = vertex_src;
sources[GL_FRAGMENT_SHADER] = fragment_src;
Compile(sources);
CompileOrGetVulkanBinaries(sources);
CompileOrGetOpenGLBinaries();
CreateProgram();
}
OpenGLShader::OpenGLShader(const std::string& shader_path)
OpenGLShader::~OpenGLShader()
{
OE_PROFILE_FUNCTION();
{
OE_PROFILE_SCOPE("Compiling Shader");
std::string source = ReadFile(shader_path);
auto shader_sources = PreProcess(source);
Compile(shader_sources);
}
// Getting file name
auto last_slash = shader_path.find_last_of("/\\");
last_slash = last_slash == std::string::npos ? 0 : last_slash + 1;
auto last_dot = shader_path.rfind('.');
auto count = last_dot == std::string::npos ? shader_path.size() - last_slash : last_dot - last_slash;
name = shader_path.substr(last_slash, count);
glDeleteProgram(id);
}
void OpenGLShader::Compile(const std::unordered_map<GLenum, std::string> sources)
{
OE_PROFILE_FUNCTION();
GLuint program = glCreateProgram();
GLenum *gl_shader_ids = (GLenum*)alloca(sources.size());
size_t shader_index = 0;
for (auto& kv_pair : sources)
{
GLenum type = kv_pair.first;
const std::string& source = kv_pair.second;
GLuint shader = glCreateShader(type);
const GLchar* source_cstr = source.c_str();
glShaderSource(shader, 1, &source_cstr, 0);
glCompileShader(shader);
GLint is_compiled = 0;
glGetShaderiv(shader, GL_COMPILE_STATUS, &is_compiled);
if (is_compiled == GL_FALSE)
{
GLint max_length = 0;
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &max_length);
std::vector<GLchar> info_log(max_length);
glGetShaderInfoLog(shader, max_length, &max_length, &info_log[0]);
glDeleteShader(shader);
OE_CORE_ERROR("{0}", info_log.data());
OE_CORE_ERROR("Shader compilation failure!");
break;
}
glAttachShader(program, shader);
gl_shader_ids[shader_index++] = shader;
}
id = program;
glLinkProgram(program);
GLint is_linked = 0;
glGetProgramiv(program, GL_LINK_STATUS, (int*)&is_linked);
if (is_linked == GL_FALSE)
{
GLint max_length = 0;
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &max_length);
// The maxLength includes the NULL character
std::vector<GLchar> infoLog(max_length);
glGetProgramInfoLog(program, max_length, &max_length, &infoLog[0]);
// We don't need the program anymore.
glDeleteProgram(program);
for (int i = 0; i < sources.size(); i++)
glDeleteShader(gl_shader_ids[i]);
OE_CORE_ERROR("{0}", infoLog.data());
OE_CORE_ERROR("Shader link failure!");
return;
}
for (int i = 0; i < sources.size(); i++) {
glDetachShader(program, gl_shader_ids[i]);
glDeleteShader(gl_shader_ids[i]);
}
}
std::unordered_map<GLenum, std::string> OpenGLShader::PreProcess(const std::string& shader_source)
{
OE_PROFILE_FUNCTION();
// TODO: Perhaps consider using getline to get the position of errors. or even regexes
std::unordered_map<GLenum, std::string> sources;
const char* type_token = "#type";
size_t type_token_lenght = strlen(type_token);
size_t pos = shader_source.find(type_token, 0);
while (pos != std::string::npos) {
size_t eol = shader_source.find("\n", pos);
if (eol == std::string::npos)
OE_CORE_ERROR("Syntax error.");
size_t begin = pos + type_token_lenght + 1;
std::string type = shader_source.substr(begin, eol - begin);
if (type != "vertex" && type != "fragment" && type != "pixel")
OE_CORE_ERROR("Invalid shader type.");
size_t next_line_pos = shader_source.find_first_not_of("\n", eol);
pos = shader_source.find(type_token, next_line_pos);
sources[ShaderTypeFromString(type)] =
shader_source.substr(next_line_pos, pos - (next_line_pos == std::string::npos ? shader_source.size() - 1 : next_line_pos));
}
return sources;
}
std::string OpenGLShader::ReadFile(const std::string& shader_path)
std::string OpenGLShader::ReadFile(const std::string& filepath)
{
OE_PROFILE_FUNCTION();
std::string result;
std::ifstream input(shader_path);
if (input) {
input.seekg(0, std::ios::end);
size_t size = input.tellg();
if (size != -1) {
std::ifstream in(filepath, std::ios::in | std::ios::binary); // ifstream closes itself due to RAII
if (in)
{
in.seekg(0, std::ios::end);
size_t size = in.tellg();
if (size != -1)
{
result.resize(size);
input.seekg(0, std::ios::beg);
input.read(&result[0], result.size());
input.close();
} else {
OE_CORE_ERROR("Could not read from file {}", shader_path);
in.seekg(0, std::ios::beg);
in.read(&result[0], size);
}
} else {
OE_CORE_ERROR("Shader file could not be open or does not exist: {}", shader_path);
else
{
OE_CORE_ERROR("Could not read from file '{0}'", filepath);
}
}
else
{
OE_CORE_ERROR("Could not open file '{0}'", filepath);
}
return result;
}
std::unordered_map<GLenum, std::string> OpenGLShader::PreProcess(const std::string& source)
{
OE_PROFILE_FUNCTION();
std::unordered_map<GLenum, std::string> shader_sources;
const char* type_token = "#type";
size_t type_token_length = strlen(type_token);
size_t pos = source.find(type_token, 0); //Start of shader type declaration line
while (pos != std::string::npos)
{
size_t eol = source.find_first_of("\r\n", pos); //End of shader type declaration line
OE_CORE_ASSERT(eol != std::string::npos, "Syntax error");
size_t begin = pos + type_token_length + 1; //Start of shader type name (after "#type " keyword)
std::string type = source.substr(begin, eol - begin);
OE_CORE_ASSERT(Utils::ShaderTypeFromString(type), "Invalid shader type specified");
size_t next_line_pos = source.find_first_not_of("\r\n", eol); //Start of shader code after shader type declaration line
OE_CORE_ASSERT(next_line_pos != std::string::npos, "Syntax error");
pos = source.find(type_token, next_line_pos); //Start of next shader type declaration line
shader_sources[Utils::ShaderTypeFromString(type)] = (pos == std::string::npos) ? source.substr(next_line_pos) : source.substr(next_line_pos, pos - next_line_pos);
}
return shader_sources;
}
void OpenGLShader::CompileOrGetVulkanBinaries(const std::unordered_map<GLenum, std::string>& shaderSources)
{
GLuint program = glCreateProgram();
shaderc::Compiler compiler;
shaderc::CompileOptions options;
options.SetTargetEnvironment(shaderc_target_env_vulkan, shaderc_env_version_vulkan_1_2);
const bool optimize = true;
if (optimize)
options.SetOptimizationLevel(shaderc_optimization_level_performance);
std::filesystem::path cache_directory = Utils::GetCacheDirectory();
auto& shader_data = vulkan_spirv;
shader_data.clear();
for (auto&& [stage, source] : shaderSources)
{
std::filesystem::path shader_file_path = file_path;
std::filesystem::path cached_path = cache_directory / (shader_file_path.filename().string() + Utils::GLShaderStageCachedVulkanFileExtension(stage));
std::ifstream in(cached_path, std::ios::in | std::ios::binary);
if (in.is_open())
{
in.seekg(0, std::ios::end);
auto size = in.tellg();
in.seekg(0, std::ios::beg);
auto& data = shader_data[stage];
data.resize(size / sizeof(uint32_t));
in.read((char*)data.data(), size);
}
else
{
shaderc::SpvCompilationResult module = compiler.CompileGlslToSpv(source, Utils::GLShaderStageToShaderC(stage), file_path.c_str(), options);
if (module.GetCompilationStatus() != shaderc_compilation_status_success)
{
OE_CORE_ERROR(module.GetErrorMessage());
OE_CORE_ASSERT(false, "No");
}
shader_data[stage] = std::vector<uint32_t>(module.cbegin(), module.cend());
std::ofstream out(cached_path, std::ios::out | std::ios::binary);
if (out.is_open())
{
auto& data = shader_data[stage];
out.write((char*)data.data(), data.size() * sizeof(uint32_t));
out.flush();
out.close();
}
}
}
for (auto&& [stage, data]: shader_data)
Reflect(stage, data);
}
void OpenGLShader::CompileOrGetOpenGLBinaries()
{
auto& shader_data = opengl_spirv;
shaderc::Compiler compiler;
shaderc::CompileOptions options;
options.SetTargetEnvironment(shaderc_target_env_opengl, shaderc_env_version_opengl_4_5);
const bool optimize = false;
if (optimize)
options.SetOptimizationLevel(shaderc_optimization_level_performance);
std::filesystem::path cache_directory = Utils::GetCacheDirectory();
shader_data.clear();
m_OpenGLSourceCode.clear();
for (auto&& [stage, spirv] : vulkan_spirv)
{
std::filesystem::path shader_file_path = file_path;
std::filesystem::path cached_path = cache_directory / (shader_file_path.filename().string() + Utils::GLShaderStageCachedOpenGLFileExtension(stage));
std::ifstream in(cached_path, std::ios::in | std::ios::binary);
if (in.is_open())
{
in.seekg(0, std::ios::end);
auto size = in.tellg();
in.seekg(0, std::ios::beg);
auto& data = shader_data[stage];
data.resize(size / sizeof(uint32_t));
in.read((char*)data.data(), size);
}
else
{
spirv_cross::CompilerGLSL glsl_compiler(spirv);
m_OpenGLSourceCode[stage] = glsl_compiler.compile();
auto& source = m_OpenGLSourceCode[stage];
shaderc::SpvCompilationResult module = compiler.CompileGlslToSpv(source, Utils::GLShaderStageToShaderC(stage), file_path.c_str());
if (module.GetCompilationStatus() != shaderc_compilation_status_success)
{
OE_CORE_ERROR(module.GetErrorMessage());
OE_CORE_ASSERT(false, "No");
}
shader_data[stage] = std::vector<uint32_t>(module.cbegin(), module.cend());
std::ofstream out(cached_path, std::ios::out | std::ios::binary);
if (out.is_open())
{
auto& data = shader_data[stage];
out.write((char*)data.data(), data.size() * sizeof(uint32_t));
out.flush();
out.close();
}
}
}
}
void OpenGLShader::CreateProgram()
{
GLuint program = glCreateProgram();
std::vector<GLuint> shader_ids;
for (auto&& [stage, spirv] : opengl_spirv)
{
GLuint shaderID = shader_ids.emplace_back(glCreateShader(stage));
glShaderBinary(1, &shaderID, GL_SHADER_BINARY_FORMAT_SPIR_V, spirv.data(), spirv.size() * sizeof(uint32_t));
glSpecializeShader(shaderID, "main", 0, nullptr, nullptr);
glAttachShader(program, shaderID);
}
glLinkProgram(program);
GLint is_linked;
glGetProgramiv(program, GL_LINK_STATUS, &is_linked);
if (is_linked == GL_FALSE)
{
GLint max_length;
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &max_length);
std::vector<GLchar> info_log(max_length);
glGetProgramInfoLog(program, max_length, &max_length, info_log.data());
OE_CORE_ERROR("Shader linking failed ({0}):\n{1}", file_path, info_log.data());
glDeleteProgram(program);
for (auto id : shader_ids)
glDeleteShader(id);
}
for (auto id : shader_ids)
{
glDetachShader(program, id);
glDeleteShader(id);
}
id = program;
}
void OpenGLShader::Reflect(GLenum stage, const std::vector<uint32_t>& shader_data)
{
spirv_cross::Compiler compiler(shader_data);
spirv_cross::ShaderResources resources = compiler.get_shader_resources();
OE_CORE_TRACE("OpenGLShader::Reflect - {0} {1}", Utils::GLShaderStageToString(stage), file_path);
OE_CORE_TRACE(" {0} uniform buffers", resources.uniform_buffers.size());
OE_CORE_TRACE(" {0} resources", resources.sampled_images.size());
OE_CORE_TRACE("Uniform buffers:");
for (const auto& resource : resources.uniform_buffers)
{
const auto& buffer_type = compiler.get_type(resource.base_type_id);
uint32_t buffer_size = compiler.get_declared_struct_size(buffer_type);
uint32_t binding = compiler.get_decoration(resource.id, spv::DecorationBinding);
int member_count = buffer_type.member_types.size();
OE_CORE_TRACE(" {0}", resource.name);
OE_CORE_TRACE(" Size = {0}", buffer_size);
OE_CORE_TRACE(" Binding = {0}", binding);
OE_CORE_TRACE(" Members = {0}", member_count);
}
}
void OpenGLShader::Bind() const
{
OE_PROFILE_FUNCTION();
glUseProgram(id);
}
void OpenGLShader::Unbind() const
{
OE_PROFILE_FUNCTION();
glUseProgram(0);
}
@@ -275,30 +464,4 @@ namespace OpenEngine {
{
glUniform4fv(glGetUniformLocation(id, name.c_str()), 1, glm::value_ptr(value));
}
void OpenGLShader::CheckCompileErrors(unsigned int shader, const std::string& type)
{
int success = GL_FALSE;
char infoLog[1024];
if (type != "PROGRAM") {
glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
if (success == GL_FALSE) {
glGetShaderInfoLog(shader, 1024, NULL, infoLog);
OE_CORE_ERROR("Shader of type {}, couldn't be compiled:", type);
OE_CORE_ERROR("\t{}", infoLog);
}
} else {
if (glGetProgramiv == nullptr) {
OE_CORE_ERROR("OpenGL functions are not loaded!");
return;
}
glGetProgramiv(shader, GL_LINK_STATUS, &success);
if (success == GL_FALSE)
{
glGetProgramInfoLog(shader, 1024, NULL, infoLog);
OE_CORE_ERROR("Program of type {}, couldn't be compiled:", type);
OE_CORE_ERROR("\t{}", infoLog);
}
}
}
}

View File

@@ -22,7 +22,7 @@ namespace OpenEngine {
glTextureStorage2D(id, 1, internal_format, width, height);
glTextureParameteri(id, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTextureParameteri(id, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTextureParameteri(id, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTextureParameteri(id, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTextureParameteri(id, GL_TEXTURE_WRAP_T, GL_REPEAT);
@@ -59,7 +59,7 @@ namespace OpenEngine {
glTextureStorage2D(id, 1, _internal_format, width, height);
glTextureParameteri(id, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTextureParameteri(id, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTextureParameteri(id, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTextureSubImage2D(id, 0, 0, 0, width, height, _data_format, GL_UNSIGNED_BYTE, data);

View File

@@ -0,0 +1,27 @@
#include <pch.hpp>
#include <opengl/opengl_uniform_buffer.hpp>
#include <glad/glad.h>
namespace OpenEngine {
OpenGLUniformBuffer::OpenGLUniformBuffer(uint32_t size, uint32_t binding)
{
glCreateBuffers(1, &id);
glNamedBufferData(id, size, nullptr, GL_DYNAMIC_DRAW);
glBindBufferBase(GL_UNIFORM_BUFFER, binding, id);
}
OpenGLUniformBuffer::~OpenGLUniformBuffer()
{
glDeleteBuffers(1, &id);
}
void OpenGLUniformBuffer::SetData(const void* data, uint32_t size, uint32_t offset)
{
glNamedBufferSubData(id, offset, size, data);
}
}

View File

@@ -0,0 +1,73 @@
#include <pch.hpp>
#include <ref_scope.hpp>
#include <physics.hpp>
#include <Jolt/Physics/Body/BodyInterface.h>
#include <Jolt/Core/JobSystemThreadPool.h>
#include <Jolt/Core/Memory.h>
#include <Jolt/Physics/PhysicsSystem.h>
#include <Jolt/Physics/PhysicsUpdateContext.h>
bool ObjectLayerPairFilterImpl::ShouldCollide(ObjectLayer object1, ObjectLayer object2) const
{
switch (object1)
{
case Layers::NON_MOVING:
return object2 == Layers::MOVING; // Non moving only collides with moving
case Layers::MOVING:
return true; // Moving collides with everything
default:
JPH_ASSERT(false);
return false;
}
}
namespace OpenEngine {
PhysicsEngine::PhysicsEngine()
{
RegisterDefaultAllocator();
Trace = TraceImpl;
JPH_IF_ENABLE_ASSERTS(AssertFailed = AssertFailedImpl);
Factory::sInstance = new Factory();
RegisterTypes();
tmp_allocator = CreateRef<TempAllocatorImpl>(10 * 1024 * 1024);
job_system = CreateRef<JobSystemThreadPool>(cMaxPhysicsJobs,
cMaxPhysicsBarriers,
thread::hardware_concurrency() - 1);
physics_system.Init(
1024,
0,
1024,
1024,
broad_phase_layer_interface,
object_vs_broadphase_layer_filter,
object_vs_object_layer_filter);
//physics_system.SetBodyActivationListener(&body_activation_listener);
//physics_system.SetContactListener(&contact_listener);
// TODO: Check the comment on Jolt's example
physics_system.OptimizeBroadPhase();
}
PhysicsEngine::~PhysicsEngine() {
UnregisterTypes();
// Destroy the factory
delete Factory::sInstance;
Factory::sInstance = nullptr;
};
void PhysicsEngine::Update(float delta_time, int collision_steps)
{
physics_system.Update(delta_time, collision_steps, &*tmp_allocator, &*job_system);
}
}

View File

@@ -91,7 +91,7 @@ namespace OpenEngine {
return nullptr;
}
Ref<IndexBuffer> IndexBuffer::Create(uint32_t* indices, uint32_t count)
Ref<IndexBuffer> IndexBuffer::Create(const uint32_t* indices, uint32_t count)
{
OE_PROFILE_FUNCTION();

View File

@@ -1,4 +1,3 @@
#include "logging.hpp"
#include <pch.hpp>
#include <renderer/editor_camera.hpp>
@@ -63,11 +62,11 @@ namespace OpenEngine {
void EditorCamera::OnUpdate()
{
if (Input::IsKeyPressed(Key::LeftAlt))
{
const glm::vec2& mouse{ Input::GetMouseX(), Input::GetMouseY() };
glm::vec2 delta = (mouse - initial_mouse_position) * 0.003f;
initial_mouse_position = mouse;
if (Input::IsKeyPressed(Key::LeftAlt)) {
const glm::vec2& mouse{ Input::GetMouseX(), Input::GetMouseY() };
glm::vec2 delta = (mouse - initial_mouse_position) * 0.003f;
initial_mouse_position = mouse;
if (Input::IsMouseButtonPressed(Mouse::ButtonMiddle)) {
MousePan(delta);
@@ -152,4 +151,10 @@ namespace OpenEngine {
return glm::quat(glm::vec3(-pitch, -yaw, 0.0f));
}
void EditorCamera::ResetMousePosition()
{
initial_mouse_position = { Input::GetMouseX(), Input::GetMouseY() };
mouse_button_was_pressed = false;
}
}

View File

@@ -0,0 +1,19 @@
#include <pch.hpp>
#include <renderer/model3d.hpp>
#include <gltf/gltf_model3d.hpp>
#include <instrumentor.hpp>
#include <ref_scope.hpp>
namespace OpenEngine {
Ref<Model3D> Model3D::Create(const char* path)
{
OE_PROFILE_FUNCTION();
return CreateRef<GLTFModel3D>(path);
}
}

View File

@@ -1,6 +1,7 @@
#include "renderer/editor_camera.hpp"
#include <pch.hpp>
#include "renderer/editor_camera.hpp"
#include "renderer/uniform_buffer.hpp"
#include <renderer/render_command.hpp>
#include <renderer/vertex_array.hpp>
#include <renderer/renderer2d.hpp>
@@ -27,7 +28,7 @@ namespace OpenEngine {
struct Renderer2DData
{
static const uint32_t max_quads = 10000;
static const uint32_t max_quads = 20000;
static const uint32_t max_vertices = max_quads * 4;
static const uint32_t max_indices = max_quads * 6;
static const uint32_t max_texture_slots = 32;
@@ -47,6 +48,13 @@ namespace OpenEngine {
glm::vec4 quad_vertex_positioning[4];
Statistics stats;
struct CameraData
{
glm::mat4 view_projection;
};
CameraData camera_buffer;
Ref<UniformBuffer> camera_uniform_buffer;
};
static Renderer2DData renderer_data;
@@ -100,8 +108,6 @@ namespace OpenEngine {
samplers[i] = i;
renderer_data.texture_shader = Shader::Create("assets/shaders/texture.glsl");
renderer_data.texture_shader->Bind();
renderer_data.texture_shader->SetIntArray("u_Texture", samplers, renderer_data.max_texture_slots);
renderer_data.texture_slots[0] = renderer_data.white_texture;
@@ -109,10 +115,14 @@ namespace OpenEngine {
renderer_data.quad_vertex_positioning[1] = {0.5, -0.5, 0.0f, 1.0f};
renderer_data.quad_vertex_positioning[2] = {0.5, 0.5, 0.0f, 1.0f};
renderer_data.quad_vertex_positioning[3] = {-0.5, 0.5, 0.0f, 1.0f};
renderer_data.camera_uniform_buffer = UniformBuffer::Create(sizeof(Renderer2DData), 0);
}
void Renderer2D::Shutdown()
{
OE_PROFILE_FUNCTION();
renderer_data.white_texture.reset();
renderer_data.vertex_array.reset();
renderer_data.vertex_buffer.reset();
@@ -122,16 +132,14 @@ namespace OpenEngine {
for (uint32_t i = 0; i < renderer_data.texture_slot_index; i++)
renderer_data.texture_slots[i].reset();
OE_PROFILE_FUNCTION();
}
void Renderer2D::BeginScene(const OrthographicCamera& camera)
{
OE_PROFILE_FUNCTION();
renderer_data.texture_shader->Bind();
renderer_data.texture_shader->SetMat4("u_ViewProjection", camera.GetViewProjectionMatrix());
renderer_data.camera_buffer.view_projection = camera.GetViewProjectionMatrix();
renderer_data.camera_uniform_buffer->SetData(&renderer_data.camera_buffer, sizeof(Renderer2DData::CameraData));
StartBatch();
}
@@ -140,10 +148,8 @@ namespace OpenEngine {
{
OE_PROFILE_FUNCTION();
glm::mat4 view_projection = camera.GetProjection() * glm::inverse(transform);
renderer_data.texture_shader->Bind();
renderer_data.texture_shader->SetMat4("u_ViewProjection", view_projection);
renderer_data.camera_buffer.view_projection = camera.GetProjection() * glm::inverse(transform);
renderer_data.camera_uniform_buffer->SetData(&renderer_data.camera_buffer, sizeof(Renderer2DData::CameraData));
StartBatch();
}
@@ -152,10 +158,8 @@ namespace OpenEngine {
{
OE_PROFILE_FUNCTION();
glm::mat4 view_projection = camera.GetViewProjection();
renderer_data.texture_shader->Bind();
renderer_data.texture_shader->SetMat4("u_ViewProjection", view_projection);
renderer_data.camera_buffer.view_projection = camera.GetViewProjection();
renderer_data.camera_uniform_buffer->SetData(&renderer_data.camera_buffer, sizeof(Renderer2DData::CameraData));
StartBatch();
}
@@ -180,6 +184,7 @@ namespace OpenEngine {
for (int i = 0; i < renderer_data.texture_slot_index; i++)
renderer_data.texture_slots[i]->Bind(i);
renderer_data.texture_shader->Bind();
RenderCommand::DrawIndexed(renderer_data.vertex_array, renderer_data.quad_index_count);
renderer_data.stats.draw_calls++;
@@ -225,6 +230,43 @@ namespace OpenEngine {
DrawQuad(transform, texture, entity_id);
}
void Renderer2D::DrawQuad(const Transform& transform_data,
const Ref<Texture2D>& texture, const glm::vec4& color,
int entity_id, float tiling_factor)
{
OE_PROFILE_FUNCTION();
constexpr size_t quad_vertex_count = 4;
constexpr glm::vec2 texture_coords[] = { { 0.0f, 0.0f }, { 1.0f, 0.0f }, { 1.0f, 1.0f }, { 0.0f, 1.0f }};
if (renderer_data.quad_index_count >= Renderer2DData::max_indices)
FlushAndReset();
glm::vec3 position = transform_data.position;
glm::vec3 size = transform_data.size;
float texture_index = 0;
for (uint32_t i = 1; i < renderer_data.texture_slot_index; i++) {
if (*renderer_data.texture_slots[i].get() == *texture.get()) {
texture_index = (float)i;
break;
}
}
if (texture_index == 0) {
if (renderer_data.texture_slot_index >= Renderer2DData::max_texture_slots)
FlushAndReset();
texture_index = (float)renderer_data.texture_slot_index;
renderer_data.texture_slots[renderer_data.texture_slot_index] = texture;
renderer_data.texture_slot_index++;
}
glm::mat4 transform = glm::translate(glm::mat4(1.0f), transform_data.position)
* glm::rotate(glm::mat4(1.0f), glm::radians(transform_data.rotation), { 0.0f, 0.0f, 1.0f })
* glm::scale(glm::mat4(1.0f), transform_data.size);
}
void Renderer2D::DrawQuad(const Transform& transform_data,
const Ref<Subtexture2D>& subtexture, int entity_id,
float tiling_factor)
@@ -333,6 +375,49 @@ namespace OpenEngine {
renderer_data.stats.quad_count++;
}
void Renderer2D::DrawQuad(const glm::mat4& transform,
const Ref<Texture2D>& texture, const glm::vec4& color,
int entity_id, float tiling_factor)
{
OE_PROFILE_FUNCTION();
constexpr size_t quad_vertex_count = 4;
constexpr glm::vec2 texture_coords[] = { { 0.0f, 0.0f }, { 1.0f, 0.0f }, { 1.0f, 1.0f }, { 0.0f, 1.0f }};
if (renderer_data.quad_index_count >= Renderer2DData::max_indices)
FlushAndReset();
float texture_index = 0;
for (uint32_t i = 1; i < renderer_data.texture_slot_index; i++) {
if (*renderer_data.texture_slots[i].get() == *texture.get()) {
texture_index = (float)i;
break;
}
}
if (texture_index == 0) {
if (renderer_data.texture_slot_index >= Renderer2DData::max_texture_slots)
FlushAndReset();
texture_index = (float)renderer_data.texture_slot_index;
renderer_data.texture_slots[renderer_data.texture_slot_index] = texture;
renderer_data.texture_slot_index++;
}
for (size_t i = 0; i < quad_vertex_count; i++) {
renderer_data.quad_vertex_ptr->position = transform * renderer_data.quad_vertex_positioning[i];
renderer_data.quad_vertex_ptr->color = color;
renderer_data.quad_vertex_ptr->tex_coord = texture_coords[i];
renderer_data.quad_vertex_ptr->tex_index = texture_index;
renderer_data.quad_vertex_ptr->tiling_factor = tiling_factor;
renderer_data.quad_vertex_ptr->id = entity_id;
renderer_data.quad_vertex_ptr++;
}
renderer_data.quad_index_count += 6;
renderer_data.stats.quad_count++;
}
void Renderer2D::DrawQuad(const glm::mat4& transform,
const Ref<Subtexture2D>& subtexture, int entity_id,
float tiling_factor)

View File

@@ -0,0 +1,277 @@
#include "logging.hpp"
#include "scene/scene_camera.hpp"
#include <pch.hpp>
#include <renderer/render_command.hpp>
#include <renderer/uniform_buffer.hpp>
#include <renderer/editor_camera.hpp>
#include <renderer/vertex_array.hpp>
#include <renderer/renderer3d.hpp>
#include <renderer/shader.hpp>
#include <renderer/buffer.hpp>
#include <instrumentor.hpp>
#include <ref_scope.hpp>
#include <glm/ext/quaternion_common.hpp>
#include <glm/ext/matrix_transform.hpp>
#include <glm/trigonometric.hpp>
#include <glm/fwd.hpp>
#include <cstdint>
#include <glad/glad.h>
namespace OpenEngine {
// SHOULD BE MOVED ==================================
Ref<Mesh> CreateQuad(uint32_t id, bool back_face)
{
OE_PROFILE_FUNCTION();
OE_CORE_DEBUG("Creating quad with id {}.", id);
std::vector<MeshVertex> vertices;
std::vector<uint32_t> indices;
if (back_face) {
vertices = {
// Front face (normal 0, 0, 1)
{{-0.5f, -0.5f, 0.0f}, {0,0,1}, {0,0}},
{{-0.5f, 0.5f, 0.0f}, {0,0,1}, {0,1}},
{{ 0.5f, 0.5f, 0.0f}, {0,0,1}, {1,1}},
{{ 0.5f, -0.5f, 0.0f}, {0,0,1}, {1,0}},
// Back face (normal 0, 0, -1)
{{-0.5f, -0.5f, -0.0f}, {0,0,-1}, {0,0}},
{{-0.5f, 0.5f, -0.0f}, {0,0,-1}, {0,1}},
{{ 0.5f, 0.5f, -0.0f}, {0,0,-1}, {1,1}},
{{ 0.5f, -0.5f, -0.0f}, {0,0,-1}, {1,0}}
};
indices = {
// Front face (z=0.5)
0, 2, 1, 0, 3, 2,
// Back face (z=-0.5)
4, 5, 6, 4, 6, 7
};
} else {
vertices = {
// Front face (normal 0, 0, 1)
{{-0.5f, -0.5f, 0.0f}, {0,0,1}, {0,0}},
{{-0.5f, 0.5f, 0.0f}, {0,0,1}, {0,1}},
{{ 0.5f, 0.5f, 0.0f}, {0,0,1}, {1,1}},
{{ 0.5f, -0.5f, 0.0f}, {0,0,1}, {1,0}}
};
indices = {
// Front face (z=0.5)
0, 2, 1, 0, 3, 2
};
}
return CreateMesh(vertices, indices);
}
Ref<Mesh> CreateCube(uint32_t id)
{
OE_PROFILE_FUNCTION();
OE_CORE_DEBUG("Creating cube with id {}.", id);
std::vector<MeshVertex> vertices = {
// Front face (normal 0, 0, 1)
{{-0.5f, -0.5f, 0.5f}, {0,0,1}, {0,0}},
{{-0.5f, 0.5f, 0.5f}, {0,0,1}, {0,1}},
{{ 0.5f, 0.5f, 0.5f}, {0,0,1}, {1,1}},
{{ 0.5f, -0.5f, 0.5f}, {0,0,1}, {1,0}},
// Back face (normal 0, 0, -1)
{{-0.5f, -0.5f, -0.5f}, {0,0,-1}, {0,0}},
{{-0.5f, 0.5f, -0.5f}, {0,0,-1}, {0,1}},
{{ 0.5f, 0.5f, -0.5f}, {0,0,-1}, {1,1}},
{{ 0.5f, -0.5f, -0.5f}, {0,0,-1}, {1,0}},
// Left face (normal -1, 0, 0)
{{-0.5f, -0.5f, -0.5f}, {-1,0,0}, {0,0}},
{{-0.5f, 0.5f, -0.5f}, {-1,0,0}, {0,1}},
{{-0.5f, 0.5f, 0.5f}, {-1,0,0}, {1,1}},
{{-0.5f, -0.5f, 0.5f}, {-1,0,0}, {1,0}},
// Right face (normal 1, 0, 0)
{{ 0.5f, -0.5f, -0.5f}, {1,0,0}, {0,0}},
{{ 0.5f, 0.5f, -0.5f}, {1,0,0}, {0,1}},
{{ 0.5f, 0.5f, 0.5f}, {1,0,0}, {1,1}},
{{ 0.5f, -0.5f, 0.5f}, {1,0,0}, {1,0}},
// Top face (normal 0, 1, 0)
{{-0.5f, 0.5f, -0.5f}, {0,1,0}, {0,0}},
{{-0.5f, 0.5f, 0.5f}, {0,1,0}, {0,1}},
{{ 0.5f, 0.5f, 0.5f}, {0,1,0}, {1,1}},
{{ 0.5f, 0.5f, -0.5f}, {0,1,0}, {1,0}},
// Bottom face (normal 0, -1, 0)
{{-0.5f, -0.5f, -0.5f}, {0,-1,0}, {0,0}},
{{-0.5f, -0.5f, 0.5f}, {0,-1,0}, {0,1}},
{{ 0.5f, -0.5f, 0.5f}, {0,-1,0}, {1,1}},
{{ 0.5f, -0.5f, -0.5f}, {0,-1,0}, {1,0}},
};
std::vector<uint32_t> indices = {
// Front face (z=-0.5)
0, 2, 1, 0, 3, 2,
// Back face (z=0.5)
4, 5, 6, 4, 6, 7,
// Right face
12, 13, 14, 12, 14, 15,
// Left face
8, 10, 9, 8, 11, 10,
// Top face
18, 16, 17, 18, 19, 16,
// Bottom face
20, 22, 21, 20, 23, 22
};
return CreateMesh(vertices, indices);
}
// ==================================================
struct Renderer3DData
{
Ref<Shader> color_shader_3d;
struct CameraData
{
glm::mat4 view_projection;
glm::vec3 view_position;
};
CameraData camera_buffer;
Ref<UniformBuffer> camera_uniform_buffer;
struct TransformData
{
glm::mat4 transform;
};
TransformData transform_buffer;
Ref<UniformBuffer> transform_uniform_buffer;
Material material_buffer;
Ref<UniformBuffer> material_uniform_buffer;
Ref<UniformBuffer> id_uniform_buffer;
};
static Renderer3DData renderer_data;
void Renderer3D::Init()
{
OE_PROFILE_FUNCTION();
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
renderer_data.color_shader_3d = Shader::Create("assets/shaders/color3d.glsl");
renderer_data.camera_uniform_buffer = UniformBuffer::Create(sizeof(Renderer3DData::CameraData), 0);
renderer_data.transform_uniform_buffer = UniformBuffer::Create(sizeof(Renderer3DData::TransformData), 1);
renderer_data.material_uniform_buffer = UniformBuffer::Create(sizeof(Material), 2);
renderer_data.id_uniform_buffer = UniformBuffer::Create(sizeof(uint32_t), 3);
glEnable(GL_DEBUG_OUTPUT);
glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
glDebugMessageCallback([](GLenum source, GLenum type, GLuint id, GLenum severity,
GLsizei length, const GLchar* message, const void* userParam) {
OE_CORE_ERROR("GL: {0}", message);
}, nullptr);
}
void Renderer3D::Shutdown()
{
renderer_data.color_shader_3d.reset();
renderer_data.camera_uniform_buffer.reset();
renderer_data.transform_uniform_buffer.reset();
renderer_data.material_uniform_buffer.reset();
renderer_data.id_uniform_buffer.reset();
}
void Renderer3D::BeginScene(const SceneCamera& camera, const glm::mat4& transform)
{
OE_PROFILE_FUNCTION();
renderer_data.camera_buffer.view_projection = camera.GetProjection() * glm::inverse(transform);
renderer_data.camera_buffer.view_position = transform[3];
renderer_data.camera_uniform_buffer->SetData(&renderer_data.camera_buffer, sizeof(Renderer3DData::CameraData));
}
void Renderer3D::BeginScene(const EditorCamera& camera)
{
OE_PROFILE_FUNCTION();
renderer_data.camera_buffer.view_projection = camera.GetViewProjection();
renderer_data.camera_buffer.view_position = camera.GetPosition();
renderer_data.camera_uniform_buffer->SetData(&renderer_data.camera_buffer, sizeof(Renderer3DData::CameraData));
}
void Renderer3D::EndScene()
{
}
void Renderer3D::DrawMesh(const Ref<Mesh>& mesh, Material& material,
const glm::mat4& transform)
{
OE_PROFILE_FUNCTION();
renderer_data.color_shader_3d->Bind();
renderer_data.transform_buffer.transform = transform;
renderer_data.transform_uniform_buffer->SetData(&renderer_data.transform_buffer, sizeof(Renderer3DData::TransformData));
renderer_data.material_buffer = material;
renderer_data.material_uniform_buffer->SetData(&renderer_data.material_buffer, sizeof(Material));
mesh->vertex_array->Bind();
RenderCommand::DrawIndexed(mesh->vertex_array, mesh->indices.size());
}
void Renderer3D::DrawMesh(const Ref<Mesh>& mesh, Material& material,
const glm::mat4& transform,
uint32_t entity_id)
{
OE_PROFILE_FUNCTION();
renderer_data.color_shader_3d->Bind();
renderer_data.transform_buffer.transform = transform;
renderer_data.transform_uniform_buffer->SetData(&renderer_data.transform_buffer, sizeof(Renderer3DData::TransformData));
renderer_data.material_buffer = material;
renderer_data.material_uniform_buffer->SetData(&renderer_data.material_buffer, sizeof(Material));
renderer_data.id_uniform_buffer->SetData(&entity_id, sizeof(uint32_t));
mesh->vertex_array->Bind();
RenderCommand::DrawIndexed(mesh->vertex_array, mesh->indices.size());
}
void Renderer3D::DrawModel(const Ref<Model3D>& model,
const glm::mat4& transform,
uint32_t entity_id)
{
OE_PROFILE_FUNCTION();
renderer_data.color_shader_3d->Bind();
renderer_data.transform_buffer.transform = transform;
renderer_data.transform_uniform_buffer->SetData(&renderer_data.transform_buffer, sizeof(Renderer3DData::TransformData));
for (auto& mesh : *model) {
renderer_data.material_buffer = mesh.material;
renderer_data.material_uniform_buffer->SetData(&renderer_data.material_buffer, sizeof(Material));
renderer_data.id_uniform_buffer->SetData(&entity_id, sizeof(uint32_t));
mesh.vertex_array->Bind();
RenderCommand::DrawIndexed(mesh.vertex_array, mesh.indices.size());
}
}
}

View File

@@ -0,0 +1,21 @@
#include <pch.hpp>
#include <renderer/uniform_buffer.hpp>
#include <opengl/opengl_uniform_buffer.hpp>
#include <renderer/renderer.hpp>
namespace OpenEngine {
Ref<UniformBuffer> UniformBuffer::Create(uint32_t size, uint32_t binding)
{
switch (Renderer::GetAPI())
{
case RendererAPI::API::None: OE_CORE_ASSERT(false, "RendererAPI::None is currently not supported!"); return nullptr;
case RendererAPI::API::OpenGL: return CreateRef<OpenGLUniformBuffer>(size, binding);
}
OE_CORE_ASSERT(false, "Unknown RendererAPI!");
return nullptr;
}
}

View File

@@ -1,3 +1,4 @@
#include "core.hpp"
#include <glm/trigonometric.hpp>
#include <pch.hpp>
@@ -32,6 +33,7 @@ namespace OpenEngine {
void SceneCamera::SetViewportSize(uint32_t width, uint32_t height)
{
OE_CORE_ASSERT(width > 0 && height > 0, "Viewport size invalid.");
aspect_ratio = (float)width / (float)height;
RecalculateProjection();

306
open_engine/src/open_engine/scene/scene.cpp Normal file → Executable file
View File

@@ -1,26 +1,160 @@
#include "logging.hpp"
#include "physics.hpp"
#include "ref_scope.hpp"
#include "renderer/model3d.hpp"
#include <Jolt/Physics/Body/MotionType.h>
#include <Jolt/Physics/Collision/ObjectLayer.h>
#include <Jolt/Physics/Collision/Shape/ConvexShape.h>
#include <pch.hpp>
#include <renderer/renderer2d.hpp>
#include <renderer/renderer3d.hpp>
#include <scene/components.hpp>
#include <open_engine/scene/native_scriptable_entity.hpp>
#include <scene/entity.hpp>
#include <scene/scene.hpp>
#include <core/time.hpp>
#include <Jolt/Physics/Collision/Shape/Shape.h>
#include <Jolt/Physics/Collision/Shape/PlaneShape.h>
#include <Jolt/Physics/Collision/Shape/BoxShape.h>
#include <Jolt/Physics/Collision/Shape/SphereShape.h>
#include <Jolt/Physics/EActivation.h>
#include <Jolt/Math/Real.h>
#include <Jolt/Math/Quat.h>
#include <cstdint>
#include <entt/entity/fwd.hpp>
namespace OpenEngine {
static Ref<ShapeSettings> CreateShape(entt::registry& reg, entt::entity e)
{
if (reg.any_of<BoxShapeComponent>(e)) {
auto& c = reg.get<BoxShapeComponent>(e);
return CreateRef<BoxShapeSettings>(ToJolt(c.size * 0.5f));
}
if (reg.any_of<SphereShapeComponent>(e)) {
auto& c = reg.get<SphereShapeComponent>(e);
return CreateRef<SphereShapeSettings>(c.radius);
}
if (reg.any_of<PlaneShapeComponent>(e)) {
auto& c = reg.get<PlaneShapeComponent>(e);
const Plane plane({ 0.0f, 1.0f, 0.0f }, 0);
return CreateRef<PlaneShapeSettings>(plane, nullptr, c.extent);
}
OE_CORE_ERROR("Entity {} has no shape component!", reg.get<TagComponent>(e).tag);
return nullptr;
};
void Scene::OnRuntimeStart()
{
body_interface = &physics_engine.GetBodyInterface();
// TODO: Cleanup components aquisition
auto view = registry.view<TransformComponent, PhysicsBodyComponent>();
for (auto e : view) {
Entity entity = { e, this };
auto shape_settings = CreateShape(registry, e);
if (!shape_settings)
shape_settings = CreateRef<BoxShapeSettings>(Vec3(0.5f, 0.5f, 0.5f));
auto shape_result = shape_settings->Create();
if (shape_result.HasError()) {
OE_CORE_ERROR("Shape creation failed: {}", shape_result.GetError().c_str());
continue;
}
ShapeRefC shape = shape_result.Get();
auto& pbc = entity.GetComponents<PhysicsBodyComponent>();
auto& tc = entity.GetComponents<TransformComponent>();
glm::vec3& pos = tc.translation;
glm::vec3& scale = tc.scale;
glm::vec3& rot = tc.rotation;
Quat quat = Quat::sEulerAngles(Vec3(rot.x, rot.y, rot.z));
BodyCreationSettings settings(
shape,
//new BoxShape(Vec3(scale.x * 0.5, scale.y * 0.5f, scale.z * 0.5f)),
Vec3(pos.x, pos.y, pos.z),
quat,
(EMotionType)pbc.type,
pbc.layer);
settings.mLinearDamping = pbc.linear_damping;
settings.mAngularDamping = pbc.angular_damping;
settings.mGravityFactor = pbc.gravity_factor;
settings.mRestitution = pbc.restitution;
settings.mFriction = pbc.friction;
settings.mObjectLayer = (ObjectLayer)pbc.layer;
pbc.body = body_interface->CreateAndAddBody(settings, (EActivation)pbc.initial_activation_state);
}
}
void Scene::OnRuntimeStop()
{
auto view = registry.view<PhysicsBodyComponent>();
for (auto e : view) {
Entity entity = { e, this };
auto& pbc = entity.GetComponents<PhysicsBodyComponent>();
body_interface->RemoveBody(pbc.body);
body_interface->DestroyBody(pbc.body);
}
}
Entity Scene::CreateEntity(const std::string& name)
{
return CreateEntityWithUUID(UUID(), name);
}
Entity Scene::CreateEntityWithUUID(UUID uuid, const std::string& name)
{
Entity entity = { registry.create(), this };
auto& tag = entity.AddComponents<TagComponent>();
entity.AddComponent<IDComponent>(uuid);
auto& tag = entity.AddComponent<TagComponent>();
tag.tag = name.empty() ? "Entity" : name;
return entity;
}
void Scene::DeleteEntity(Entity entity)
void Scene::DeleteEntity(entt::entity entity)
{
registry.destroy(entity);
}
void Scene::MarkEntityForDeletion(Entity entity)
{
pending_deletion.emplace_back(entity);
}
void Scene::UpdateEntities()
{
for (auto& entity : pending_deletion)
DeleteEntity(entity);
pending_deletion.clear();
}
void Scene::OnUpdatePhysics()
{
static int step = 0;
static float accumulator = 0.0f;
static const float fixedDT = 1.0f / 60.0f;
float real_delta_time = Time::DeltaTime(); // e.g. from a timer
accumulator += real_delta_time;
if (accumulator >= fixedDT) {
step++;
physics_engine.Update(fixedDT, 1);
accumulator -= fixedDT;
}
}
void Scene::OnUpdateRuntime()
{
{
@@ -38,6 +172,40 @@ namespace OpenEngine {
});
}
auto view = registry.view<TransformComponent, PhysicsBodyComponent>();
for (auto e : view) {
Entity entity = { e, this };
auto& pos = entity.GetComponents<TransformComponent>().translation;
auto& body = entity.GetComponents<PhysicsBodyComponent>();
body_interface->SetPosition(body.body, { pos.x, pos.y, pos.z }, EActivation::Activate);
body_interface->SetRestitution(body.body, body.restitution);
body_interface->SetFriction(body.body, body.friction);
}
OnUpdatePhysics();
for (auto e : view) {
Entity entity = { e, this };
auto& transform = entity.GetComponents<TransformComponent>();
auto& body = entity.GetComponents<PhysicsBodyComponent>();
auto position = body_interface->GetPosition(body.body);
auto rotation = body_interface->GetRotation(body.body).GetEulerAngles();
transform.translation.x = position.GetX();
transform.translation.y = position.GetY();
transform.translation.z = position.GetZ();
transform.rotation.x = rotation.GetX();
transform.rotation.y = rotation.GetY();
transform.rotation.z = rotation.GetZ();
body_interface->SetGravityFactor(body.body, body.gravity_factor);
}
SceneCamera* main_camera = nullptr;
glm::mat4 main_transform{ 1.0f };
{
@@ -53,33 +221,64 @@ namespace OpenEngine {
}
if (main_camera) {
Renderer2D::BeginScene(main_camera->GetProjection(), main_transform);
Renderer3D::BeginScene(*main_camera, main_transform);
auto view = registry.view<TransformComponent, SpriteRendererComponent>();
auto view = registry.view<TransformComponent, MeshComponent>();
for (const auto& entity : view) {
auto [transform, sprite] = view.get<TransformComponent, SpriteRendererComponent>(entity);
Renderer2D::DrawQuad(GetTransformFromComp(transform), sprite.color, (int)entity);
for (const auto& e : view) {
auto [transform, mesh] = view.get<TransformComponent, MeshComponent>(e);
Entity entity(e, this);
Material material;
if (entity.HasComponent<MaterialComponent>())
material = entity.GetComponents<MaterialComponent>().material;
Renderer3D::DrawMesh(mesh.mesh, material, GetTransformFromComp(transform));
/*
if (sprite.texture)
Renderer2D::DrawQuad(GetTransformFromComp(transform),
sprite.texture, sprite.color, (int)entity, sprite.tiling_factor);
else
Renderer2D::DrawQuad(GetTransformFromComp(transform),
sprite.color, (int)entity);
*/
}
Renderer2D::EndScene();
Renderer3D::EndScene();
}
}
}
void Scene::OnUpdateEditor(EditorCamera& camera)
{
Renderer2D::BeginScene(camera);
Renderer3D::BeginScene(camera);
auto group = registry.group<TransformComponent>(entt::get<SpriteRendererComponent>);
for (auto entity : group)
{
auto [transform, sprite] = group.get<TransformComponent, SpriteRendererComponent>(entity);
auto view = registry.view<TransformComponent, MeshComponent>();
Renderer2D::DrawQuad(GetTransformFromComp(transform), sprite.color, (int)entity);
}
for (const auto& entity : view) {
auto [transform, mesh] = view.get<TransformComponent, MeshComponent>(entity);
Renderer2D::EndScene();
Material material;
Entity _entity(entity, this);
if (_entity.HasComponent<MaterialComponent>())
material = _entity.GetComponents<MaterialComponent>().material;
if (mesh.mesh)
Renderer3D::DrawMesh(mesh.mesh, material, GetTransformFromComp(transform), (uint32_t)_entity);
}
auto model_view = registry.view<TransformComponent, ModelComponent>();
for (const auto& entity : model_view) {
auto [transform, model_comp] = model_view.get<TransformComponent, ModelComponent>(entity);
Entity _entity(entity, this);
Renderer3D::DrawModel(model_comp.model, GetTransformFromComp(transform), (uint32_t)_entity);
}
Renderer3D::EndScene();
}
void Scene::OnViewportResize(uint32_t width, uint32_t height)
@@ -107,4 +306,77 @@ namespace OpenEngine {
return {};
}
template<typename T>
void Scene::OnComponentAdded(Entity entity, T& component)
{
static_assert(false);
}
template<>
void Scene::OnComponentAdded<TransformComponent>(Entity entity, TransformComponent& component)
{
}
template<>
void Scene::OnComponentAdded<CameraComponent>(Entity entity, CameraComponent& component)
{
if (viewport_width > 0 && viewport_height > 0)
component.camera.SetViewportSize(viewport_width, viewport_height);
}
template<>
void Scene::OnComponentAdded<SpriteRendererComponent>(Entity entity, SpriteRendererComponent& component)
{
}
template<>
void Scene::OnComponentAdded<TagComponent>(Entity entity, TagComponent& component)
{
}
template<>
void Scene::OnComponentAdded<NativeScriptComponent>(Entity entity, NativeScriptComponent& component)
{
}
template<>
void Scene::OnComponentAdded<MeshComponent>(Entity entity, MeshComponent& component)
{
}
template<>
void Scene::OnComponentAdded<MaterialComponent>(Entity entity, MaterialComponent& component)
{
}
template<>
void Scene::OnComponentAdded<PhysicsBodyComponent>(Entity entity, PhysicsBodyComponent& component)
{
}
template<>
void Scene::OnComponentAdded<SphereShapeComponent>(Entity entity, SphereShapeComponent& component)
{
}
template<>
void Scene::OnComponentAdded<BoxShapeComponent>(Entity entity, BoxShapeComponent& component)
{
}
template<>
void Scene::OnComponentAdded<IDComponent>(Entity entity, IDComponent& component)
{
}
template<>
void Scene::OnComponentAdded<PlaneShapeComponent>(Entity entity, PlaneShapeComponent& component)
{
}
template<>
void Scene::OnComponentAdded<ModelComponent>(Entity entity, ModelComponent& component)
{
}
}

View File

@@ -1,7 +1,9 @@
#include <cstdint>
#include <pch.hpp>
#include "core.hpp"
#include <scene/scene_serializer.hpp>
#include "renderer/renderer3d.hpp"
#include "scene/components.hpp"
#include "scene/entity.hpp"
@@ -86,11 +88,12 @@ namespace OpenEngine {
static void SerializeEntity(YAML::Emitter& out, Entity entity)
{
out << YAML::BeginMap;
out << YAML::Key << "Entity" << YAML::Value << "412741205"; // Needs random
OE_CORE_ASSERT(entity.HasComponent<IDComponent>(), "Entity is missing UUID.");
if (entity.HasComponent<TagComponent>())
{
out << YAML::BeginMap;
out << YAML::Key << "Entity" << YAML::Value << entity.GetUUID(); // Needs random
if (entity.HasComponent<TagComponent>()) {
out << YAML::Key << "TagComponent";
out << YAML::BeginMap; // TagComponent
@@ -100,8 +103,7 @@ namespace OpenEngine {
out << YAML::EndMap; // TagComponent
}
if (entity.HasComponent<TransformComponent>())
{
if (entity.HasComponent<TransformComponent>()) {
out << YAML::Key << "TransformComponent";
out << YAML::BeginMap; // TransformComponent
@@ -113,8 +115,7 @@ namespace OpenEngine {
out << YAML::EndMap; // TransformComponent
}
if (entity.HasComponent<CameraComponent>())
{
if (entity.HasComponent<CameraComponent>()) {
out << YAML::Key << "CameraComponent";
out << YAML::BeginMap; // CameraComponent
@@ -138,8 +139,7 @@ namespace OpenEngine {
out << YAML::EndMap; // CameraComponent
}
if (entity.HasComponent<SpriteRendererComponent>())
{
if (entity.HasComponent<SpriteRendererComponent>()) {
out << YAML::Key << "SpriteRendererComponent";
out << YAML::BeginMap; // SpriteRendererComponent
@@ -149,6 +149,78 @@ namespace OpenEngine {
out << YAML::EndMap; // SpriteRendererComponent
}
if (entity.HasComponent<MeshComponent>()) {
out << YAML::Key << "MeshComponent";
out << YAML::BeginMap; // MeshComponent
auto& mesh_component = entity.GetComponents<MeshComponent>();
out << YAML::Key << "MeshType" << YAML::Value << (int)mesh_component.primitive_type;
out << YAML::EndMap; // MeshComponent
}
if (entity.HasComponent<MaterialComponent>()) {
out << YAML::Key << "MaterialComponent";
out << YAML::BeginMap; // MaterialComponent
auto& material = entity.GetComponents<MaterialComponent>().material;
out << YAML::Key << "Albedo" << YAML::Value << material.albedo;
out << YAML::Key << "Roughness" << YAML::Value << material.roughness;
out << YAML::Key << "Metalic" << YAML::Value << material.metallic;
out << YAML::Key << "AmbiantStrength" << YAML::Value << material.ambient_strength;
out << YAML::Key << "SpecularStrength" << YAML::Value << material.specular_strength;
out << YAML::EndMap; // MaterialComponent
}
if (entity.HasComponent<PhysicsBodyComponent>()) {
out << YAML::Key << "PhysicsBodyComponent";
out << YAML::BeginMap; // PhysicsBodyComponent
auto& pbc = entity.GetComponents<PhysicsBodyComponent>();
out << YAML::Key << "LinearDamping" << YAML::Value << pbc.linear_damping;
out << YAML::Key << "AngularDamping" << YAML::Value << pbc.angular_damping;
out << YAML::Key << "GravityFactor" << YAML::Value << pbc.gravity_factor;
out << YAML::Key << "Restitution" << YAML::Value << pbc.restitution;
out << YAML::Key << "Friction" << YAML::Value << pbc.friction;
out << YAML::Key << "Type" << YAML::Value << pbc.type;
out << YAML::Key << "ActivationState" << YAML::Value << pbc.initial_activation_state;
out << YAML::Key << "Layer" << YAML::Value << pbc.layer;
out << YAML::EndMap; // PhysicsBodyComponent
}
if (entity.HasComponent<BoxShapeComponent>()) {
out << YAML::Key << "BoxShapeComponent";
out << YAML::BeginMap; //BoxShapeComponent
auto& bsc = entity.GetComponents<BoxShapeComponent>();
out << YAML::Key << "Size" << YAML::Value << bsc.size;
out << YAML::EndMap; //BoxShapeComponent
}
if (entity.HasComponent<SphereShapeComponent>()) {
out << YAML::Key << "SphereShapeComponent";
out << YAML::BeginMap; //SphereShapeComponent
auto& ssc = entity.GetComponents<SphereShapeComponent>();
out << YAML::Key << "Radius" << YAML::Value << ssc.radius;
out << YAML::EndMap; //SphereShapeComponent
}
if (entity.HasComponent<PlaneShapeComponent>()) {
out << YAML::Key << "PlaneShapeComponent";
out << YAML::BeginMap; //PlaneShapeComponent
auto& psc = entity.GetComponents<PlaneShapeComponent>();
out << YAML::Key << "Extent" << YAML::Value << psc.extent;
out << YAML::EndMap; //PlaneShapeComponent
}
out << YAML::EndMap;
}
@@ -191,11 +263,10 @@ namespace OpenEngine {
OE_CORE_TRACE("Deserializing scene '{0}'", sceneName);
auto entities = data["Entities"];
if (entities)
{
if (entities) {
for (auto entity : entities)
{
uint64_t uuid = entity["Entity"].as<uint64_t>(); // TODO
uint64_t uuid = entity["Entity"].as<uint64_t>();
std::string name;
auto tagComponent = entity["TagComponent"];
@@ -204,21 +275,19 @@ namespace OpenEngine {
OE_CORE_TRACE("Deserialized entity with ID = {0}, name = {1}", uuid, name);
Entity deserializedEntity = context->CreateEntity(name);
Entity deserializedEntity = context->CreateEntityWithUUID(uuid, name);
auto transformComponent = entity["TransformComponent"];
if (transformComponent)
{
auto& tc = deserializedEntity.AddComponents<TransformComponent>();
if (transformComponent) {
auto& tc = deserializedEntity.AddComponent<TransformComponent>();
tc.translation = transformComponent["Translation"].as<glm::vec3>();
tc.rotation = transformComponent["Rotation"].as<glm::vec3>();
tc.scale = transformComponent["Scale"].as<glm::vec3>();
}
auto cameraComponent = entity["CameraComponent"];
if (cameraComponent)
{
auto& cc = deserializedEntity.AddComponents<CameraComponent>();
if (cameraComponent) {
auto& cc = deserializedEntity.AddComponent<CameraComponent>();
auto camera_props = cameraComponent["Camera"];
cc.camera.SetProjectionType((SceneCamera::ProjectionType)camera_props["ProjectionType"].as<int>());
@@ -236,16 +305,82 @@ namespace OpenEngine {
}
auto spriteRendererComponent = entity["SpriteRendererComponent"];
if (spriteRendererComponent)
{
auto& src = deserializedEntity.AddComponents<SpriteRendererComponent>();
if (spriteRendererComponent) {
auto& src = deserializedEntity.AddComponent<SpriteRendererComponent>();
src.color = spriteRendererComponent["Color"].as<glm::vec4>();
}
auto mesh_component = entity["MeshComponent"];
if (mesh_component) {
auto& mesh = deserializedEntity.AddComponent<MeshComponent>();
mesh.primitive_type = (PrimitiveType)mesh_component["MeshType"].as<int>();
switch (mesh.primitive_type) {
case OpenEngine::PrimitiveType::Quad: {
mesh.mesh = CreateQuad((uint32_t)deserializedEntity);
break;
}
case OpenEngine::PrimitiveType::Cube: {
mesh.mesh = CreateCube((uint32_t)deserializedEntity);
break;
}
default: {
OE_CORE_ASSERT(false, "No mesh");
break;
}
}
}
auto material_component = entity["MaterialComponent"];
if (material_component) {
auto& material = deserializedEntity.AddComponent<MaterialComponent>();
material.material.albedo = material_component["Albedo"].as<glm::vec4>();
material.material.roughness = material_component["Roughness"].as<float>();
material.material.metallic = material_component["Metalic"].as<float>();
material.material.ambient_strength = material_component["AmbiantStrength"].as<float>();
material.material.specular_strength = material_component["SpecularStrength"].as<float>();
}
auto physics_body_component = entity["PhysicsBodyComponent"];
if (physics_body_component) {
auto& pbc = deserializedEntity.AddComponent<PhysicsBodyComponent>();
pbc.linear_damping = physics_body_component["LinearDamping"].as<float>();
pbc.angular_damping = physics_body_component["AngularDamping"].as<float>();
pbc.gravity_factor = physics_body_component["GravityFactor"].as<float>();
pbc.restitution = physics_body_component["Restitution"].as<float>();
pbc.friction = physics_body_component["Friction"].as<float>();
pbc.type = physics_body_component["Type"].as<int>();
pbc.initial_activation_state = physics_body_component["ActivationState"].as<int>();
pbc.layer = physics_body_component["Layer"].as<int>();
}
auto box_shape_component = entity["BoxShapeComponent"];
if (box_shape_component) {
auto& bsc = deserializedEntity.AddComponent<BoxShapeComponent>();
bsc.size = box_shape_component["Size"].as<glm::vec3>();
}
auto sphere_shape_component = entity["SphereShapeComponent"];
if (sphere_shape_component) {
auto& ssc = deserializedEntity.AddComponent<SphereShapeComponent>();
ssc.radius = sphere_shape_component["Radius"].as<float>();
}
auto plane_shape_component = entity["PlaneShapeComponent"];
if (sphere_shape_component) {
auto& psc = deserializedEntity.AddComponent<PlaneShapeComponent>();
psc.extent = plane_shape_component["Extent"].as<float>();
}
}
}
return true;
}
bool SceneSerializer::DeserializeRuntime(const std::string& file_path)
{
OE_CORE_ASSERT(false, "Not implemented yet");

View File

@@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.28)
cmake_minimum_required(VERSION 3.25.1)
set(CMAKE_CXX_STANDARD 20)

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

@@ -1,47 +0,0 @@
Scene: N/A
Entities:
- Entity: 412741205
TagComponent:
Tag: square 3
TransformComponent:
Translation: [-1.49011612e-08, 0.299999774, -0.499999911]
Rotation: [-1.57079685, 0, 0]
Scale: [0.605000019, 0.60496217, 0.60496217]
SpriteRendererComponent:
Color: [1, 1, 1, 1]
- Entity: 412741205
TagComponent:
Tag: "square 2 "
TransformComponent:
Translation: [0, 0, -0.200000003]
Rotation: [0, 0, 0]
Scale: [0.600000024, 0.600000083, 0.600000024]
SpriteRendererComponent:
Color: [0.882352948, 0.745098054, 0.376470596, 1]
- Entity: 412741205
TagComponent:
Tag: square
TransformComponent:
Translation: [0.299827427, -9.68575478e-08, -0.499896437]
Rotation: [0, 1.57079637, 0]
Scale: [0.6049999, 0.604999959, 0.6049999]
SpriteRendererComponent:
Color: [0.517647088, 0.0901960805, 1, 1]
- Entity: 412741205
TagComponent:
Tag: camera
TransformComponent:
Translation: [0, 0, 20.8999996]
Rotation: [0, 0, 0]
Scale: [1, 1, 1]
CameraComponent:
Camera:
ProjectionType: 0
PerspectiveFOV: 45
PerspectiveNear: 0.00999999978
PerspectiveFar: 1000
OrthographicSize: 10
OrthographicNear: -1
OrthographicFar: 1
Primary: true
FixedAspectRatio: false

1
vendor/ImGuizmo vendored Submodule

Submodule vendor/ImGuizmo added at a15acd87a3