12 Commits

Author SHA1 Message Date
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
b7e5ceb1d1 added quad primitive, shortcuts and safe entity deletion 2026-03-02 21:27:42 +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
43 changed files with 1554 additions and 204 deletions

View File

@@ -0,0 +1,93 @@
#type vertex
#version 450 core
layout(location = 0) in vec3 a_Position;
layout(location = 1) in vec4 a_Color;
layout(location = 2) in vec3 a_Normal;
layout(location = 3) in vec2 a_TexCoord;
layout(location = 4) in int a_EntityID;
layout(std140, binding = 0) uniform Camera
{
mat4 u_ViewProjection;
vec3 u_ViewPosition;
};
layout(std140, binding = 1) uniform Transform
{
mat4 u_Transform;
};
struct VertexOutput
{
vec4 Color;
vec2 TexCoord;
vec3 Normal;
vec3 ViewPos;
};
layout (location = 0) out VertexOutput Output;
layout (location = 4) out flat int v_EntityID;
layout (location = 5) out vec4 v_Pos;
void main()
{
Output.Color = a_Color;
Output.TexCoord = a_TexCoord;
Output.Normal = mat3(transpose(inverse(u_Transform))) * a_Normal;
Output.ViewPos = u_ViewPosition;
v_EntityID = a_EntityID;
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;
struct VertexOutput
{
vec4 Color;
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
float ambientStrength = 0.8;
vec3 ambient = ambientStrength * lightColor;
// 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
float specularStrength = 0.5;
vec3 viewDir = normalize(Input.ViewPos - v_Pos.xyz); // .xyz here too
vec3 reflectDir = reflect(-lightDir, norm);
float spec = pow(max(dot(viewDir, reflectDir), 0.0), 32);
vec3 specular = specularStrength * spec * lightColor;
vec3 result = (ambient + diffuse + specular) * Input.Color.rgb; // objectColor → Input.Color.rgb
// Output
color = vec4(result, 1.0); // vec3 → vec4
color2 = v_EntityID;
}

View File

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

View File

@@ -1,17 +1,17 @@
#ifndef EDITOR_HPP #ifndef EDITOR_HPP
#define EDITOR_HPP #define EDITOR_HPP
#include <filesystem>
#include <open_engine.hpp> #include <open_engine.hpp>
#include "open_engine/application.hpp" #include "open_engine/renderer/renderer3d.hpp"
#include "open_engine/logging.hpp" #include "open_engine/scene/components.hpp"
#include "open_engine/renderer/texture.hpp"
#include "open_engine/scene/entity.hpp"
#include "open_engine/scene/scene_serializer.hpp"
#include "panels/content_browser.hpp" #include "panels/content_browser.hpp"
#include "panels/scene_hierarchy.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/ext/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp> #include <glm/gtc/type_ptr.hpp>
#include <glm/matrix.hpp> #include <glm/matrix.hpp>
@@ -19,6 +19,7 @@
#include <glad/glad.h> #include <glad/glad.h>
#include <GLFW/glfw3.h> #include <GLFW/glfw3.h>
#include <ImGuizmo.h> #include <ImGuizmo.h>
#include <filesystem>
#include <cstdint> #include <cstdint>
#include <imgui.h> #include <imgui.h>
#include <vector> #include <vector>
@@ -93,9 +94,49 @@ namespace OpenEngine {
editor_camera = EditorCamera(30.0f, 1920.0f/1080.0f, 0.1f, 1000.0f); 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["play"] = Texture2D::Create("resources/textures/icons/play.png");
icons["stop"] = Texture2D::Create("resources/textures/icons/stop.png"); icons["stop"] = Texture2D::Create("resources/textures/icons/stop.png");
// TODO: Add file texture. Get free icons and add license
// =============================================
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;
/*
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"); //icons["folder"] = Texture2D::Create("resources/textures/icons/folder.png");
/* /*
for (float i = 0; i < 200; i++) { for (float i = 0; i < 200; i++) {
@@ -140,12 +181,11 @@ namespace OpenEngine {
} }
framebuffer->Bind(); framebuffer->Bind();
Renderer2D::ResetStats(); //Renderer2D::ResetStats();
RenderCommand::SetClearColor({0.11f, 0.11f, 0.15f, 1.0f}); RenderCommand::SetClearColor({0.11f, 0.11f, 0.15f, 1.0f});
RenderCommand::Clear(); RenderCommand::Clear();
framebuffer->ClearBufferI(1, -1); framebuffer->ClearBufferI(1, -1);
switch (state) { switch (state) {
case PlayState::Play: { case PlayState::Play: {
scene->OnUpdateRuntime(); scene->OnUpdateRuntime();
@@ -172,6 +212,7 @@ namespace OpenEngine {
static bool clicked = false; static bool clicked = false;
// Mouse Picking // Mouse Picking
if (Input::IsMouseButtonPressed(MouseCode::ButtonLeft) if (Input::IsMouseButtonPressed(MouseCode::ButtonLeft)
&& !Application::Get().GetImGuiLayer()->GetBlockEvents()
&& mouse_x >= 0 && mouse_y >= 0 && mouse_x >= 0 && mouse_y >= 0
&& mouse_x < (int)viewport_size.x && mouse_x < (int)viewport_size.x
&& mouse_y < (int)viewport_size.y && mouse_y < (int)viewport_size.y
@@ -193,6 +234,8 @@ namespace OpenEngine {
} }
framebuffer->Unbind(); framebuffer->Unbind();
scene->UpdateEntities();
} }
bool EditorKeyBinds(KeyPressedEvent& event) bool EditorKeyBinds(KeyPressedEvent& event)
@@ -203,6 +246,29 @@ namespace OpenEngine {
bool shift = Input::IsKeyPressed(Key::LeftShift) || Input::IsKeyPressed(Key::RightShift); bool shift = Input::IsKeyPressed(Key::LeftShift) || Input::IsKeyPressed(Key::RightShift);
switch(event.GetKeyCode()) { 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: { case KeyCode::Q: {
guizmo_operation = -1; guizmo_operation = -1;
break; break;
@@ -219,6 +285,12 @@ namespace OpenEngine {
guizmo_operation = ImGuizmo::OPERATION::SCALE; guizmo_operation = ImGuizmo::OPERATION::SCALE;
break; break;
} }
case KeyCode::Delete: {
scene->MarkEntityForDeletion(selected_entity);
scene_hierarchy.ClearSelection();
selected_entity = {};
break;
}
default: default:
break; break;
} }
@@ -282,11 +354,15 @@ namespace OpenEngine {
void DrawViewport() void DrawViewport()
{ {
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2{ 0, 0 }); ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2{ 0, 0 });
ImGui::Begin("Viewport"); ImGui::Begin("Viewport");
bool was_focused = viewport_focused;
viewport_focused = ImGui::IsWindowFocused(ImGuiFocusedFlags_RootWindow); viewport_focused = ImGui::IsWindowFocused(ImGuiFocusedFlags_RootWindow);
viewport_hovered = ImGui::IsWindowHovered(ImGuiHoveredFlags_RootWindow); viewport_hovered = ImGui::IsWindowHovered(ImGuiHoveredFlags_RootWindow);
Application::Get().GetImGuiLayer()->SetBlockEvents((!viewport_focused && !viewport_hovered) || ImGui::IsAnyItemActive()); Application::Get().GetImGuiLayer()->SetBlockEvents(ImGui::IsAnyItemActive());
if (viewport_focused && !was_focused)
editor_camera.ResetMousePosition();
ImVec2 viewport_panel_size = ImGui::GetContentRegionAvail(); ImVec2 viewport_panel_size = ImGui::GetContentRegionAvail();
@@ -318,7 +394,7 @@ namespace OpenEngine {
void DrawStats() void DrawStats()
{ {
auto stats = Renderer2D::GetStats(); //auto stats = Renderer2D::GetStats();
static float time = 0; static float time = 0;
time += Time::DeltaTime(); time += Time::DeltaTime();
@@ -330,17 +406,17 @@ namespace OpenEngine {
ImGui::Begin("Statistics"); ImGui::Begin("Statistics");
ImGui::SeparatorText("Performance"); ImGui::SeparatorText("Performance");
ImGui::Text("FPS: %0.0f", 1 / Time::DeltaTime()); ImGui::Text("FPS: %0.0f", 1 / Time::DeltaTime());
ImGui::Text("Renderer2D:"); //ImGui::Text("Renderer2D:");
ImGui::Text("\t\tDraw calls: %d", stats.draw_calls); //ImGui::Text("\t\tDraw calls: %d", stats.draw_calls);
ImGui::Text("\t\tQuad count: %d", stats.quad_count); //ImGui::Text("\t\tQuad count: %d", stats.quad_count);
ImGui::Text("\t\tVertices count: %d", stats.GetTotalVertexCount()); //ImGui::Text("\t\tVertices count: %d", stats.GetTotalVertexCount());
ImGui::Text("\t\tIndices count: %d", stats.GetTotalIndexCount()); //ImGui::Text("\t\tIndices count: %d", stats.GetTotalIndexCount());
if (selected_entity) { //if (selected_entity) {
ImGui::SeparatorText("Entities"); // ImGui::SeparatorText("Entities");
ImGui::Text("Selected entity:"); // ImGui::Text("Selected entity:");
ImGui::Text("\t\tname: %s", selected_entity.GetComponents<TagComponent>().tag.c_str()); // ImGui::Text("\t\tname: %s", selected_entity.GetComponents<TagComponent>().tag.c_str());
ImGui::Text("\t\tid: %d", (uint32_t)selected_entity); // ImGui::Text("\t\tid: %d", (uint32_t)selected_entity);
} //}
ImGui::End(); ImGui::End();
}; };
@@ -400,6 +476,14 @@ namespace OpenEngine {
} }
} }
void SaveScene(const std::string& file)
{
if (!file.empty()) {
SceneSerializer serializer(scene);
serializer.Serialize(file);
}
}
void DrawPlayBar() void DrawPlayBar()
{ {
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, { 0, 2 }); ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, { 0, 2 });
@@ -450,10 +534,7 @@ namespace OpenEngine {
if (ImGui::MenuItem("Save Scene As", "Ctrl+S")) { if (ImGui::MenuItem("Save Scene As", "Ctrl+S")) {
std::string file = FileDialogs::SaveFile("useless"); std::string file = FileDialogs::SaveFile("useless");
OE_TRACE("saving to filename: {}", file); OE_TRACE("saving to filename: {}", file);
if (!file.empty()) { SaveScene(file);
SceneSerializer serializer(scene);
serializer.Serialize(file);
}
} }
if (ImGui::MenuItem("Open Scene", "Ctrl+O")) { if (ImGui::MenuItem("Open Scene", "Ctrl+O")) {
std::string file = FileDialogs::OpenFile("useless"); std::string file = FileDialogs::OpenFile("useless");
@@ -489,10 +570,12 @@ namespace OpenEngine {
void OnScenePlay() void OnScenePlay()
{ {
state = PlayState::Play; state = PlayState::Play;
scene->OnRuntimeStart();
} }
void OnSceneStop() void OnSceneStop()
{ {
state = PlayState::Edit; state = PlayState::Edit;
scene->OnRuntimeStop();
} }
private: private:
@@ -532,24 +615,3 @@ class EditorApp : public OpenEngine::Application
}; };
#endif // EDITOR_HPP #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,14 @@ namespace OpenEngine {
const std::array<const char*, 3> labels = {"x", "y", "z"}); const std::array<const char*, 3> labels = {"x", "y", "z"});
void TagOnImGuiRender(entt::registry& registry, entt::entity entity); void TagOnImGuiRender(entt::registry& registry, entt::entity entity);
void TransformOnImGuiRender(entt::registry& registry, entt::entity entity); void TransformOnImGuiRender(entt::registry& registry, entt::entity entity);
void SpriteOnImGuiRender(entt::registry& registry, entt::entity entity); void SpriteOnImGuiRender(entt::registry& registry, entt::entity entity);
void CameraOnImGuiRender(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);
} }
#endif // EDITOR_COMPONENT_HPP #endif // EDITOR_COMPONENT_HPP

View File

@@ -6,6 +6,8 @@
namespace OpenEngine { namespace OpenEngine {
class EditorLayer;
class ContentBrowserPanel class ContentBrowserPanel
{ {
public: public:
@@ -16,6 +18,7 @@ namespace OpenEngine {
private: private:
std::filesystem::path current_directory; std::filesystem::path current_directory;
Ref<Texture2D> folder_icon; Ref<Texture2D> folder_icon;
Ref<Texture2D> file_icon;
}; };
} }

View File

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

View File

@@ -1,5 +1,10 @@
#include "imgui.h" #include "imgui.h"
#include "open_engine/renderer/renderer3d.hpp"
#include "open_engine/scene/components.hpp"
#include <Jolt/Physics/Body/MotionType.h>
#include <editor_component.hpp> #include <editor_component.hpp>
#include <entt/entity/fwd.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <open_engine.hpp> #include <open_engine.hpp>
namespace OpenEngine { namespace OpenEngine {
@@ -91,6 +96,7 @@ namespace OpenEngine {
if (ImGui::InputText("##tagEditor", buffer, sizeof(buffer), ImGuiInputTextFlags_EnterReturnsTrue | ImGuiInputTextFlags_AutoSelectAll) if (ImGui::InputText("##tagEditor", buffer, sizeof(buffer), ImGuiInputTextFlags_EnterReturnsTrue | ImGuiInputTextFlags_AutoSelectAll)
|| (!ImGui::IsItemActive() && ImGui::IsMouseClicked(0))) || (!ImGui::IsItemActive() && ImGui::IsMouseClicked(0)))
tag = buffer; tag = buffer;
ImGui::Spacing();
}; };
void TransformOnImGuiRender(entt::registry& registry, entt::entity entity) void TransformOnImGuiRender(entt::registry& registry, entt::entity entity)
@@ -101,6 +107,7 @@ namespace OpenEngine {
DrawVec3Control("Rotation", rotation_comp); DrawVec3Control("Rotation", rotation_comp);
transform.rotation = glm::radians(rotation_comp); transform.rotation = glm::radians(rotation_comp);
DrawVec3Control("Scale", transform.scale); DrawVec3Control("Scale", transform.scale);
ImGui::Spacing();
}; };
void SpriteOnImGuiRender(entt::registry& registry, entt::entity entity) void SpriteOnImGuiRender(entt::registry& registry, entt::entity entity)
@@ -170,4 +177,110 @@ 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);
}
} }

28
editor/src/panels/content_browser.cpp Normal file → Executable file
View File

@@ -15,8 +15,9 @@ namespace OpenEngine {
ContentBrowserPanel::ContentBrowserPanel() ContentBrowserPanel::ContentBrowserPanel()
: current_directory(assets_directory) : current_directory(assets_directory)
{ {
// TODO: Add file texture. Get free icons and add license // TODO: Add license
folder_icon = Texture2D::Create("resources/textures/icons/folder.png"); folder_icon = Texture2D::Create("resources/textures/icons/folder2.png");
file_icon = Texture2D::Create("resources/textures/icons/file.png");
} }
void ContentBrowserPanel::OnImGuiRender() void ContentBrowserPanel::OnImGuiRender()
@@ -30,6 +31,16 @@ namespace OpenEngine {
current_directory = current_directory.parent_path(); current_directory = current_directory.parent_path();
auto directory_it = std::filesystem::directory_iterator(current_directory); 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 }; ImVec2 button_size = { 100, 100 };
auto panel_width = ImGui::GetContentRegionAvail().x; auto panel_width = ImGui::GetContentRegionAvail().x;
@@ -42,9 +53,12 @@ namespace OpenEngine {
ImGui::PushStyleVar(ImGuiStyleVar_CellPadding, padding); ImGui::PushStyleVar(ImGuiStyleVar_CellPadding, padding);
float margin = 20.0f;
ImGui::Indent(margin);
if (ImGui::BeginTable("table1", table_columns, ImGuiTableFlags_SizingFixedSame)) if (ImGui::BeginTable("table1", table_columns, ImGuiTableFlags_SizingFixedSame))
{ {
for (auto& entry : directory_it) { for (auto& entry : entries) {
auto file_name = entry.path().filename().string(); auto file_name = entry.path().filename().string();
ImGui::PushID(file_name.c_str()); ImGui::PushID(file_name.c_str());
@@ -56,17 +70,14 @@ namespace OpenEngine {
ImGui::PushStyleColor(ImGuiCol_ButtonActive, { 0.270f, 0.278f, 0.352f, 1.0f }); ImGui::PushStyleColor(ImGuiCol_ButtonActive, { 0.270f, 0.278f, 0.352f, 1.0f });
ImGui::BeginGroup(); ImGui::BeginGroup();
ImGui::ImageButton("##X", (ImTextureID)folder_icon->GetID(), button_size, { 0, 1 }, { 1, 0 }); 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()) { if (entry.is_regular_file() && ImGui::BeginDragDropSource()) {
const char* source = entry.path().c_str(); const char* source = entry.path().c_str();
ImGui::SetDragDropPayload("CONTENT_BROWSER_PAYLOAD", source, (strlen(source) + 1) * sizeof(char), ImGuiCond_Once); ImGui::SetDragDropPayload("CONTENT_BROWSER_PAYLOAD", source, (strlen(source) + 1) * sizeof(char), ImGuiCond_Once);
ImGui::EndDragDropSource(); ImGui::EndDragDropSource();
} }
float columnWidth = ImGui::GetColumnWidth();
float textWidth = ImGui::CalcTextSize(file_name.c_str()).x;
ImGui::SetCursorPosX(ImGui::GetCursorPosX() + (columnWidth - textWidth) * 0.5f);
ImGui::TextWrapped("%s", file_name.c_str()); ImGui::TextWrapped("%s", file_name.c_str());
ImGui::EndGroup(); ImGui::EndGroup();
@@ -81,6 +92,7 @@ namespace OpenEngine {
} }
ImGui::EndTable(); ImGui::EndTable();
} }
ImGui::Unindent();
ImGui::PopStyleVar(); ImGui::PopStyleVar();
ImGui::End(); ImGui::End();

View File

@@ -1,4 +1,3 @@
#include "open_engine/scene/components.hpp"
#include "open_engine/scene/entity.hpp" #include "open_engine/scene/entity.hpp"
#include "editor_component.hpp" #include "editor_component.hpp"
@@ -22,6 +21,11 @@ namespace OpenEngine {
RegisterDrawer<TransformComponent>("Transform", &TransformOnImGuiRender); RegisterDrawer<TransformComponent>("Transform", &TransformOnImGuiRender);
RegisterDrawer<SpriteRendererComponent>("Sprite Renderer", &SpriteOnImGuiRender); RegisterDrawer<SpriteRendererComponent>("Sprite Renderer", &SpriteOnImGuiRender);
RegisterDrawer<CameraComponent>("Camera", &CameraOnImGuiRender); 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);
scene = context; scene = context;
selected_context = {}; selected_context = {};
@@ -32,17 +36,42 @@ namespace OpenEngine {
ImGui::SeparatorText("Add"); ImGui::SeparatorText("Add");
if (!selected_context.HasComponent<TransformComponent>()) if (!selected_context.HasComponent<TransformComponent>())
if (ImGui::MenuItem("Transform")) { if (ImGui::MenuItem("Transform")) {
selected_context.AddComponents<TransformComponent>(); selected_context.AddComponent<TransformComponent>();
ImGui::CloseCurrentPopup(); ImGui::CloseCurrentPopup();
} }
if (!selected_context.HasComponent<SpriteRendererComponent>()) if (!selected_context.HasComponent<SpriteRendererComponent>())
if (ImGui::MenuItem("Sprite")) { if (ImGui::MenuItem("Sprite")) {
selected_context.AddComponents<SpriteRendererComponent>(); selected_context.AddComponent<SpriteRendererComponent>();
ImGui::CloseCurrentPopup(); ImGui::CloseCurrentPopup();
} }
if (!selected_context.HasComponent<CameraComponent>()) if (!selected_context.HasComponent<CameraComponent>())
if (ImGui::MenuItem("Camera")) { 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(); ImGui::CloseCurrentPopup();
} }
} }
@@ -127,7 +156,6 @@ namespace OpenEngine {
{ {
auto& tag = entity.GetComponents<TagComponent>().tag; auto& tag = entity.GetComponents<TagComponent>().tag;
bool entity_marked_deletion = false;
if (renamed_entity == entity && selected_context == entity) { if (renamed_entity == entity && selected_context == entity) {
char buffer[255]; char buffer[255];
std::memset(buffer, 0, sizeof(buffer)); std::memset(buffer, 0, sizeof(buffer));
@@ -155,8 +183,10 @@ namespace OpenEngine {
bool opened = ImGui::TreeNodeEx((void*)(uint64_t)(uint32_t)entity, flags, "%s", tag.c_str()); bool opened = ImGui::TreeNodeEx((void*)(uint64_t)(uint32_t)entity, flags, "%s", tag.c_str());
if (ImGui::BeginPopupContextItem()) { if (ImGui::BeginPopupContextItem()) {
if (ImGui::MenuItem("Delete entity")) if (ImGui::MenuItem("Delete entity")) {
entity_marked_deletion = true; scene->MarkEntityForDeletion(entity);
selected_context = {};
}
ImGui::EndPopup(); ImGui::EndPopup();
} }
@@ -183,27 +213,23 @@ namespace OpenEngine {
if (opened) if (opened)
ImGui::TreePop(); ImGui::TreePop();
} }
if (entity_marked_deletion) {
scene->DeleteEntity(entity);
if (selected_context == entity)
selected_context = {};
}
} }
void SceneHierarchy::DrawComponents(Entity& entity) void SceneHierarchy::DrawComponents(Entity& entity)
{ {
auto& reg = scene->GetRegistry(); auto& reg = scene->GetRegistry();
entt::entity handle = selected_context; entt::entity handle = entity;
if (!selected_context || !entity) if (!entity)
return; return;
entity.GetComponents<TagComponent>(); entity.GetComponents<TagComponent>();
TagOnImGuiRender(reg, entity); TagOnImGuiRender(reg, entity);
std::vector<entt::id_type> component_to_delete; // 0 is null/invalid in entt usually // TODO: Defer deletion like the entities?
// Iterate through every component type entt knows about 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()) { for (auto [id, storage] : reg.storage()) {
if (storage.contains(handle)) { if (storage.contains(handle)) {
if (drawers.contains(id)) { if (drawers.contains(id)) {
@@ -226,20 +252,24 @@ namespace OpenEngine {
if (ImGui::BeginPopup("component_settings")) { if (ImGui::BeginPopup("component_settings")) {
if (ImGui::MenuItem("Remove component")) if (ImGui::MenuItem("Remove component"))
component_to_delete.emplace_back(id); pending_deletion.emplace_back(id);
ImGui::EndPopup(); ImGui::EndPopup();
} }
if (opened) { if (opened) {
ImGui::Spacing();
drawers[id].draw_func(reg, handle); drawers[id].draw_func(reg, handle);
ImGui::Spacing();
ImGui::TreePop(); ImGui::TreePop();
} }
} }
} }
} }
for (auto& id : component_to_delete) for (auto& id : pending_deletion) {
drawers[id].remove_func(reg, entity); drawers[id].remove_func(reg, entity);
pending_deletion.clear();
}
} }
} }

View File

@@ -173,11 +173,11 @@ DockSpace ID=0x08BD597D Window=0x1BBC0F80 Pos=0,24 Size=1272,1363
DockNode ID=0x0000000F Parent=0x0000000D SizeRef=594,60 Selected=0x8325EBDA DockNode ID=0x0000000F Parent=0x0000000D SizeRef=594,60 Selected=0x8325EBDA
DockNode ID=0x00000010 Parent=0x0000000D SizeRef=594,931 Split=Y Selected=0xC450F867 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=0x00000011 Parent=0x00000010 SizeRef=594,35 HiddenTabBar=1 Selected=0xAB37695D
DockNode ID=0x00000012 Parent=0x00000010 SizeRef=594,956 CentralNode=1 Selected=0xC450F867 DockNode ID=0x00000012 Parent=0x00000010 SizeRef=594,964 CentralNode=1 Selected=0xC450F867
DockNode ID=0x0000000E Parent=0x0000000B SizeRef=800,993 Selected=0x3EEA4247 DockNode ID=0x0000000E Parent=0x0000000B SizeRef=800,993 Selected=0x3EEA4247
DockNode ID=0x0000000C Parent=0x00000009 SizeRef=409,368 Selected=0x42C24103 DockNode ID=0x0000000C Parent=0x00000009 SizeRef=409,368 Selected=0x42C24103
DockNode ID=0x0000000A Parent=0x00000002 SizeRef=483,600 Selected=0x1BCA3180 DockNode ID=0x0000000A Parent=0x00000002 SizeRef=483,600 Selected=0x1BCA3180
DockNode ID=0x00000006 Parent=0x08BD597D SizeRef=450,1386 Split=Y Selected=0x8C72BEA8 DockNode ID=0x00000006 Parent=0x08BD597D SizeRef=450,1386 Split=Y Selected=0x8C72BEA8
DockNode ID=0x00000007 Parent=0x00000006 SizeRef=444,769 Selected=0x8C72BEA8 DockNode ID=0x00000007 Parent=0x00000006 SizeRef=444,805 Selected=0x8C72BEA8
DockNode ID=0x00000008 Parent=0x00000006 SizeRef=444,531 Selected=0x5E5F7166 DockNode ID=0x00000008 Parent=0x00000006 SizeRef=444,556 Selected=0x5E5F7166

View File

@@ -13,6 +13,7 @@ add_definitions( -DOE_ENABLE_ASSERTS )
find_package(imgui REQUIRED) find_package(imgui REQUIRED)
find_package(EnTT REQUIRED) find_package(EnTT REQUIRED)
find_package(yaml-cpp REQUIRED) find_package(yaml-cpp REQUIRED)
find_package(Jolt REQUIRED)
file(GLOB_RECURSE SRC_FILES "src/*.cpp") file(GLOB_RECURSE SRC_FILES "src/*.cpp")
file(GLOB IMGUIZMO_SRC_FILES "${CMAKE_SOURCE_DIR}/vendor/ImGuizmo/*.cpp") file(GLOB IMGUIZMO_SRC_FILES "${CMAKE_SOURCE_DIR}/vendor/ImGuizmo/*.cpp")
@@ -52,6 +53,16 @@ target_link_libraries(${PROJECT_EXECUTABLE_NAME} PUBLIC
X11 X11
yaml-cpp::yaml-cpp yaml-cpp::yaml-cpp
nfd 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
) )
#target_link_directories(${PROJECT_EXECUTABLE_NAME} PRIVATE #target_link_directories(${PROJECT_EXECUTABLE_NAME} PRIVATE
@@ -63,3 +74,5 @@ add_subdirectory(vendor/glad
) )
add_subdirectory("vendor/nativefiledialog-extended") 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/subtexture2d.hpp"
#include "open_engine/renderer/framebuffer.hpp" #include "open_engine/renderer/framebuffer.hpp"
#include "open_engine/renderer/renderer2d.hpp" #include "open_engine/renderer/renderer2d.hpp"
#include "open_engine/renderer/renderer3d.hpp"
#include "open_engine/renderer/renderer.hpp" #include "open_engine/renderer/renderer.hpp"
#include "open_engine/renderer/texture.hpp" #include "open_engine/renderer/texture.hpp"
#include "open_engine/renderer/buffer.hpp" #include "open_engine/renderer/buffer.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

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

View File

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

View File

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

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,6 +1,8 @@
#ifndef BUFFER_HPP #ifndef BUFFER_HPP
#define BUFFER_HPP #define BUFFER_HPP
#include "open_engine/ref_scope.hpp"
#include <cstdint> #include <cstdint>
#include <vector> #include <vector>
#include <string> #include <string>
@@ -82,8 +84,9 @@ namespace OpenEngine {
virtual void UnBind() const = 0; virtual void UnBind() const = 0;
virtual uint32_t GetCount() 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; glm::vec3 GetForwardDirection() const;
const glm::vec3& GetPosition() const { return position; } const glm::vec3& GetPosition() const { return position; }
glm::quat GetOrientation() const; glm::quat GetOrientation() const;
void ResetMousePosition();
float GetPitch() const { return pitch; } float GetPitch() const { return pitch; }
float GetYaw() const { return yaw; } float GetYaw() const { return yaw; }
@@ -61,6 +62,7 @@ namespace OpenEngine {
glm::vec3 focal_point = { 0.0f, 0.0f, 0.0f }; glm::vec3 focal_point = { 0.0f, 0.0f, 0.0f };
glm::vec2 initial_mouse_position = { 0.0f, 0.0f }; glm::vec2 initial_mouse_position = { 0.0f, 0.0f };
bool mouse_button_was_pressed = false;
float distance = 10.0f; float distance = 10.0f;
float pitch = 0.0f, yaw = 0.0f; float pitch = 0.0f, yaw = 0.0f;

View File

@@ -0,0 +1,71 @@
#ifndef RENDERER3D_HPP
#define RENDERER3D_HPP
#include "open_engine/renderer/editor_camera.hpp"
#include "open_engine/renderer/vertex_array.hpp"
#include "open_engine/renderer/buffer.hpp"
#include "open_engine/scene/scene_camera.hpp"
#include <cstdint>
namespace OpenEngine {
// SHOULD BE MOVED ==================================
enum class PrimitiveType
{
None = 0,
Quad,
Cube
};
struct MeshVertex
{
glm::vec3 position;
glm::vec4 color;
glm::vec3 normal;
glm::vec2 text_coords;
uint32_t id = -1;
};
struct Material
{
glm::vec4 albedo = { 1.0f, 1.0f, 1.0f, 1.0f };
float roughness = 1.0f;
float metallic = 1.0f;
float ambient_strength = 1.0f;
float specular_strength = 1.0f;
};
struct Mesh
{
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;
};
Ref<Mesh> CreateMesh(const std::vector<MeshVertex>& vertices,
const std::vector<uint32_t>& indices);
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);
};
}
#endif // RENDERER3D_HPP

View File

@@ -1,21 +0,0 @@
#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

@@ -8,7 +8,7 @@ namespace OpenEngine {
class UniformBuffer class UniformBuffer
{ {
public: public:
virtual ~UniformBuffer() {} virtual ~UniformBuffer() = default;
virtual void SetData(const void* data, uint32_t size, virtual void SetData(const void* data, uint32_t size,
uint32_t offset = 0) = 0; uint32_t offset = 0) = 0;

View File

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

View File

@@ -1,10 +1,19 @@
#ifndef COMPONENTS_HPP #ifndef COMPONENTS_HPP
#define 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/scene/scene_camera.hpp"
#include "open_engine/renderer/texture.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 <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/ext/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp> #include <glm/gtc/type_ptr.hpp>
#include <glm/fwd.hpp> #include <glm/fwd.hpp>
@@ -19,6 +28,15 @@
namespace OpenEngine { namespace OpenEngine {
struct IDComponent
{
UUID id;
IDComponent() = default;
IDComponent(const IDComponent&) = default;
IDComponent(const UUID& uuid) : id(uuid) {};
};
struct TagComponent struct TagComponent
{ {
std::string tag; std::string tag;
@@ -65,6 +83,8 @@ namespace OpenEngine {
CameraComponent(const CameraComponent&) = default; CameraComponent(const CameraComponent&) = default;
}; };
class NativeScriptableEntity;
struct NativeScriptComponent struct NativeScriptComponent
{ {
NativeScriptableEntity* instance = nullptr; NativeScriptableEntity* instance = nullptr;
@@ -72,9 +92,6 @@ namespace OpenEngine {
NativeScriptableEntity* (*InstanciateScript)(); NativeScriptableEntity* (*InstanciateScript)();
void (*DestroyInstanceScript)(NativeScriptComponent*); void (*DestroyInstanceScript)(NativeScriptComponent*);
void OnImGuiRender(Entity& entity)
{};
template <typename T> template <typename T>
void Bind() void Bind()
{ {
@@ -84,9 +101,58 @@ namespace OpenEngine {
(delete nsc->instance); (delete nsc->instance);
nsc->instance = nullptr; 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 };
};
struct SphereShapeComponent
{
float radius = 1.0f;
};
} }
#endif // COMPONENTS_HPP #endif // COMPONENTS_HPP

View File

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

View File

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

View File

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

View File

@@ -4,6 +4,7 @@
#include <core.hpp> #include <core.hpp>
#include <events/application_event.hpp> #include <events/application_event.hpp>
#include <renderer/renderer3d.hpp>
#include <renderer/renderer2d.hpp> #include <renderer/renderer2d.hpp>
#include <input/input_system.hpp> #include <input/input_system.hpp>
#include <imgui/imgui_layer.hpp> #include <imgui/imgui_layer.hpp>
@@ -28,7 +29,8 @@ namespace OpenEngine {
{ {
OE_PROFILE_SCOPE("Initializing Renderers"); OE_PROFILE_SCOPE("Initializing Renderers");
Renderer::Init(); Renderer::Init();
Renderer2D::Init(); //Renderer2D::Init();
Renderer3D::Init();
} }
imgui_layer = std::make_shared<ImGuiLayer>(); imgui_layer = std::make_shared<ImGuiLayer>();
@@ -39,7 +41,8 @@ namespace OpenEngine {
Application::~Application() Application::~Application()
{ {
OpenEngine::Renderer2D::Shutdown(); //OpenEngine::Renderer2D::Shutdown();
Renderer3D::Shutdown();
} }
void Application::Run() 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

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

View File

@@ -45,6 +45,7 @@ namespace OpenEngine {
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_DEPTH_TEST); glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
} }
void OpenGLRendererAPI::SetViewport(uint32_t x, uint32_t y, uint32_t width, uint32_t height) 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_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(); uint32_t count = index_count? index_count : vertex_array->GetIndexBuffer()->GetCount();
glDrawElements(GL_TRIANGLES, count, GL_UNSIGNED_INT, nullptr); glDrawElements(GL_TRIANGLES, count, GL_UNSIGNED_INT, nullptr);
glBindTexture(GL_TEXTURE_2D, 0); glBindTexture(GL_TEXTURE_2D, 0);

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; 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(); OE_PROFILE_FUNCTION();

View File

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

@@ -1,7 +1,7 @@
#include "renderer/editor_camera.hpp"
#include "renderer/uniform_buffer.hpp"
#include <pch.hpp> #include <pch.hpp>
#include "renderer/editor_camera.hpp"
#include "renderer/uniform_buffer.hpp"
#include <renderer/render_command.hpp> #include <renderer/render_command.hpp>
#include <renderer/vertex_array.hpp> #include <renderer/vertex_array.hpp>
#include <renderer/renderer2d.hpp> #include <renderer/renderer2d.hpp>
@@ -121,6 +121,8 @@ namespace OpenEngine {
void Renderer2D::Shutdown() void Renderer2D::Shutdown()
{ {
OE_PROFILE_FUNCTION();
renderer_data.white_texture.reset(); renderer_data.white_texture.reset();
renderer_data.vertex_array.reset(); renderer_data.vertex_array.reset();
renderer_data.vertex_buffer.reset(); renderer_data.vertex_buffer.reset();
@@ -130,8 +132,6 @@ namespace OpenEngine {
for (uint32_t i = 0; i < renderer_data.texture_slot_index; i++) for (uint32_t i = 0; i < renderer_data.texture_slot_index; i++)
renderer_data.texture_slots[i].reset(); renderer_data.texture_slots[i].reset();
OE_PROFILE_FUNCTION();
} }
void Renderer2D::BeginScene(const OrthographicCamera& camera) void Renderer2D::BeginScene(const OrthographicCamera& camera)

View File

@@ -0,0 +1,256 @@
#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> CreateMesh(const std::vector<MeshVertex>& vertices,
const std::vector<uint32_t>& indices)
{
Ref<Mesh> mesh = CreateRef<Mesh>();
mesh->vertices = vertices;
mesh->indices = indices;
mesh->vertex_array = VertexArray::Create();
mesh->vertex_buffer = VertexBuffer::Create(vertices.size() * sizeof(MeshVertex));
mesh->vertex_buffer->SetData(vertices.data(), vertices.size() * sizeof(MeshVertex));
BufferLayout layout = {
{ ShaderDataType::Float3, "a_Position" },
{ ShaderDataType::Float4, "a_Color" },
{ ShaderDataType::Float3, "a_Normal" },
{ ShaderDataType::Float2, "a_TexCoord" },
{ ShaderDataType::Int, "a_EntityID"}
};
mesh->vertex_buffer->SetLayout(layout);
mesh->vertex_array->AddVertexBuffer(mesh->vertex_buffer);
mesh->index_buffer = IndexBuffer::Create(indices.data(), indices.size());
mesh->vertex_array->SetIndexBuffer(mesh->index_buffer);
return mesh;
}
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.5f, 0.5f, 0.5f, 1 }, {0,0,1}, {0,0}, id},
{{-0.5f, 0.5f, 0.0f}, { 0.5f, 0.5f, 0.5f, 1 }, {0,0,1}, {0,1}, id},
{{ 0.5f, 0.5f, 0.0f}, { 0.5f, 0.5f, 0.5f, 1 }, {0,0,1}, {1,1}, id},
{{ 0.5f, -0.5f, 0.0f}, { 0.5f, 0.5f, 0.5f, 1 }, {0,0,1}, {1,0}, id},
// Back face (normal 0, 0, -1)
{{-0.5f, -0.5f, -0.0f}, { 0.5f, 0.5f, 0.5f, 1 }, {0,0,-1}, {0,0}, id},
{{-0.5f, 0.5f, -0.0f}, { 0.5f, 0.5f, 0.5f, 1 }, {0,0,-1}, {0,1}, id},
{{ 0.5f, 0.5f, -0.0f}, { 0.5f, 0.5f, 0.5f, 1 }, {0,0,-1}, {1,1}, id},
{{ 0.5f, -0.5f, -0.0f}, { 0.5f, 0.5f, 0.5f, 1 }, {0,0,-1}, {1,0}, id}
};
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.5f, 0.5f, 0.5f, 1 }, {0,0,1}, {0,0}, id},
{{-0.5f, 0.5f, 0.0f}, { 0.5f, 0.5f, 0.5f, 1 }, {0,0,1}, {0,1}, id},
{{ 0.5f, 0.5f, 0.0f}, { 0.5f, 0.5f, 0.5f, 1 }, {0,0,1}, {1,1}, id},
{{ 0.5f, -0.5f, 0.0f}, { 0.5f, 0.5f, 0.5f, 1 }, {0,0,1}, {1,0}, id}
};
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.5f, 0.5f, 0.5f, 1 }, {0,0,1}, {0,0}, id},
{{-0.5f, 0.5f, 0.5f}, { 0.5f, 0.5f, 0.5f, 1 }, {0,0,1}, {0,1}, id},
{{ 0.5f, 0.5f, 0.5f}, { 0.5f, 0.5f, 0.5f, 1 }, {0,0,1}, {1,1}, id},
{{ 0.5f, -0.5f, 0.5f}, { 0.5f, 0.5f, 0.5f, 1 }, {0,0,1}, {1,0}, id},
// Back face (normal 0, 0, -1)
{{-0.5f, -0.5f, -0.5f}, { 0.5f, 0.5f, 0.5f, 1 }, {0,0,-1}, {0,0}, id},
{{-0.5f, 0.5f, -0.5f}, { 0.5f, 0.5f, 0.5f, 1 }, {0,0,-1}, {0,1}, id},
{{ 0.5f, 0.5f, -0.5f}, { 0.5f, 0.5f, 0.5f, 1 }, {0,0,-1}, {1,1}, id},
{{ 0.5f, -0.5f, -0.5f}, { 0.5f, 0.5f, 0.5f, 1 }, {0,0,-1}, {1,0}, id},
// Left face (normal -1, 0, 0)
{{-0.5f, -0.5f, -0.5f}, { 0.5f, 0.5f, 0.5f, 1 }, {-1,0,0}, {0,0}, id},
{{-0.5f, 0.5f, -0.5f}, { 0.5f, 0.5f, 0.5f, 1 }, {-1,0,0}, {0,1}, id},
{{-0.5f, 0.5f, 0.5f}, { 0.5f, 0.5f, 0.5f, 1 }, {-1,0,0}, {1,1}, id},
{{-0.5f, -0.5f, 0.5f}, { 0.5f, 0.5f, 0.5f, 1 }, {-1,0,0}, {1,0}, id},
// Right face (normal 1, 0, 0)
{{ 0.5f, -0.5f, -0.5f}, { 0.5f, 0.5f, 0.5f, 1 }, {1,0,0}, {0,0}, id},
{{ 0.5f, 0.5f, -0.5f}, { 0.5f, 0.5f, 0.5f, 1 }, {1,0,0}, {0,1}, id},
{{ 0.5f, 0.5f, 0.5f}, { 0.5f, 0.5f, 0.5f, 1 }, {1,0,0}, {1,1}, id},
{{ 0.5f, -0.5f, 0.5f}, { 0.5f, 0.5f, 0.5f, 1 }, {1,0,0}, {1,0}, id},
// Top face (normal 0, 1, 0)
{{-0.5f, 0.5f, -0.5f}, { 0.5f, 0.5f, 0.5f, 1 }, {0,1,0}, {0,0}, id},
{{-0.5f, 0.5f, 0.5f}, { 0.5f, 0.5f, 0.5f, 1 }, {0,1,0}, {0,1}, id},
{{ 0.5f, 0.5f, 0.5f}, { 0.5f, 0.5f, 0.5f, 1 }, {0,1,0}, {1,1}, id},
{{ 0.5f, 0.5f, -0.5f}, { 0.5f, 0.5f, 0.5f, 1 }, {0,1,0}, {1,0}, id},
// Bottom face (normal 0, -1, 0)
{{-0.5f, -0.5f, -0.5f}, { 0.5f, 0.5f, 0.5f, 1 }, {0,-1,0}, {0,0}, id},
{{-0.5f, -0.5f, 0.5f}, { 0.5f, 0.5f, 0.5f, 1 }, {0,-1,0}, {0,1}, id},
{{ 0.5f, -0.5f, 0.5f}, { 0.5f, 0.5f, 0.5f, 1 }, {0,-1,0}, {1,1}, id},
{{ 0.5f, -0.5f, -0.5f}, { 0.5f, 0.5f, 0.5f, 1 }, {0,-1,0}, {1,0}, id},
};
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;
};
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);
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();
}
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());
}
}

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

@@ -1,26 +1,153 @@
#include "logging.hpp"
#include "physics.hpp"
#include "ref_scope.hpp"
#include <Jolt/Physics/Body/MotionType.h>
#include <Jolt/Physics/Collision/ObjectLayer.h>
#include <Jolt/Physics/Collision/Shape/ConvexShape.h>
#include <pch.hpp> #include <pch.hpp>
#include <renderer/renderer2d.hpp> #include <renderer/renderer3d.hpp>
#include <scene/components.hpp> #include <scene/components.hpp>
#include <open_engine/scene/native_scriptable_entity.hpp>
#include <scene/entity.hpp> #include <scene/entity.hpp>
#include <scene/scene.hpp> #include <scene/scene.hpp>
#include <core/time.hpp>
#include <Jolt/Physics/Collision/Shape/Shape.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 { 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);
}
OE_CORE_ERROR("Entity has no shape component!");
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) 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 }; 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; tag.tag = name.empty() ? "Entity" : name;
return entity; return entity;
} }
void Scene::DeleteEntity(Entity entity) void Scene::DeleteEntity(entt::entity entity)
{ {
registry.destroy(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() void Scene::OnUpdateRuntime()
{ {
{ {
@@ -38,6 +165,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; SceneCamera* main_camera = nullptr;
glm::mat4 main_transform{ 1.0f }; glm::mat4 main_transform{ 1.0f };
{ {
@@ -53,44 +214,54 @@ namespace OpenEngine {
} }
if (main_camera) { 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) { for (const auto& e : view) {
auto [transform, sprite] = view.get<TransformComponent, SpriteRendererComponent>(entity); 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) if (sprite.texture)
Renderer2D::DrawQuad(GetTransformFromComp(transform), Renderer2D::DrawQuad(GetTransformFromComp(transform),
sprite.texture, sprite.color, (int)entity, sprite.tiling_factor); sprite.texture, sprite.color, (int)entity, sprite.tiling_factor);
else else
Renderer2D::DrawQuad(GetTransformFromComp(transform), Renderer2D::DrawQuad(GetTransformFromComp(transform),
sprite.color, (int)entity); sprite.color, (int)entity);
*/
} }
Renderer2D::EndScene(); Renderer3D::EndScene();
} }
} }
} }
void Scene::OnUpdateEditor(EditorCamera& camera) void Scene::OnUpdateEditor(EditorCamera& camera)
{ {
Renderer2D::BeginScene(camera); Renderer3D::BeginScene(camera);
auto group = registry.group<TransformComponent>(entt::get<SpriteRendererComponent>); auto view = registry.view<TransformComponent, MeshComponent>();
for (auto entity : group)
{
auto [transform, sprite] = group.get<TransformComponent, SpriteRendererComponent>(entity);
if (sprite.texture) for (const auto& entity : view) {
Renderer2D::DrawQuad(GetTransformFromComp(transform), auto [transform, mesh] = view.get<TransformComponent, MeshComponent>(entity);
sprite.texture, sprite.color, (int)entity, sprite.tiling_factor);
else
Renderer2D::DrawQuad(GetTransformFromComp(transform),
sprite.color, (int)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));
}
Renderer3D::EndScene();
} }
void Scene::OnViewportResize(uint32_t width, uint32_t height) void Scene::OnViewportResize(uint32_t width, uint32_t height)
@@ -151,4 +322,34 @@ namespace OpenEngine {
void Scene::OnComponentAdded<NativeScriptComponent>(Entity entity, NativeScriptComponent& component) 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)
{
}
} }

View File

@@ -1,7 +1,9 @@
#include <cstdint>
#include <pch.hpp> #include <pch.hpp>
#include "core.hpp" #include "core.hpp"
#include <scene/scene_serializer.hpp> #include <scene/scene_serializer.hpp>
#include "renderer/renderer3d.hpp"
#include "scene/components.hpp" #include "scene/components.hpp"
#include "scene/entity.hpp" #include "scene/entity.hpp"
@@ -86,8 +88,10 @@ namespace OpenEngine {
static void SerializeEntity(YAML::Emitter& out, Entity entity) static void SerializeEntity(YAML::Emitter& out, Entity entity)
{ {
OE_CORE_ASSERT(entity.HasComponent<IDComponent>(), "Entity is missing UUID.");
out << YAML::BeginMap; out << YAML::BeginMap;
out << YAML::Key << "Entity" << YAML::Value << "412741205"; // Needs random out << YAML::Key << "Entity" << YAML::Value << entity.GetUUID(); // Needs random
if (entity.HasComponent<TagComponent>()) if (entity.HasComponent<TagComponent>())
{ {
@@ -113,8 +117,7 @@ namespace OpenEngine {
out << YAML::EndMap; // TransformComponent out << YAML::EndMap; // TransformComponent
} }
if (entity.HasComponent<CameraComponent>()) if (entity.HasComponent<CameraComponent>()) {
{
out << YAML::Key << "CameraComponent"; out << YAML::Key << "CameraComponent";
out << YAML::BeginMap; // CameraComponent out << YAML::BeginMap; // CameraComponent
@@ -149,6 +152,68 @@ namespace OpenEngine {
out << YAML::EndMap; // SpriteRendererComponent 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
}
out << YAML::EndMap; out << YAML::EndMap;
} }
@@ -195,7 +260,7 @@ namespace OpenEngine {
{ {
for (auto entity : 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; std::string name;
auto tagComponent = entity["TagComponent"]; auto tagComponent = entity["TagComponent"];
@@ -204,12 +269,12 @@ namespace OpenEngine {
OE_CORE_TRACE("Deserialized entity with ID = {0}, name = {1}", uuid, name); 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"]; auto transformComponent = entity["TransformComponent"];
if (transformComponent) if (transformComponent)
{ {
auto& tc = deserializedEntity.AddComponents<TransformComponent>(); auto& tc = deserializedEntity.AddComponent<TransformComponent>();
tc.translation = transformComponent["Translation"].as<glm::vec3>(); tc.translation = transformComponent["Translation"].as<glm::vec3>();
tc.rotation = transformComponent["Rotation"].as<glm::vec3>(); tc.rotation = transformComponent["Rotation"].as<glm::vec3>();
tc.scale = transformComponent["Scale"].as<glm::vec3>(); tc.scale = transformComponent["Scale"].as<glm::vec3>();
@@ -218,7 +283,7 @@ namespace OpenEngine {
auto cameraComponent = entity["CameraComponent"]; auto cameraComponent = entity["CameraComponent"];
if (cameraComponent) if (cameraComponent)
{ {
auto& cc = deserializedEntity.AddComponents<CameraComponent>(); auto& cc = deserializedEntity.AddComponent<CameraComponent>();
auto camera_props = cameraComponent["Camera"]; auto camera_props = cameraComponent["Camera"];
cc.camera.SetProjectionType((SceneCamera::ProjectionType)camera_props["ProjectionType"].as<int>()); cc.camera.SetProjectionType((SceneCamera::ProjectionType)camera_props["ProjectionType"].as<int>());
@@ -238,9 +303,69 @@ namespace OpenEngine {
auto spriteRendererComponent = entity["SpriteRendererComponent"]; auto spriteRendererComponent = entity["SpriteRendererComponent"];
if (spriteRendererComponent) if (spriteRendererComponent)
{ {
auto& src = deserializedEntity.AddComponents<SpriteRendererComponent>(); auto& src = deserializedEntity.AddComponent<SpriteRendererComponent>();
src.color = spriteRendererComponent["Color"].as<glm::vec4>(); 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>();
}
} }
} }

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 320 B

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 156 B

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