diff --git a/editor/include/editor.hpp b/editor/include/editor.hpp index fc809c8..e054478 100755 --- a/editor/include/editor.hpp +++ b/editor/include/editor.hpp @@ -3,9 +3,15 @@ #include +#include "open_engine/renderer/renderer3d.hpp" +#include "open_engine/scene/components.hpp" #include "panels/content_browser.hpp" #include "panels/scene_hierarchy.hpp" +#include +#include +#include +#include #include #include #include @@ -95,12 +101,12 @@ namespace OpenEngine { // ============================================= Entity cube = scene->CreateEntity("cube"); - - cube.AddComponent(); + auto& tc = cube.AddComponent(); Ref mesh = CreateCube(cube); - cube.AddComponent(mesh); + auto& mc = cube.AddComponent(mesh); + mc.primitive_type = PrimitiveType::Cube; // ============================================= Entity quad = scene->CreateEntity("quad"); @@ -109,7 +115,8 @@ namespace OpenEngine { Ref quad_mesh = CreateQuad(quad, true); - quad.AddComponent(quad_mesh); + auto& mc3 = quad.AddComponent(quad_mesh); + mc3.primitive_type = PrimitiveType::Quad; // ============================================= Entity cube2 = scene->CreateEntity("cube2"); @@ -118,7 +125,8 @@ namespace OpenEngine { Ref mesh2 = CreateCube(cube2); - cube2.AddComponent(mesh2); + auto& mc2 = cube2.AddComponent(mesh2); + mc2.primitive_type = PrimitiveType::Cube; /* auto view = scene->GetRegistry().view(); @@ -562,10 +570,12 @@ namespace OpenEngine { void OnScenePlay() { state = PlayState::Play; + scene->OnRuntimeStart(); } void OnSceneStop() { state = PlayState::Edit; + scene->OnRuntimeStop(); } private: diff --git a/editor/include/editor_component.hpp b/editor/include/editor_component.hpp index c9fd455..5630dfc 100644 --- a/editor/include/editor_component.hpp +++ b/editor/include/editor_component.hpp @@ -18,6 +18,8 @@ namespace OpenEngine { void CameraOnImGuiRender(entt::registry& registry, entt::entity entity); void MeshOnImGuiRender(entt::registry®istry, entt::entity entity); void MaterialOnImGuiRender(entt::registry& registry, entt::entity entity); + void BodyOnImGuiRender(entt::registry& registry, entt::entity entity); + void ShapeOnImGuiRender(entt::registry& registry, entt::entity entity); } #endif // EDITOR_COMPONENT_HPP diff --git a/editor/src/editor_component.cpp b/editor/src/editor_component.cpp index 0c33a67..6b1d445 100644 --- a/editor/src/editor_component.cpp +++ b/editor/src/editor_component.cpp @@ -95,6 +95,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) @@ -221,16 +222,27 @@ namespace OpenEngine { { auto& material = registry.get(entity).material; - auto& albedo = material.albedo; - auto& roughness = material.roughness; - auto& metallic = material.metallic; - auto& ambient = material.ambient_strength; - auto& specular = material.specular_strength; + 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); + } - ImGui::SliderFloat4("Albedo", glm::value_ptr(albedo), 0, 1); - ImGui::SliderFloat("Roughness", &roughness, 0, 1); - ImGui::SliderFloat("Metallic", &metallic, 0, 1); - ImGui::SliderFloat("Ambient strength", &ambient, 0, 1); - ImGui::SliderFloat("Specular strength", &specular, 0, 10); + void BodyOnImGuiRender(entt::registry ®istry, entt::entity entity) + { + auto& body_comp = registry.get(entity); + + 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); + } + + void ShapeOnImGuiRender(entt::registry ®istry, entt::entity entity) + { + auto& shape_comp = registry.get(entity); + + ImGui::SliderFloat("Bounciness", &shape_comp.restitution, 0, 1); + ImGui::SliderFloat("Friction", &shape_comp.friction, 0, 1); } } diff --git a/editor/src/panels/scene_hierarchy.cpp b/editor/src/panels/scene_hierarchy.cpp index 0c716ad..8b7e41c 100644 --- a/editor/src/panels/scene_hierarchy.cpp +++ b/editor/src/panels/scene_hierarchy.cpp @@ -24,6 +24,8 @@ namespace OpenEngine { RegisterDrawer("Camera", &CameraOnImGuiRender); RegisterDrawer("Mesh", &MeshOnImGuiRender); RegisterDrawer("Material", &MaterialOnImGuiRender); + RegisterDrawer("Physics Body", &BodyOnImGuiRender); + RegisterDrawer("Physics Shape", &ShapeOnImGuiRender); scene = context; selected_context = {}; @@ -57,6 +59,16 @@ namespace OpenEngine { selected_context.AddComponent(); ImGui::CloseCurrentPopup(); } + if (!selected_context.HasComponent()) + if (ImGui::MenuItem("Physics body")) { + selected_context.AddComponent(); + ImGui::CloseCurrentPopup(); + } + if (!selected_context.HasComponent()) + if (ImGui::MenuItem("Physics shape")) { + selected_context.AddComponent(); + ImGui::CloseCurrentPopup(); + } } void EntityPopup(Ref& scene) @@ -201,17 +213,18 @@ namespace OpenEngine { 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(); TagOnImGuiRender(reg, entity); + // TODO: Defer deletion like the entities? + std::vector pending_deletion; // 0 is null/invalid in entt usually - std::vector component_to_delete; // 0 is null/invalid in entt usually - // Iterate through every component type entt knows about + // Iterate through every component type entt knows about for (auto [id, storage] : reg.storage()) { if (storage.contains(handle)) { if (drawers.contains(id)) { @@ -234,20 +247,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(); + } } } diff --git a/imgui.ini b/imgui.ini index 7fa393d..1e264a3 100644 --- a/imgui.ini +++ b/imgui.ini @@ -1,6 +1,6 @@ [Window][WindowOverViewport_11111111] Pos=0,24 -Size=1272,1363 +Size=2552,1363 Collapsed=0 [Window][Debug##Default] @@ -15,19 +15,19 @@ Collapsed=0 DockId=0x00000003,0 [Window][Properties] -Pos=822,24 +Pos=2102,24 Size=450,805 Collapsed=0 DockId=0x00000007,0 [Window][Viewport] Pos=226,61 -Size=594,956 +Size=1874,956 Collapsed=0 DockId=0x00000012,0 [Window][Dear ImGui Demo] -Pos=822,831 +Pos=2102,831 Size=450,556 Collapsed=0 DockId=0x00000008,0 @@ -144,7 +144,7 @@ DockId=0x00000012,1 [Window][Assets] Pos=226,1019 -Size=594,368 +Size=1874,368 Collapsed=0 DockId=0x0000000C,0 @@ -156,12 +156,12 @@ DockId=0x0000000F,0 [Window][##play_state_bar] Pos=226,24 -Size=594,35 +Size=1874,35 Collapsed=0 DockId=0x00000011,0 [Docking][Data] -DockSpace ID=0x08BD597D Window=0x1BBC0F80 Pos=0,24 Size=1272,1363 Split=X +DockSpace ID=0x08BD597D Window=0x1BBC0F80 Pos=0,24 Size=2552,1363 Split=X DockNode ID=0x00000005 Parent=0x08BD597D SizeRef=820,1386 Split=X DockNode ID=0x00000001 Parent=0x00000005 SizeRef=224,1386 Split=Y Selected=0xE601B12F DockNode ID=0x00000003 Parent=0x00000001 SizeRef=255,417 Selected=0x553E127E @@ -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=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,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=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,769 Selected=0x8C72BEA8 - DockNode ID=0x00000008 Parent=0x00000006 SizeRef=444,531 Selected=0x5E5F7166 + DockNode ID=0x00000007 Parent=0x00000006 SizeRef=444,810 Selected=0x8C72BEA8 + DockNode ID=0x00000008 Parent=0x00000006 SizeRef=444,559 Selected=0x5E5F7166 diff --git a/open_engine/include/open_engine/physics.hpp b/open_engine/include/open_engine/physics.hpp new file mode 100644 index 0000000..317d918 --- /dev/null +++ b/open_engine/include/open_engine/physics.hpp @@ -0,0 +1,188 @@ +#ifndef PHYSICS_HPP +#define PHYSICS_HPP + +#include "logging.hpp" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +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); +}; + +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 tmp_allocator; + Ref 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 diff --git a/open_engine/include/open_engine/scene/components.hpp b/open_engine/include/open_engine/scene/components.hpp index aae8457..a896b12 100644 --- a/open_engine/include/open_engine/scene/components.hpp +++ b/open_engine/include/open_engine/scene/components.hpp @@ -6,7 +6,14 @@ #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 +#include +#include +#include +#include +#include #include #include #include @@ -110,6 +117,32 @@ namespace OpenEngine { : material(material) {}; }; + struct PhysicsBodyComponent + { + enum class BodyType { Static = 0, Kinematic, Dynamic }; + + BodyID body; + + BodyType type = BodyType::Dynamic; + + float linear_damping = 0.05f; + float angular_damping = 0.05f; + float gravity_factor = 1.0f; + + EActivation initial_activation_state = EActivation::Activate; + + PhysicsBodyComponent() = default; + PhysicsBodyComponent(const PhysicsBodyComponent&) = default; + }; + + struct PhysicsShapeComponent + { + ShapeRefC shape; + + float restitution = 0.8f; + float friction = 0.5f; + }; + } #endif // COMPONENTS_HPP diff --git a/open_engine/include/open_engine/scene/scene.hpp b/open_engine/include/open_engine/scene/scene.hpp index a4cb2cc..91dd480 100644 --- a/open_engine/include/open_engine/scene/scene.hpp +++ b/open_engine/include/open_engine/scene/scene.hpp @@ -2,7 +2,9 @@ #define SCENE_HPP #include "open_engine/renderer/editor_camera.hpp" +#include "open_engine/physics.hpp" +#include #include #include #include @@ -17,6 +19,9 @@ namespace OpenEngine { Scene() = default; ~Scene() = default; + void OnRuntimeStart(); + void OnRuntimeStop(); + Entity CreateEntity(const std::string& name = std::string()); void DeleteEntity(entt::entity entity); void MarkEntityForDeletion(Entity entity); @@ -28,20 +33,27 @@ namespace OpenEngine { void OnViewportResize(uint32_t width, uint32_t height); entt::registry& GetRegistry() { return registry; }; - + PhysicsEngine& GetPhysicsEngine() { return physics_engine; }; Entity GetPrimaryCamera(); private: + void OnUpdatePhysics(); + template 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 pending_deletion; + //BodyID sphere_id; + friend class SceneSerializer; friend class Entity; }; diff --git a/open_engine/src/open_engine/physics.cpp b/open_engine/src/open_engine/physics.cpp new file mode 100644 index 0000000..7fde043 --- /dev/null +++ b/open_engine/src/open_engine/physics.cpp @@ -0,0 +1,71 @@ +#include + +#include +#include + +#include +#include +#include +#include +#include + +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(10 * 1024 * 1024); + + job_system = CreateRef(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: Move out of here and 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); + } +} diff --git a/open_engine/src/open_engine/scene/scene.cpp b/open_engine/src/open_engine/scene/scene.cpp old mode 100644 new mode 100755 index 5fe217d..626b18d --- a/open_engine/src/open_engine/scene/scene.cpp +++ b/open_engine/src/open_engine/scene/scene.cpp @@ -1,14 +1,85 @@ -#include -#include +#include "logging.hpp" #include #include #include #include #include +#include + +#include +#include +#include +#include +#include +#include namespace OpenEngine { + void Scene::OnRuntimeStart() + { + body_interface = &physics_engine.GetBodyInterface(); + + BoxShapeSettings floor_shape_settings(Vec3(100.0f, 1.0f, 100.0f)); + floor_shape_settings.SetEmbedded(); // A ref counted object on the stack (base class RefTarget) should be marked as such to prevent it from being freed when its reference count goes to 0. + + // Create the shape + ShapeSettings::ShapeResult floor_shape_result = floor_shape_settings.Create(); + ShapeRefC floor_shape = floor_shape_result.Get(); // We don't expect an error here, but you can check floor_shape_result for HasError() / GetError() + + // Create the settings for the body itself. Note that here you can also set other properties like the restitution / friction. + BodyCreationSettings floor_settings(floor_shape, RVec3(0.0_r, -1.0_r, 0.0_r), Quat::sIdentity(), EMotionType::Static, Layers::NON_MOVING); + + // Create the actual rigid body + Body *floor = body_interface->CreateBody(floor_settings); // Note that if we run out of bodies this can return nullptr + + // Add it to the world + body_interface->AddBody(floor->GetID(), EActivation::DontActivate); + + auto view = registry.view(); + for (auto e : view) { + Entity entity = { e, this }; + + TransformComponent* tc; + if (entity.HasComponent()) + tc = &entity.GetComponents(); + auto& pbc = entity.GetComponents(); + + PhysicsShapeComponent* psc; + if (entity.HasComponent()) + psc = &entity.GetComponents(); + + glm::vec3& pos = tc->translation; + BodyCreationSettings settings( + new BoxShape(Vec3(0.5f, 0.5f, 0.5f)), + Vec3(pos.x, pos.y, pos.z), + Quat::sIdentity(), + EMotionType::Dynamic, + Layers::MOVING); + settings.mLinearDamping = pbc.linear_damping; + settings.mAngularDamping = pbc.angular_damping; + settings.mGravityFactor = pbc.gravity_factor; + + settings.mRestitution = psc->restitution; + settings.mFriction = psc->friction; + + pbc.body = body_interface->CreateAndAddBody(settings, EActivation::Activate); + } + } + + void Scene::OnRuntimeStop() + { + auto view = registry.view(); + for (auto e : view) { + Entity entity = { e, this }; + + auto& pbc = entity.GetComponents(); + + physics_engine.GetBodyInterface().RemoveBody(pbc.body); + physics_engine.GetBodyInterface().DestroyBody(pbc.body); + } + } + Entity Scene::CreateEntity(const std::string& name) { Entity entity = { registry.create(), this }; @@ -37,6 +108,22 @@ namespace OpenEngine { 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() { { @@ -54,6 +141,40 @@ namespace OpenEngine { }); } + auto view = registry.view(); + for (auto e : view) { + Entity entity = { e, this }; + + auto& pos = entity.GetComponents().translation; + auto& body = entity.GetComponents(); + + body_interface->SetPosition(body.body, { pos.x, pos.y, pos.z }, EActivation::Activate); + + PhysicsShapeComponent* shape; + if (entity.HasComponent()) { + shape = &entity.GetComponents(); + + body_interface->SetRestitution(body.body, shape->restitution); + body_interface->SetFriction(body.body, shape->friction); + body_interface->SetGravityFactor(body.body, body.gravity_factor); + } + + } + + OnUpdatePhysics(); + + for (auto e : view) { + Entity entity = { e, this }; + + auto& transform = entity.GetComponents(); + auto& body = entity.GetComponents(); + + auto position = physics_engine.GetBodyInterface().GetPosition(body.body); + transform.translation.x = position.GetX(); + transform.translation.y = position.GetY(); + transform.translation.z = position.GetZ(); + } + SceneCamera* main_camera = nullptr; glm::mat4 main_transform{ 1.0f }; { @@ -75,6 +196,7 @@ namespace OpenEngine { for (const auto& entity : view) { auto [transform, mesh] = view.get(entity); + Material material; Entity _entity(entity, this); @@ -186,4 +308,14 @@ namespace OpenEngine { void Scene::OnComponentAdded(Entity entity, MaterialComponent& component) { } + + template<> + void Scene::OnComponentAdded(Entity entity, PhysicsBodyComponent& component) + { + } + + template<> + void Scene::OnComponentAdded(Entity entity, PhysicsShapeComponent& component) + { + } } diff --git a/open_engine/src/open_engine/scene/scene_serializer.cpp b/open_engine/src/open_engine/scene/scene_serializer.cpp index 26600b5..c217544 100644 --- a/open_engine/src/open_engine/scene/scene_serializer.cpp +++ b/open_engine/src/open_engine/scene/scene_serializer.cpp @@ -274,19 +274,20 @@ namespace OpenEngine { if (mesh_component) { auto& mesh = deserializedEntity.AddComponent(); + mesh.primitive_type = (PrimitiveType)mesh_component["MeshType"].as(); switch (mesh.primitive_type) { - case OpenEngine::PrimitiveType::Quad: - { + case OpenEngine::PrimitiveType::Quad: { mesh.mesh = CreateQuad((uint32_t)deserializedEntity); break; } - case OpenEngine::PrimitiveType::Cube: - { + case OpenEngine::PrimitiveType::Cube: { mesh.mesh = CreateCube((uint32_t)deserializedEntity); break; } - default: - break; + default: { + OE_CORE_ASSERT(false, "No mesh"); + break; + } } } @@ -300,9 +301,6 @@ namespace OpenEngine { material.material.ambient_strength = material_component["AmbiantStrength"].as(); material.material.specular_strength = material_component["SpecularStrength"].as(); } - - auto mesh = CreateCube((uint32_t)deserializedEntity); - deserializedEntity.AddComponent(mesh); } } diff --git a/untitled_persp.oes b/untitled_persp.oes deleted file mode 100644 index 9532713..0000000 --- a/untitled_persp.oes +++ /dev/null @@ -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 \ No newline at end of file