diff --git a/include/Core/Engine.h b/include/Core/Engine.h index 45a9dcc..8245052 100755 --- a/include/Core/Engine.h +++ b/include/Core/Engine.h @@ -52,6 +52,8 @@ #include "Physics/CRectangleShape.h" #include "Physics/ESetImpulse.h" #include "Physics/CWaterVolume.h" +#include "Physics/CParticle.h" +#include "Physics/CParticleEmitter.h" #include "Game/EGameStart.h" #include "Sound/EPlaySound.h" @@ -129,6 +131,8 @@ public: m_World->ComponentFactory.Register(); m_World->ComponentFactory.Register(); m_World->ComponentFactory.Register(); + m_World->ComponentFactory.Register(); + m_World->ComponentFactory.Register(); m_World->Initialize(); @@ -165,7 +169,7 @@ public: pl->Radius = 20.f; pl->Diffuse = glm::vec3(0.8f, 0.7f, 0.05f); auto model = m_World->AddComponent(t_Light); - model->ModelFile = "Core/UnitSphere.obj"; + model->ModelFile = "Models/Core/UnitSphere.obj"; m_World->CommitEntity(t_Light); } { @@ -176,7 +180,7 @@ public: pl->Radius = 15.f; pl->Diffuse = glm::vec3(0.1f, 0.5f, 0.8f); auto model = m_World->AddComponent(t_Light); - model->ModelFile = "Core/UnitSphere.obj"; + model->ModelFile = "Models/Core/UnitSphere.obj"; m_World->CommitEntity(t_Light); } @@ -188,7 +192,7 @@ public: transform->Scale = glm::vec3(6.f, 6.f, 10.f); auto model = m_World->AddComponent(t_halfPipe); model->ModelFile = "Models/Test/halfpipe/Halfpipe.obj"; - model->Color = glm::vec4(1.f, 1.f, 1.f, 0.3f); + model->Color = glm::vec4(1.f, 0.f, 0.f, 0.3f); m_World->CommitEntity(t_halfPipe); } @@ -203,16 +207,44 @@ public: m_World->CommitEntity(background); } - //Water test - { - auto t_waterBody = m_World->CreateEntity(); - auto transform = m_World->AddComponent(t_waterBody); - transform->Position = glm::vec3(0.f, -0.5f, -10.f); - transform->Scale = glm::vec3(1.f, 1.f, 1.f); - auto water = m_World->AddComponent(t_waterBody); - auto body = m_World->AddComponent(t_waterBody); - m_World->CommitEntity(t_waterBody); - } + //ParticleTest +// { +// auto Pe = m_World->CreateEntity(); +// auto transform = m_World->AddComponent(Pe); +// auto particleEmitter= m_World->AddComponent(Pe); +// +// transform->Position = glm::vec3(0.f, -5.f, -10.f); +// particleEmitter->GravityScale = 0.0f; +// particleEmitter->SpawnRate = 1.0f; +// +// { +// auto Pt = m_World->CreateEntity(Pe); +// auto PtTransform = m_World->AddComponent(Pt); +// auto PtSprite = m_World->AddComponent(Pt); +// //auto PtModel = m_World->AddComponent(Pt); +// auto PtParticle = m_World->AddComponent(Pt); +// auto PtTemplate = m_World->AddComponent(Pt); +// +// PtTransform->Velocity = glm::vec3(1.0f, 0.f, 0.f); +// PtTransform->Position = transform->Position; +// PtSprite->SpriteFile = "Textures/Ball.png"; +// +// //PtModel->ModelFile = "Models/Brick/Brick.obj"; +// PtParticle->LifeTime = 1000.f; +// PtParticle->Flags = ParticleFlags::Type::powderParticle; +// } +// m_World->CommitEntity(Pe); +// } + +// { +// auto Pt = m_World->CreateEntity(); +// auto PtTransform = m_World->AddComponent(Pt); +// auto PtSprite = m_World->AddComponent(Pt); +// +// PtTransform->Position = glm::vec3(2.f, 0.f, -10.f); +// PtSprite->SpriteFile = "Textures/Ball.png"; +// } + //Water test { auto t_waterBody = m_World->CreateEntity(); @@ -371,7 +403,7 @@ public: // Swap event queues to get fresh input data in the read queue //m_EventBroker->Swap(); - ResourceManager::Update(); + //ResourceManager::Update(); if (m_GameIsRunning) { m_World->Update(dt); } @@ -460,7 +492,6 @@ public: auto spriteComponent = m_World->GetComponent(entity); if (spriteComponent) { - std::string normal = spriteComponent->NormalTexture; std::string spec = spriteComponent->SpecularTexture; @@ -483,7 +514,6 @@ public: EnqueueSprite(texturediff, texturenorm, texturespec, modelMatrix, spriteComponent->Color, absoluteTransform.Position.z); } } - } //TODO: Get this out of engine.h diff --git a/include/Physics/CParticle.h b/include/Physics/CParticle.h new file mode 100755 index 0000000..baec66d --- /dev/null +++ b/include/Physics/CParticle.h @@ -0,0 +1,65 @@ +#ifndef COMPONENTS_PARTICLE_H__ +#define COMPONENTS_PARTICLE_H__ +#include "Core/Component.h" + +namespace dd { + +namespace ParticleFlags { + +enum Type { + waterParticle = 0, + zombieParticle = 1 << 1, + wallParticle = 1 << 2, + springParticle = 1 << 3, + elasticParticle = 1 << 4, + viscousParticle = 1 << 5, + powderParticle = 1 << 6, + tensileParticle = 1 << 7, + colorMixingParticle = 1 << 8, + destructionListenerParticle = 1 << 9, + barrierParticle = 1 << 10, + staticPressureParticle = 1 << 11, + reactiveParticle = 1 << 12, + repulsiveParticle = 1 << 13, + fixtureContactListenerParticle = 1 << 14, + particleContactListenerParticle = 1 << 15, + fixtureContactFilterParticle = 1 << 16, + particleContactFilterParticle = 1 << 17 +}; +} + +namespace Components +{ + +struct Particle : public Component +{ + float Radius = 0.5f; + float LifeTime = 5.0f; + + ParticleFlags::Type Flags = + ParticleFlags::Type::waterParticle | + ParticleFlags::Type::zombieParticle | + ParticleFlags::Type::wallParticle | + ParticleFlags::Type::springParticle | + ParticleFlags::Type::elasticParticle | + ParticleFlags::Type::viscousParticle | + ParticleFlags::Type::powderParticle | + ParticleFlags::Type::tensileParticle | + ParticleFlags::Type::colorMixingParticle | + ParticleFlags::Type::destructionListenerParticle | + ParticleFlags::Type::barrierParticle | + ParticleFlags::Type::staticPressureParticle | + ParticleFlags::Type::reactiveParticle | + ParticleFlags::Type::repulsiveParticle | + ParticleFlags::Type::fixtureContactListenerParticle | + ParticleFlags::Type::particleContactListenerParticle | + ParticleFlags::Type::fixtureContactFilterParticle | + ParticleFlags::Type::particleContactFilterParticle; + +}; + +} + +} + +#endif \ No newline at end of file diff --git a/include/Physics/CParticleEmitter.h b/include/Physics/CParticleEmitter.h new file mode 100755 index 0000000..a965a84 --- /dev/null +++ b/include/Physics/CParticleEmitter.h @@ -0,0 +1,25 @@ +#ifndef COMPONENTS_PARTICLEEMITTER_H__ +#define COMPONENTS_PARTICLEEMITTER_H__ +#include "Core/Component.h" + +namespace dd +{ +namespace Components +{ + +struct ParticleEmitter : public Component +{ + int Amount = 10.f; + float InitialSpeed = 1.f; + double SpawnRate = 1.f; + double TimeSinceLastSpawn = 0; + + //ParticleSystem variables + float GravityScale = 1.0f; +}; + +} + +} + +#endif \ No newline at end of file diff --git a/include/Physics/PhysicsSystem.h b/include/Physics/PhysicsSystem.h index 79e1205..02e3e06 100755 --- a/include/Physics/PhysicsSystem.h +++ b/include/Physics/PhysicsSystem.h @@ -18,6 +18,9 @@ #include "Physics/CWaterVolume.h" #include "Game/CBall.h" #include "Rendering/CSprite.h" +#include "Physics/CParticle.h" +#include "Physics/CParticleEmitter.h" +#include "Core/CTemplate.h" namespace dd @@ -66,18 +69,29 @@ private: std::unordered_map m_BodiesToEntities; void CreateBody(EntityID entity); - void CreateParticleSystem(float radius); std::vector m_ParticleSystem; std::vector t_ParticleGroup; - std::unordered_map m_EntitiesToParticleHandle; - std::unordered_map m_ParticleHandleToEntities; + std::vector> m_EntitiesToParticleHandle; + std::vector> m_ParticleHandleToEntities; + b2ParticleSystem* CreateParticleSystem(float radius, float gravityScale); void InitializeWater(); - void SyncWater(); //TODO: Probably remove this void CreateParticleGroup(EntityID entity); + void CreateParticleEmitter(EntityID entity); + void UpdateParticleEmitters(double dt); //TODO: Remove them and particles if needed. + //TODO: Fill struct with info needed. + struct ParticleEmitter + { + std::vector ParticleSystem; + std::vector ParticleEmitter; + std::vector ParticleTemplate; + }; + ParticleEmitter m_ParticleEmitters; + + //TODO: Struct med listor är bättre än en lista med structs struct Impulse { b2Body* Body; diff --git a/src/game/Core/Renderer.cpp b/src/game/Core/Renderer.cpp index caf1160..6abf221 100755 --- a/src/game/Core/Renderer.cpp +++ b/src/game/Core/Renderer.cpp @@ -312,7 +312,7 @@ void dd::Renderer::Draw(RenderQueueCollection& rq) void dd::Renderer::DrawDeferred(RenderQueue &objects, RenderQueue &lights) { // Pass #1: Fill G-buffers - glDisable(GL_CULL_FACE); + glEnable(GL_CULL_FACE); glCullFace(GL_BACK); glDepthMask(GL_TRUE); glEnable(GL_DEPTH_TEST); @@ -444,6 +444,7 @@ void dd::Renderer::DrawScene(RenderQueue &objects, ShaderProgram &program) glUniformMatrix4fv(glGetUniformLocation(shaderProgramHandle, "V"), 1, GL_FALSE, glm::value_ptr(viewMatrix)); glUniform4fv(glGetUniformLocation(shaderProgramHandle, "Color"), 1, glm::value_ptr(modelJob->Color)); + glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, spriteJob->DiffuseTexture); glActiveTexture(GL_TEXTURE1); diff --git a/src/game/Physics/PhysicsSystem.cpp b/src/game/Physics/PhysicsSystem.cpp index c8623b4..e13d374 100755 --- a/src/game/Physics/PhysicsSystem.cpp +++ b/src/game/Physics/PhysicsSystem.cpp @@ -30,9 +30,8 @@ void dd::Systems::PhysicsSystem::Initialize() void dd::Systems::PhysicsSystem::InitializeWater() { float radius = 0.13f; - - - CreateParticleSystem(radius); + float gravityScale = 1.0f; + CreateParticleSystem(radius, gravityScale); } bool dd::Systems::PhysicsSystem::SetImpulse(const Events::SetImpulse &event) @@ -58,24 +57,22 @@ bool dd::Systems::PhysicsSystem::SetImpulse(const Events::SetImpulse &event) return true; } -void dd::Systems::PhysicsSystem::Update(double dt) -{ +void dd::Systems::PhysicsSystem::Update(double dt) { m_Accumulator += dt; - while(m_Accumulator >= m_TimeStep) - { + while (m_Accumulator >= m_TimeStep) { for (auto i : m_EntitiesToBodies) { EntityID entity = i.first; - b2Body* body = i.second; + b2Body *body = i.second; auto transformComponent = m_World->GetComponent(entity); - if (! transformComponent) { + if (!transformComponent) { continue; LOG_ERROR("RigidBody with no TransformComponent"); } auto physicsComponent = m_World->GetComponent(entity); - if (! physicsComponent) { + if (!physicsComponent) { continue; LOG_ERROR("RigidBody with no PhysicsComponent"); } @@ -102,19 +99,19 @@ void dd::Systems::PhysicsSystem::Update(double dt) } } + UpdateParticleEmitters(dt); + for (auto i : m_Impulses) { i.Body->ApplyLinearImpulse(i.Impulse, i.Point, true); } m_Impulses.clear(); - m_PhysicsWorld->Step(m_TimeStep, m_VelocityIterations, m_PositionIterations); - for (auto i : m_EntitiesToBodies) { EntityID entity = i.first; - b2Body* body = i.second; + b2Body *body = i.second; if (body == nullptr) { LOG_ERROR("This body should not exist"); @@ -122,15 +119,17 @@ void dd::Systems::PhysicsSystem::Update(double dt) } auto transformComponent = m_World->GetComponent(entity); - if (! transformComponent) + if (!transformComponent) continue; - auto parent = m_World->GetEntityParent(entity); - if (parent == 0) { + auto parent = m_World->GetEntityParent(entity); + if (parent == 0) { auto physicsComponent = m_World->GetComponent(entity); if (physicsComponent->Calculate) { //TODO: REPLACE THIS WITH PARTICLE COLLISION FILTERS - transformComponent->Position.x = transformComponent->Position.x + (transformComponent->Velocity.x * m_TimeStep); - transformComponent->Position.y = transformComponent->Position.y + (transformComponent->Velocity.y * m_TimeStep); + transformComponent->Position.x = + transformComponent->Position.x + (transformComponent->Velocity.x * m_TimeStep); + transformComponent->Position.y = + transformComponent->Position.y + (transformComponent->Velocity.y * m_TimeStep); } else { b2Vec2 position = body->GetPosition(); @@ -138,36 +137,42 @@ void dd::Systems::PhysicsSystem::Update(double dt) transformComponent->Position.y = position.y; float angle = body->GetAngle(); - transformComponent->Orientation = glm::quat(glm::vec3(0, 0, angle)); + transformComponent->Orientation = glm::quat(glm::vec3(0, 0, angle)); b2Vec2 velocity = body->GetLinearVelocity(); transformComponent->Velocity.x = velocity.x; transformComponent->Velocity.y = velocity.y; } } - } - b2Vec2* positionBuffer = m_ParticleSystem[0]->GetPositionBuffer(); - for (auto i : m_EntitiesToParticleHandle) { - EntityID entity = i.first; - b2ParticleHandle* particleH = i.second; + for ( int e = 0; e < m_EntitiesToParticleHandle.size(); e++) { + b2Vec2 *positionBuffer = m_ParticleSystem[e]->GetPositionBuffer(); + for (auto i : m_EntitiesToParticleHandle[e]){ + EntityID entity = i.first; + b2ParticleHandle *particleH = i.second; - b2Vec2 positionB2 = positionBuffer[particleH->GetIndex()]; - glm::vec2 position = glm::vec2(positionB2.x, positionB2.y); + b2Vec2 positionB2 = positionBuffer[particleH->GetIndex()]; + glm::vec2 position = glm::vec2(positionB2.x, positionB2.y); + EntityID entityParent = m_World->GetEntityParent(entity); + glm::vec3 parentTransform = glm::vec3(0.f); + if(entityParent) { + auto tp = m_World->GetComponent(entityParent); + parentTransform = tp->Position; + } + auto transform = m_World->GetComponent(entity); - EntityID entityParent = m_World->GetEntityParent(entity); - auto transform = m_World->GetComponent(entity); - auto transformParent = m_World->GetComponent(entityParent); + transform->Position = glm::vec3(position.x, position.y, -10) - parentTransform; - transform->Position = glm::vec3(position.x, position.y, -10) - transformParent->Position; - } + } + } m_Accumulator -= dt; } } + void dd::Systems::PhysicsSystem::UpdateEntity(double dt, EntityID entity, EntityID parent) { @@ -177,15 +182,23 @@ void dd::Systems::PhysicsSystem::OnEntityCommit(EntityID entity) { auto physicsComponent = m_World->GetComponent(entity); auto waterComponent = m_World->GetComponent(entity); + auto particleEmitterComponent = m_World->GetComponent(entity); if (physicsComponent && waterComponent) { LOG_ERROR("Entity has both water and physics component, this is illegal. The police has been alerted."); return; } + if (physicsComponent && particleEmitterComponent) { + LOG_ERROR("Entity has both particle and physics component, this is illegal. The police has been alerted."); + return; + } + if (physicsComponent) { CreateBody(entity); } else if (waterComponent) { CreateParticleGroup(entity); + } else if (particleEmitterComponent) { + CreateParticleEmitter(entity); } } @@ -208,7 +221,6 @@ void dd::Systems::PhysicsSystem::OnEntityRemoved(EntityID entity) } - void dd::Systems::PhysicsSystem::CreateBody(EntityID entity) { auto physicsComponent = m_World->GetComponent(entity); @@ -292,41 +304,128 @@ void dd::Systems::PhysicsSystem::CreateParticleGroup(EntityID e) auto transform = m_World->GetComponent(e); if (!transform) { LOG_ERROR("No Transform component in CreateParticleGroup"); - return; } - b2ParticleGroupDef pd; b2PolygonShape shape; - //TODO: FIX SO IT CAN NOTICE WHAT PARTICLE SYSTEM IS WATER! [0] IS A FUCKING BULLSHIT FIX. + auto water = m_World->GetComponent(e); + if (water) { - shape.SetAsBox(transform->Scale.x/2.f, transform->Scale.y/2.f); - pd.shape = &shape; - pd.flags = b2_tensileParticle; - pd.position.Set(transform->Position.x, transform->Position.y); - t_ParticleGroup.push_back(m_ParticleSystem[0]->CreateParticleGroup(pd)); - b2Vec2* t_ParticlePositions = m_ParticleSystem[0]->GetPositionBuffer(); - for(int i = 0; i < m_ParticleSystem[0]->GetParticleCount(); i++){ - { - auto t_waterparticle = m_World->CreateEntity(e); - auto transformChild = m_World->AddComponent(t_waterparticle); + shape.SetAsBox(transform->Scale.x/2.f, transform->Scale.y/2.f); + pd.shape = &shape; + pd.flags = b2_tensileParticle; + pd.position.Set(transform->Position.x, transform->Position.y); + t_ParticleGroup.push_back(m_ParticleSystem[0]->CreateParticleGroup(pd)); + b2Vec2* t_ParticlePositions = m_ParticleSystem[0]->GetPositionBuffer(); + for(int i = 0; i < m_ParticleSystem[0]->GetParticleCount(); i++){ + { + auto t_waterparticle = m_World->CreateEntity(e); + auto transformChild = m_World->AddComponent(t_waterparticle); - transformChild->Position = glm::vec3(t_ParticlePositions[i].x - transform->Position.x, t_ParticlePositions[i].y - transform->Position.y, -9.5f); - transformChild->Scale = glm::vec3(m_ParticleSystem[0]->GetRadius())/transform->Scale; - m_World->CommitEntity(t_waterparticle); + transformChild->Position = glm::vec3(t_ParticlePositions[i].x - transform->Position.x, t_ParticlePositions[i].y - transform->Position.y, -9.5f); + transformChild->Scale = glm::vec3(m_ParticleSystem[0]->GetRadius())/transform->Scale; + m_World->CommitEntity(t_waterparticle); + + m_EntitiesToParticleHandle[0].insert(std::make_pair(t_waterparticle, m_ParticleSystem[0]->GetParticleHandleFromIndex(i))); + m_ParticleHandleToEntities[0].insert(std::make_pair( m_ParticleSystem[0]->GetParticleHandleFromIndex(i), t_waterparticle)); + } - m_EntitiesToParticleHandle.insert(std::make_pair(t_waterparticle, m_ParticleSystem[0]->GetParticleHandleFromIndex(i))); - m_ParticleHandleToEntities.insert(std::make_pair( m_ParticleSystem[0]->GetParticleHandleFromIndex(i), t_waterparticle)); } } } -void dd::Systems::PhysicsSystem::CreateParticleSystem(float radius) +void dd::Systems::PhysicsSystem::UpdateParticleEmitters(double dt) { + for (int i = 0; i < m_ParticleEmitters.ParticleSystem.size(); i++) { + auto e = m_ParticleEmitters.ParticleEmitter[i]; + auto pt = m_ParticleEmitters.ParticleTemplate[i]; + auto ps = m_ParticleEmitters.ParticleSystem[i]; + + + auto emitter = m_World->GetComponent(e); + auto particleTemplate = m_World->GetComponent(pt); + emitter->TimeSinceLastSpawn += dt; + if(emitter->TimeSinceLastSpawn < emitter->SpawnRate) { + continue; + } + emitter->TimeSinceLastSpawn -= emitter->SpawnRate; + auto templateTransform = m_World->GetComponent(pt); + + b2ParticleDef particleDef; + particleDef.flags = particleTemplate->Flags; + //particleDef.color TODO: Implement this if we want color mixing and shit. + particleDef.lifetime = particleTemplate->LifeTime; + particleDef.velocity = b2Vec2(templateTransform->Velocity.x, templateTransform->Velocity.y); + particleDef.position = b2Vec2(templateTransform->Position.x, templateTransform->Position.y); + + auto particle = m_World->CloneEntity(pt, 0); + m_World->RemoveComponent(particle); + + auto b2Particle = ps->CreateParticle(particleDef); + auto b2ParticleHandle = ps->GetParticleHandleFromIndex(b2Particle); + m_EntitiesToParticleHandle[i].insert(std::make_pair(particle, b2ParticleHandle)); + m_ParticleHandleToEntities[i].insert(std::make_pair(b2ParticleHandle, particle)); + + //TODO: Ta bort detta + int particles = 0; + for (auto i : m_EntitiesToParticleHandle) + { + particles += i.size(); + } + LOG_INFO("--I have %i particles.", particles); + } +} + +void dd::Systems::PhysicsSystem::CreateParticleEmitter(EntityID entity) +{ + auto childEntities = m_World->GetEntityChildren(entity); + if (childEntities.empty()) { + LOG_ERROR("Particle Emitter does not have any child. Please adopt one or this will not work."); + return; + } + int pf = 0; + dd::Components::Particle* particle; + EntityID childEntity; + for ( auto c : childEntities ) { + auto p = m_World->GetComponent(c); + auto particleTemplate = m_World->GetComponent(c); + if (!p) { + continue; + LOG_WARNING("--ParticleEmitter's Child is not a particle."); + } + if(!particleTemplate) { + LOG_ERROR("ParticleEmitter's particleChild is not a template."); + continue; + } + if (pf != 0) { + LOG_WARNING("ParticleEmitter has more than one child that is a particleTemplate, only the first one is used."); + break; + } + childEntity = c; + particle = p; + pf++; + } + //TODO: Skicka med fler flaggor till particlesystemet; + m_ParticleEmitters.ParticleSystem.push_back(CreateParticleSystem(particle->Radius, 0.f)); + m_ParticleEmitters.ParticleEmitter.push_back(entity); + m_ParticleEmitters.ParticleTemplate.push_back(childEntity); +} + + +b2ParticleSystem* dd::Systems::PhysicsSystem::CreateParticleSystem(float radius, float gravityScale) +{ + std::unordered_map m1; + std::unordered_map m2; + m_EntitiesToParticleHandle.push_back(m1); + m_ParticleHandleToEntities.push_back(m2); + b2ParticleSystemDef m_ParticleSystemDef; m_ParticleSystemDef.radius = radius; + m_ParticleSystemDef.gravityScale = gravityScale; m_ParticleSystem.push_back(m_PhysicsWorld->CreateParticleSystem(&m_ParticleSystemDef)); + + return m_ParticleSystem.back(); } dd::Systems::PhysicsSystem::~PhysicsSystem()