diff --git a/include/Core/CBoxShape.h b/include/Core/CBoxShape.h new file mode 100644 index 0000000..cc05ca4 --- /dev/null +++ b/include/Core/CBoxShape.h @@ -0,0 +1,20 @@ +#ifndef DAYDREAM_CRECTANGLESHAPE_H +#define DAYDREAM_CRECTANGLESHAPE_H + +#include "Core/Component.h" + +namespace dd +{ +namespace Components +{ + + struct RectangleShape : public Component + { + + }; + +} + +} + +#endif //DAYDREAM_CRECTANGLESHAPE_H diff --git a/include/Core/Engine.h b/include/Core/Engine.h old mode 100755 new mode 100644 index 1b05bf8..a367fc6 --- a/include/Core/Engine.h +++ b/include/Core/Engine.h @@ -35,41 +35,83 @@ #include "CTemplate.h" #include "Transform/TransformSystem.h" +#include "Physics/PhysicsSystem.h" +#include "Physics/CPhysics.h" + +#include "CBoxShape.h" + namespace dd { class Engine { public: - Engine(int argc, char* argv[]) - { - m_EventBroker = std::make_shared(); + Engine(int argc, char* argv[]) { + m_EventBroker = std::make_shared(); - m_Renderer = std::make_shared(); - m_Renderer->SetFullscreen(false); - m_Renderer->SetResolution(Rectangle(0, 0, 1920, 1080)); - m_Renderer->Initialize(); + m_Renderer = std::make_shared(); + m_Renderer->SetFullscreen(false); + m_Renderer->SetResolution(Rectangle(0, 0, 1920, 1080)); + m_Renderer->Initialize(); - m_InputManager = std::make_shared(m_Renderer->Window(), m_EventBroker); + m_InputManager = std::make_shared(m_Renderer->Window(), m_EventBroker); - m_World = std::make_shared(m_EventBroker); + m_World = std::make_shared(m_EventBroker); - //TODO: Move this out of engine.h - m_World->ComponentFactory.Register(); - m_World->SystemFactory.Register([this]() { return new Systems::TransformSystem(m_World.get(), m_EventBroker); }); - m_World->AddSystem(); - m_World->ComponentFactory.Register(); - m_World->ComponentFactory.Register(); - m_World->ComponentFactory.Register(); - m_World->Initialize(); + //TODO: Move this out of engine.h + m_World->ComponentFactory.Register(); + m_World->SystemFactory.Register( + [this]() { return new Systems::TransformSystem(m_World.get(), m_EventBroker); }); + m_World->AddSystem(); +// m_World->ComponentFactory.Register(); +// m_World->ComponentFactory.Register(); - { - auto ent = m_World->CreateEntity(); - std::shared_ptr transform = m_World->AddComponent(ent); - transform->Position = glm::vec3(0.f, 0.f, -10.f); - auto sprite = m_World->AddComponent(ent); - sprite->SpriteFile = "Textures/Core/ErrorTexture.png"; - } + m_World->ComponentFactory.Register(); + + m_World->ComponentFactory.Register(); + m_World->ComponentFactory.Register(); + m_World->SystemFactory.Register( + [this]() { return new Systems::PhysicsSystem(m_World.get(), m_EventBroker); }); + m_World->AddSystem(); + + m_World->ComponentFactory.Register(); + m_World->ComponentFactory.Register(); + m_World->Initialize(); + + { + auto ent = m_World->CreateEntity(); + std::shared_ptr transform = m_World->AddComponent(ent); + transform->Position = glm::vec3(0.f, 0.f, -10.f); + + std::shared_ptr sprite = m_World->AddComponent(ent); + sprite->SpriteFile = "Textures/Core/ErrorTexture.png"; + + std::shared_ptr boxShape = m_World->AddComponent(ent); + + std::shared_ptr physics = m_World->AddComponent(ent); + physics->Static = false; + + m_World->CommitEntity(ent); + } + + + { + auto ent = m_World->CreateEntity(); + std::shared_ptr transform = m_World->AddComponent(ent); + transform->Position = glm::vec3(0.f, -3.f, -9.f); + transform->Scale = glm::vec3(2.f, 0.5f, 1.f); + //transform->Orientation = glm::rotate(transform->Orientation, glm::radians(45.f), glm::vec3(0, 0, -1)); + + std::shared_ptr sprite = m_World->AddComponent(ent); + sprite->SpriteFile = "Textures/Core/ErrorTexture.png"; + + std::shared_ptr boxShape = m_World->AddComponent(ent); + + std::shared_ptr physics = m_World->AddComponent(ent); + physics->Static = true; + + m_World->CommitEntity(ent); + } m_LastTime = glfwGetTime(); } diff --git a/include/Physics/CPhysics.h b/include/Physics/CPhysics.h new file mode 100644 index 0000000..d6c3b21 --- /dev/null +++ b/include/Physics/CPhysics.h @@ -0,0 +1,20 @@ +#ifndef DAYDREAM_CPHYSICS_H +#define DAYDREAM_CPHYSICS_H +#include "Core/Component.h" + +namespace dd +{ +namespace Components +{ + + struct Physics: public Component + { + //idk if anything should be here :) + bool Static = true; + }; + +} + +} + +#endif //DAYDREAM_CPHYSICS_H diff --git a/include/Physics/EContact.h b/include/Physics/EContact.h new file mode 100644 index 0000000..b2d5f57 --- /dev/null +++ b/include/Physics/EContact.h @@ -0,0 +1,27 @@ +// +// Created by Viktor on 10/09/2015. +// + +#ifndef Events_ECONTACT_h__ +#define Events_ECONTACT_h__ + + +#include +#include "Core/EventBroker.h" +#include "Core/Entity.h" + +namespace dd +{ + namespace Events + { + struct Contact : Event + { + EntityID Entity1; + EntityID Entity2; + glm::vec2 ContactPoint; + }; + } + +} + +#endif //Events_ECONTACT_h__ diff --git a/include/Physics/PhysicsSystem.h b/include/Physics/PhysicsSystem.h new file mode 100644 index 0000000..add84dc --- /dev/null +++ b/include/Physics/PhysicsSystem.h @@ -0,0 +1,94 @@ +#ifndef DAYDREAM_PHYSICSSYSTEM_H +#define DAYDREAM_PHYSICSSYSTEM_H + +#include + +#include "Core/System.h" +#include "Core/World.h" +#include "Core/CBoxShape.h" +#include "Physics/CPhysics.h" +#include +#include "Core/CTransform.h" +#include "Transform/TransformSystem.h" +#include "Physics/EContact.h" + + +namespace dd +{ + +namespace Systems +{ + +//KOLLA http://box2d.org/manual.pdf p52 Pre-Solve Event + +class PhysicsSystem : public System +{ + friend class ContractListener; + +public: + PhysicsSystem(World* world, std::shared_ptr eventBroker) + : System(world, eventBroker) {} + + ~PhysicsSystem(); + + void RegisterComponents(ComponentFactory* cf) override; + void Initialize() override; + + // Called once per system every tick + void Update(double dt) override; + // Called once for every entity in the world every tick + void UpdateEntity(double dt, EntityID entity, EntityID parent) override; + + // Called when components are committed to an entity + void OnEntityCommit(EntityID entity) override; + + // Called when an entity is removed + void OnEntityRemoved(EntityID entity) override; + +private: + b2Vec2 m_Gravity; + b2World* m_PhysicsWorld; + float m_TimeStep; + int m_VelocityIterations, m_PositionIterations; + + std::unordered_map m_EntitiesToBodies; + std::unordered_map m_BodiesToEntities; + + void CreateBody(EntityID entity); + + + class ContactListener : public b2ContactListener + { + public: + ContactListener(PhysicsSystem* physicsSystem) + : m_PhysicsSystem(physicsSystem) { } + + void BeginContact(b2Contact* contact) + { + b2Vec2 contactPoint = contact->GetManifold()->localPoint; + + Events::Contact e; + e.ContactPoint = glm::vec2(contactPoint.x, contactPoint.y); + e.Entity1 = m_PhysicsSystem->m_BodiesToEntities[contact->GetFixtureA()->GetBody()]; + e.Entity2 = m_PhysicsSystem->m_BodiesToEntities[contact->GetFixtureB()->GetBody()]; + + m_PhysicsSystem->EventBroker->Publish(e); + } + void EndContact(b2Contact* contact) + { /* handle end event */ } + void PreSolve(b2Contact* contact, const b2Manifold* oldManifold) + { /* handle pre-solve event */ } + void PostSolve(b2Contact* contact, const b2ContactImpulse* impulse) + { /* handle post-solve event */ } + + private: + PhysicsSystem* m_PhysicsSystem; + }; + + ContactListener* m_ContactListener; +}; + +} +} + +#endif //DAYDREAM_PHYSICSSYSTEM_H diff --git a/src/game/CMakeLists.txt b/src/game/CMakeLists.txt index fc38081..c1c8611 100755 --- a/src/game/CMakeLists.txt +++ b/src/game/CMakeLists.txt @@ -69,7 +69,7 @@ set(SOURCE_FILES ${SOURCE_FILES_Rendering} ${SOURCE_FILES_Transform} ${SOURCE_FILES_Game} -) + Physics/PhysicsSystem.cpp ../../include/Physics/PhysicsSystem.h ../../include/Core/CBoxShape.h ../../include/Physics/CPhysics.h ../../include/Physics/EContact.h) if(CMAKE_COMPILER_IS_GNUCXX) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread") diff --git a/src/game/Physics/PhysicsSystem.cpp b/src/game/Physics/PhysicsSystem.cpp new file mode 100644 index 0000000..b9e2421 --- /dev/null +++ b/src/game/Physics/PhysicsSystem.cpp @@ -0,0 +1,136 @@ +#include "PrecompiledHeader.h" +#include "Physics/PhysicsSystem.h" + + + +void dd::Systems::PhysicsSystem::RegisterComponents(ComponentFactory* cf) +{ + +} + +void dd::Systems::PhysicsSystem::Initialize() +{ + m_ContactListener = new ContactListener(this); + + m_Gravity = b2Vec2(0.f, -9.82f); + m_PhysicsWorld = new b2World(m_Gravity); + + m_TimeStep = 1.f/60.f; + m_VelocityIterations = 6; + m_PositionIterations = 2; + + + m_PhysicsWorld->SetContactListener(m_ContactListener); +} + +void dd::Systems::PhysicsSystem::Update(double dt) +{ + m_PhysicsWorld->Step(m_TimeStep, m_VelocityIterations, m_PositionIterations); + + for(auto i : m_EntitiesToBodies) + { + EntityID entity = i.first; + b2Body* body = i.second; + + auto transformComponent = m_World->GetComponent(entity); + + + if(m_World->GetEntityParent(entity) == 0) { + b2Vec2 position = body->GetPosition(); + transformComponent->Position.x = position.x; + transformComponent->Position.y = position.y; + + float angle = body->GetAngle(); + + //TODO: CHECK IF THIS IS CORRECT + transformComponent->Orientation = glm::quat(glm::vec3(0, 0, -angle)); + } + // auto absoluteTransform = m_World->GetSystem()-> + } +} + +void dd::Systems::PhysicsSystem::UpdateEntity(double dt, EntityID entity, EntityID parent) +{ + +} + + +void dd::Systems::PhysicsSystem::OnEntityCommit(EntityID entity) +{ + + auto physicsComponent = m_World->GetComponent(entity); + if(physicsComponent) + CreateBody(entity); + +} + + +void dd::Systems::PhysicsSystem::OnEntityRemoved(EntityID entity) +{ + +} + + +void dd::Systems::PhysicsSystem::CreateBody(EntityID entity) +{ + auto physicsComponent = m_World->GetComponent(entity); + if(!physicsComponent){ + LOG_ERROR("No PhysicsComponent in CreateBody"); + return; + } + + + auto transformComponent = m_World->GetComponent(entity); + if(!transformComponent) { + LOG_ERROR("No TransformComponent in CreateBody"); + return; + } + + auto absoluteTransform = m_World->GetSystem()->AbsoluteTransform(entity); + + b2BodyDef bodyDef; + bodyDef.position.Set(absoluteTransform.Position.x, absoluteTransform.Position.y); + + + bodyDef.angle = glm::degrees(-glm::eulerAngles(absoluteTransform.Orientation).z); //TODO: CHECK IF THIS IS CORRECT + + if(physicsComponent->Static) + bodyDef.type = b2_staticBody; + else + bodyDef.type = b2_dynamicBody; + + b2Body* body = m_PhysicsWorld->CreateBody(&bodyDef); + + b2PolygonShape pShape; + + auto boxComponent = m_World->GetComponent(entity); + if(boxComponent){ + + pShape.SetAsBox(absoluteTransform.Scale.x/4, absoluteTransform.Scale.y/4); //TODO: THIS SUCKS DUDE + } + + if(physicsComponent->Static){ + body->CreateFixture(&pShape, 0); //Density kanske ska vara 0 på statiska kroppar + } + else{ + //TODO: FIX THIS SHIT INTO COMPONENTS + b2FixtureDef fixtureDef; + fixtureDef.shape = &pShape; + fixtureDef.density = 1.f; + fixtureDef.restitution = 1.0f; + fixtureDef.friction = 0.3f; + body->CreateFixture(&fixtureDef); + + } + + m_EntitiesToBodies.insert(std::make_pair(entity, body)); + m_BodiesToEntities.insert(std::make_pair(body, entity)); +} + +dd::Systems::PhysicsSystem::~PhysicsSystem() +{ + if (m_ContactListener != nullptr) { + delete m_ContactListener; + m_ContactListener = nullptr; + } +}