mirror of
https://github.com/antopilo/Nuake.git
synced 2026-09-15 20:08:54 +03:00
Merge pull request #56 from antopilo/feature/NK-146-particle-system
Feature/nk 146 particle system
This commit is contained in:
88
Editor/src/ComponentsPanel/ParticleEmitterPanel.h
Normal file
88
Editor/src/ComponentsPanel/ParticleEmitterPanel.h
Normal file
@@ -0,0 +1,88 @@
|
||||
#pragma once
|
||||
#include "ComponentPanel.h"
|
||||
|
||||
#include <src/Core/FileSystem.h>
|
||||
#include <src/Core/Maths.h>
|
||||
#include <src/Scene/Components/ParticleEmitterComponent.h>
|
||||
#include <src/Scene/Entities/ImGuiHelper.h>
|
||||
|
||||
class ParticleEmitterPanel : ComponentPanel
|
||||
{
|
||||
public:
|
||||
ParticleEmitterPanel() {}
|
||||
|
||||
void Draw(Nuake::Entity entity) override
|
||||
{
|
||||
if (!entity.HasComponent<Nuake::ParticleEmitterComponent>())
|
||||
return;
|
||||
|
||||
auto& component = entity.GetComponent<Nuake::ParticleEmitterComponent>();
|
||||
BeginComponentTable(PARTICLE EMITTER, Nuake::ParticleEmitterComponent);
|
||||
{
|
||||
{
|
||||
ImGui::Text("Particle Color");
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
ImGui::PushItemWidth(ImGui::GetContentRegionAvail().x);
|
||||
ImGui::ColorEdit3("##lightcolor", &component.ParticleColor.r, ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_NoLabel);
|
||||
ImGui::PopItemWidth();
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
ComponentTableReset(component.ParticleColor, Nuake::Vector4(1, 1, 1, 1));
|
||||
}
|
||||
ImGui::TableNextColumn();
|
||||
{
|
||||
ImGui::Text("Amount");
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
ImGui::DragFloat("##ParticleAmount", &component.Amount, 0.1f, 0.0f, 500.0f);
|
||||
ImGui::TableNextColumn();
|
||||
ComponentTableReset(component.Amount, 10.0f);
|
||||
}
|
||||
ImGui::TableNextColumn();
|
||||
{
|
||||
ImGui::Text("Rate");
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
ImGui::DragFloat("##ParticleRate", &component.Rate, 0.1f, 0.0f, 10.0f);
|
||||
ImGui::TableNextColumn();
|
||||
ComponentTableReset(component.Rate, 0.0f);
|
||||
}
|
||||
ImGui::TableNextColumn();
|
||||
{
|
||||
ImGui::Text("Life");
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
ImGui::DragFloat("##ParticleLife", &component.Life, 0.1f, 0.0f, 100.0f);
|
||||
ImGui::TableNextColumn();
|
||||
ComponentTableReset(component.Life, 5.0f);
|
||||
}
|
||||
ImGui::TableNextColumn();
|
||||
{
|
||||
ImGui::Text("Gravity");
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
ImGuiHelper::DrawVec3("Gravity", &component.Gravity);
|
||||
ImGui::TableNextColumn();
|
||||
ComponentTableReset(component.Gravity, Nuake::Vector3(0, -1, 0));
|
||||
}
|
||||
ImGui::TableNextColumn();
|
||||
{
|
||||
ImGui::Text("Gravity Random");
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::DragFloat("##GravityRandom", &component.GravityRandom, 0.01f, 0.0f, 1.0f);
|
||||
ImGui::TableNextColumn();
|
||||
ComponentTableReset(component.GravityRandom, 0.0f);
|
||||
}
|
||||
ImGui::TableNextColumn();
|
||||
{
|
||||
ImGui::Text("Radius");
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::DragFloat("##ParticleRadius", &component.Radius, 0.01f, 0.0f, 10.0f);
|
||||
ImGui::TableNextColumn();
|
||||
ComponentTableReset(component.Radius, 1.0f);
|
||||
}
|
||||
}
|
||||
EndComponentTable();
|
||||
}
|
||||
};
|
||||
@@ -16,6 +16,7 @@
|
||||
#include <src/Scene/Components/CylinderColliderComponent.h>
|
||||
#include <src/Scene/Components/MeshCollider.h>
|
||||
#include <src/Scene/Components/ModelComponent.h>
|
||||
#include <src/Scene/Components/ParticleEmitterComponent.h>
|
||||
|
||||
|
||||
GizmoDrawer::GizmoDrawer()
|
||||
@@ -217,6 +218,18 @@ void GizmoDrawer::DrawGizmos(Ref<Scene> scene)
|
||||
Nuake::RenderCommand::DrawLines(0, 264);
|
||||
}
|
||||
|
||||
auto particleView = scene->m_Registry.view<TransformComponent, ParticleEmitterComponent>();
|
||||
for (auto e : particleView)
|
||||
{
|
||||
auto [transform, particle] = scene->m_Registry.get<TransformComponent, ParticleEmitterComponent>(e);
|
||||
mLineShader->Bind();
|
||||
mLineShader->SetUniformMat4f("u_View", glm::scale(glm::translate(scene->m_EditorCamera->GetTransform(), transform.Translation), Vector3(particle.Radius)));
|
||||
mLineShader->SetUniformMat4f("u_Projection", scene->m_EditorCamera->GetPerspective());
|
||||
|
||||
mCircleBuffer->Bind();
|
||||
Nuake::RenderCommand::DrawLines(0, 128);
|
||||
}
|
||||
|
||||
auto meshColliderView = scene->m_Registry.view<TransformComponent, MeshColliderComponent, ModelComponent>();
|
||||
for (auto e : meshColliderView)
|
||||
{
|
||||
|
||||
@@ -11,6 +11,8 @@
|
||||
#include <Engine.h>
|
||||
|
||||
#include "src/Scene/Components/WrenScriptComponent.h"
|
||||
#include "src/Scene/Components/ParticleEmitterComponent.h"
|
||||
|
||||
|
||||
EditorSelectionPanel::EditorSelectionPanel()
|
||||
{
|
||||
@@ -98,6 +100,7 @@ void EditorSelectionPanel::DrawEntity(Nuake::Entity entity)
|
||||
mTransformPanel.Draw(entity);
|
||||
mLightPanel.Draw(entity);
|
||||
mScriptPanel.Draw(entity);
|
||||
mParticleEmitterPanel.Draw(entity);
|
||||
mSpritePanel.Draw(entity);
|
||||
mMeshPanel.Draw(entity);
|
||||
mQuakeMapPanel.Draw(entity);
|
||||
@@ -129,6 +132,7 @@ void EditorSelectionPanel::DrawAddComponentMenu(Nuake::Entity entity)
|
||||
MenuItemComponent("Light", Nuake::LightComponent)
|
||||
MenuItemComponent("Model", Nuake::ModelComponent)
|
||||
MenuItemComponent("Sprite", Nuake::SpriteComponent)
|
||||
MenuItemComponent("Particle Emitter", Nuake::ParticleEmitterComponent)
|
||||
ImGui::Separator();
|
||||
MenuItemComponent("Character Controller", Nuake::CharacterControllerComponent)
|
||||
MenuItemComponent("Rigid body", Nuake::RigidBodyComponent)
|
||||
|
||||
@@ -19,9 +19,11 @@
|
||||
#include "../ComponentsPanel/MeshColliderPanel.h"
|
||||
#include "../ComponentsPanel/CharacterControllerPanel.h"
|
||||
#include "../ComponentsPanel/SpritePanel.h"
|
||||
#include "../ComponentsPanel/ParticleEmitterPanel.h"
|
||||
|
||||
|
||||
class EditorSelectionPanel {
|
||||
class EditorSelectionPanel
|
||||
{
|
||||
private:
|
||||
TransformPanel mTransformPanel;
|
||||
LightPanel mLightPanel;
|
||||
@@ -37,6 +39,7 @@ private:
|
||||
CylinderColliderPanel mCylinderColliderPanel;
|
||||
SpritePanel mSpritePanel;
|
||||
CharacterControllerPanel mCharacterControllerPanel;
|
||||
ParticleEmitterPanel mParticleEmitterPanel;
|
||||
|
||||
Ref<Nuake::File> currentFile;
|
||||
Ref<Nuake::Resource> selectedResource;
|
||||
|
||||
@@ -53,22 +53,20 @@ namespace Nuake
|
||||
s_CurrentWindow->Update(s_TimeStep);
|
||||
|
||||
// Play mode update all the entities, Editor does not.
|
||||
if (Engine::IsPlayMode())
|
||||
{
|
||||
s_FixedUpdateDifference += s_TimeStep;
|
||||
|
||||
// Fixed update
|
||||
while (s_FixedUpdateDifference >= s_FixedUpdateRate)
|
||||
{
|
||||
s_CurrentWindow->FixedUpdate(s_FixedUpdateDifference);
|
||||
|
||||
s_FixedUpdateDifference -= s_FixedUpdateRate;
|
||||
}
|
||||
}
|
||||
else
|
||||
if (!Engine::IsPlayMode())
|
||||
{
|
||||
GetCurrentScene()->EditorUpdate(s_TimeStep);
|
||||
}
|
||||
|
||||
s_FixedUpdateDifference += s_TimeStep;
|
||||
|
||||
// Fixed update
|
||||
while (s_FixedUpdateDifference >= s_FixedUpdateRate)
|
||||
{
|
||||
s_CurrentWindow->FixedUpdate(s_FixedUpdateDifference);
|
||||
|
||||
s_FixedUpdateDifference -= s_FixedUpdateRate;
|
||||
}
|
||||
}
|
||||
|
||||
Input::Update();
|
||||
|
||||
@@ -82,14 +82,17 @@ namespace Nuake
|
||||
|
||||
m_LightsUniformBuffer = CreateRef<UniformBuffer>(128);
|
||||
|
||||
Ref<Material> material = MaterialManager::Get()->GetMaterial("default");
|
||||
Ref<Material> defaultMaterial = CreateRef<Material>(Vector3{1, 1, 1});
|
||||
defaultMaterial->SetName("white");
|
||||
MaterialManager::Get()->RegisterMaterial(defaultMaterial);
|
||||
|
||||
CubeMesh = CreateRef<Mesh>();
|
||||
CubeMesh->AddSurface(CubeVertices, CubeIndices);
|
||||
CubeMesh->SetMaterial(material);
|
||||
CubeMesh->SetMaterial(defaultMaterial);
|
||||
|
||||
QuadMesh = CreateRef<Mesh>();
|
||||
QuadMesh->AddSurface(QuadVertices, { 0, 1, 2, 3, 4, 5 });
|
||||
QuadMesh->SetMaterial(material);
|
||||
QuadMesh->SetMaterial(defaultMaterial);
|
||||
}
|
||||
|
||||
void Renderer::LoadShaders()
|
||||
|
||||
@@ -3,9 +3,11 @@
|
||||
|
||||
#include "src/Scene/Components/BSPBrushComponent.h"
|
||||
#include "src/Scene/Components/SpriteComponent.h"
|
||||
#include "src/Scene/Components/ParticleEmitterComponent.h"
|
||||
|
||||
#include <GL\glew.h>
|
||||
|
||||
|
||||
namespace Nuake
|
||||
{
|
||||
void SceneRenderer::Init()
|
||||
@@ -229,6 +231,7 @@ namespace Nuake
|
||||
|
||||
Renderer::SubmitMesh(sprite.SpriteMesh, finalQuadTransform, (uint32_t)e);
|
||||
}
|
||||
|
||||
Renderer::Flush(shader, true);
|
||||
}
|
||||
}
|
||||
@@ -284,7 +287,7 @@ namespace Nuake
|
||||
|
||||
// Sprites
|
||||
auto spriteView = scene.m_Registry.view<TransformComponent, SpriteComponent, VisibilityComponent>();
|
||||
for (auto e : spriteView)
|
||||
for (auto& e : spriteView)
|
||||
{
|
||||
auto [transform, sprite, visibility] = spriteView.get<TransformComponent, SpriteComponent, VisibilityComponent>(e);
|
||||
|
||||
@@ -314,6 +317,38 @@ namespace Nuake
|
||||
Renderer::SubmitMesh(sprite.SpriteMesh, finalQuadTransform, (uint32_t)e);
|
||||
}
|
||||
Renderer::Flush(gBufferShader, false);
|
||||
|
||||
// Particles
|
||||
auto particleEmitterView = scene.m_Registry.view<TransformComponent, ParticleEmitterComponent, VisibilityComponent>();
|
||||
for (auto& e : particleEmitterView)
|
||||
{
|
||||
auto [transform, emitterComponent, visibility] = particleEmitterView.get<TransformComponent, ParticleEmitterComponent, VisibilityComponent>(e);
|
||||
|
||||
if (!visibility.Visible)
|
||||
continue;
|
||||
|
||||
Vector3 oldColor = Renderer::QuadMesh->GetMaterial()->data.m_AlbedoColor;
|
||||
auto initialTransform = transform.GetGlobalTransform();
|
||||
for (auto& p : emitterComponent.Emitter.Particles)
|
||||
{
|
||||
Matrix4 particleTransform = initialTransform;
|
||||
particleTransform = glm::inverse(mView);
|
||||
|
||||
// Translation
|
||||
const Vector3& particleGlobalPosition = transform.GetGlobalPosition() + p.Position;
|
||||
particleTransform[3] = Vector4(particleGlobalPosition, 1.0f);
|
||||
|
||||
// Scale
|
||||
particleTransform = glm::scale(particleTransform, transform.GetGlobalScale());
|
||||
|
||||
Renderer::QuadMesh->GetMaterial()->data.u_HasAlbedo = 0;
|
||||
Renderer::QuadMesh->GetMaterial()->data.m_AlbedoColor = p.Color;
|
||||
Renderer::SubmitMesh(Renderer::QuadMesh, particleTransform, (uint32_t)e);
|
||||
}
|
||||
|
||||
Renderer::Flush(gBufferShader, false);
|
||||
Renderer::QuadMesh->GetMaterial()->data.m_AlbedoColor = oldColor;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -68,9 +68,7 @@ namespace Nuake
|
||||
|
||||
data.m_AlbedoColor = Vector3{ albedoColor.r, albedoColor.g, albedoColor.b };
|
||||
|
||||
m_Name = "New material";
|
||||
|
||||
m_Albedo = m_DefaultAlbedo;
|
||||
m_Name = "default";
|
||||
}
|
||||
|
||||
Material::~Material() {}
|
||||
|
||||
@@ -11,8 +11,6 @@ namespace Nuake
|
||||
class MaterialManager
|
||||
{
|
||||
private:
|
||||
const std::string DEFAULT_MATERIAL = "resources/Textures/default/Default.png";
|
||||
|
||||
static Ref<MaterialManager> s_Instance;
|
||||
|
||||
std::map<std::string, Ref<Material>> m_Materials;
|
||||
@@ -24,6 +22,7 @@ namespace Nuake
|
||||
|
||||
|
||||
public:
|
||||
const std::string DEFAULT_MATERIAL = "resources/Textures/default/Default.png";
|
||||
std::string CurrentlyBoundedMaterial = "";
|
||||
MaterialManager();
|
||||
|
||||
|
||||
@@ -19,6 +19,9 @@ using json = nlohmann::json;
|
||||
SERIALIZE_VEC3(v) \
|
||||
j[#v]["w"] = this->v.w;
|
||||
|
||||
#define DESERIALIZE_VEC4(v, p) \
|
||||
p = Vector4(v["x"], v["y"], v["z"], v["w"]);
|
||||
|
||||
#define DESERIALIZE_VEC3(v, p) \
|
||||
p = Vector3(v["x"], v["y"], v["z"]);
|
||||
|
||||
|
||||
33
Nuake/src/Scene/Components/ParticleEmitterComponent.cpp
Normal file
33
Nuake/src/Scene/Components/ParticleEmitterComponent.cpp
Normal file
@@ -0,0 +1,33 @@
|
||||
#include "src/Scene/Components/ParticleEmitterComponent.h"
|
||||
|
||||
namespace Nuake
|
||||
{
|
||||
json ParticleEmitterComponent::Serialize()
|
||||
{
|
||||
BEGIN_SERIALIZE();
|
||||
SERIALIZE_VEC4(ParticleColor);
|
||||
SERIALIZE_VAL(Amount);
|
||||
SERIALIZE_VAL(Life);
|
||||
SERIALIZE_VAL(Rate);
|
||||
SERIALIZE_VEC3(Gravity);
|
||||
SERIALIZE_VAL(GravityRandom);
|
||||
SERIALIZE_VAL(Radius);
|
||||
END_SERIALIZE();
|
||||
}
|
||||
|
||||
bool ParticleEmitterComponent::Deserialize(const std::string& str)
|
||||
{
|
||||
BEGIN_DESERIALIZE();
|
||||
DESERIALIZE_VEC4(j["ParticleColor"], ParticleColor);
|
||||
Amount = j["Amount"];
|
||||
Life = j["Life"];
|
||||
if (j.contains("Rate"))
|
||||
{
|
||||
Rate = j["Rate"];
|
||||
}
|
||||
DESERIALIZE_VEC3(j["Gravity"], Gravity);
|
||||
GravityRandom = j["GravityRandom"];
|
||||
Radius = j["Radius"];
|
||||
return true;
|
||||
}
|
||||
}
|
||||
34
Nuake/src/Scene/Components/ParticleEmitterComponent.h
Normal file
34
Nuake/src/Scene/Components/ParticleEmitterComponent.h
Normal file
@@ -0,0 +1,34 @@
|
||||
#pragma once
|
||||
#include "src/Core/Core.h"
|
||||
#include "src/Core/Maths.h"
|
||||
#include "src/Resource/Serializable.h"
|
||||
|
||||
#include "src/Scene/Systems/ParticleEmitter.h"
|
||||
|
||||
|
||||
namespace Nuake
|
||||
{
|
||||
class ParticleEmitterComponent
|
||||
{
|
||||
public:
|
||||
ParticleEmitterComponent() = default;
|
||||
~ParticleEmitterComponent() = default;
|
||||
|
||||
Color ParticleColor;
|
||||
float Amount;
|
||||
float Life = 1.0f;
|
||||
float Rate = 0.0f;
|
||||
|
||||
Vector3 Gravity;
|
||||
float GravityRandom;
|
||||
|
||||
// For now use a radius, later should use shape.
|
||||
float Radius;
|
||||
|
||||
ParticleEmitter Emitter;
|
||||
|
||||
public:
|
||||
json Serialize();
|
||||
bool Deserialize(const std::string& str);
|
||||
};
|
||||
}
|
||||
@@ -15,7 +15,7 @@
|
||||
#include "src/Scene/Components/BoxCollider.h"
|
||||
#include "src/Scene/Components/CapsuleColliderComponent.h"
|
||||
#include "src/Scene/Components/SpriteComponent.h"
|
||||
|
||||
#include "src/Scene/Components/ParticleEmitterComponent.h"
|
||||
|
||||
namespace Nuake
|
||||
{
|
||||
@@ -39,6 +39,8 @@ namespace Nuake
|
||||
SERIALIZE_OBJECT_REF_LBL("VisibilityComponent", GetComponent<VisibilityComponent>())
|
||||
if (HasComponent<CameraComponent>())
|
||||
SERIALIZE_OBJECT_REF_LBL("CameraComponent", GetComponent<CameraComponent>())
|
||||
if (HasComponent<ParticleEmitterComponent>())
|
||||
SERIALIZE_OBJECT_REF_LBL("ParticleEmitterComponent", GetComponent<ParticleEmitterComponent>())
|
||||
if (HasComponent<SpriteComponent>())
|
||||
SERIALIZE_OBJECT_REF_LBL("SpriteComponent", GetComponent<SpriteComponent>())
|
||||
if (HasComponent<QuakeMapComponent>())
|
||||
@@ -82,6 +84,7 @@ namespace Nuake
|
||||
}
|
||||
DESERIALIZE_COMPONENT(NameComponent)
|
||||
DESERIALIZE_COMPONENT(ParentComponent)
|
||||
DESERIALIZE_COMPONENT(ParticleEmitterComponent)
|
||||
DESERIALIZE_COMPONENT(SpriteComponent)
|
||||
DESERIALIZE_COMPONENT(CameraComponent)
|
||||
DESERIALIZE_COMPONENT(QuakeMapComponent)
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include "src/Scene/Systems/PhysicsSystem.h"
|
||||
#include "src/Scene/Systems/TransformSystem.h"
|
||||
#include "src/Scene/Systems/QuakeMapBuilder.h"
|
||||
#include "src/Scene/Systems/ParticleSystem.h"
|
||||
|
||||
#include "src/Rendering/SceneRenderer.h"
|
||||
#include "Scene.h"
|
||||
@@ -45,6 +46,7 @@ namespace Nuake {
|
||||
m_Systems.push_back(CreateRef<ScriptingSystem>(this));
|
||||
m_Systems.push_back(CreateRef<TransformSystem>(this));
|
||||
m_Systems.push_back(CreateRef<PhysicsSystem>(this));
|
||||
m_Systems.push_back(CreateRef<ParticleSystem>(this));
|
||||
|
||||
m_SceneRenderer = new SceneRenderer();
|
||||
m_SceneRenderer->Init();
|
||||
@@ -271,11 +273,15 @@ namespace Nuake {
|
||||
|
||||
for (auto& c : copyChildrens)
|
||||
{
|
||||
Logger::Log("Deleting entity " + std::to_string(c.GetHandle()));
|
||||
DestroyEntity(c);
|
||||
}
|
||||
|
||||
Logger::Log("Deleted entity" + std::to_string(entity.GetHandle()) + " - " + entity.GetComponent<NameComponent>().Name);
|
||||
// Remove from ID to Entity cache
|
||||
if (m_EntitiesIDMap.find(entity.GetComponent<NameComponent>().ID) != m_EntitiesIDMap.end())
|
||||
{
|
||||
m_EntitiesIDMap.erase(entity.GetComponent<NameComponent>().ID);
|
||||
}
|
||||
|
||||
entity.Destroy();
|
||||
m_Registry.shrink_to_fit();
|
||||
}
|
||||
|
||||
13
Nuake/src/Scene/Systems/Particle.h
Normal file
13
Nuake/src/Scene/Systems/Particle.h
Normal file
@@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
#include "src/Core/Maths.h"
|
||||
|
||||
namespace Nuake
|
||||
{
|
||||
struct Particle
|
||||
{
|
||||
Vector3 Position;
|
||||
Vector3 Velocity;
|
||||
Color Color;
|
||||
float Life;
|
||||
};
|
||||
}
|
||||
87
Nuake/src/Scene/Systems/ParticleEmitter.cpp
Normal file
87
Nuake/src/Scene/Systems/ParticleEmitter.cpp
Normal file
@@ -0,0 +1,87 @@
|
||||
#include "ParticleEmitter.h"
|
||||
|
||||
namespace Nuake
|
||||
{
|
||||
ParticleEmitter::ParticleEmitter()
|
||||
{
|
||||
m_MT = std::mt19937(std::random_device()());
|
||||
SetRadius(1.0f);
|
||||
}
|
||||
|
||||
void ParticleEmitter::RecreateRandom()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void ParticleEmitter::SpawnParticle()
|
||||
{
|
||||
const bool canSpawnParticle = Particles.size() < Amount;
|
||||
if (!canSpawnParticle)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (Rate == 0.0f || RateTimer > Rate)
|
||||
{
|
||||
const auto initialPosition = Vector3(m_Random(m_MT), m_Random(m_MT), m_Random(m_MT));
|
||||
const auto initialVelocity = Vector3();
|
||||
const auto initialColor = ParticleColor;
|
||||
const float initialLife = Life;
|
||||
|
||||
Particles.push_back({
|
||||
initialPosition,
|
||||
initialVelocity,
|
||||
initialColor,
|
||||
initialLife
|
||||
});
|
||||
|
||||
RateTimer = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
void ParticleEmitter::Update(Timestep ts)
|
||||
{
|
||||
if (Rate != 0.0f)
|
||||
{
|
||||
RateTimer += ts;
|
||||
}
|
||||
|
||||
std::vector<uint32_t> deletionQueue;
|
||||
int i = 0;
|
||||
for (auto& p : Particles)
|
||||
{
|
||||
p.Life -= ts;
|
||||
|
||||
if (p.Life <= 0.0f) // The particle has died.
|
||||
{
|
||||
deletionQueue.push_back(i);
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
// Delete all dead particles.
|
||||
int shiftOffset = 0;
|
||||
for (int d = deletionQueue.size() - 1; d > 0; d--)
|
||||
{
|
||||
// Erase shifts the elements
|
||||
const auto it = d;
|
||||
Particles.erase(Particles.begin() + it);
|
||||
}
|
||||
|
||||
for (auto& p : Particles)
|
||||
{
|
||||
p.Velocity += Gravity * static_cast<float>(ts);
|
||||
p.Position += p.Velocity * static_cast<float>(ts);
|
||||
}
|
||||
}
|
||||
|
||||
void ParticleEmitter::SetRadius(float radius)
|
||||
{
|
||||
if (Radius != radius)
|
||||
{
|
||||
Radius = radius;
|
||||
m_Random = std::uniform_real_distribution<float>(-Radius, Radius);
|
||||
}
|
||||
}
|
||||
}
|
||||
42
Nuake/src/Scene/Systems/ParticleEmitter.h
Normal file
42
Nuake/src/Scene/Systems/ParticleEmitter.h
Normal file
@@ -0,0 +1,42 @@
|
||||
#pragma once
|
||||
#include "Particle.h"
|
||||
|
||||
#include "src/Core/Core.h"
|
||||
#include "src/Core/Maths.h"
|
||||
#include "src/Core/Timestep.h"
|
||||
|
||||
#include "src/Rendering/Textures/Material.h"
|
||||
|
||||
#include <random>
|
||||
|
||||
namespace Nuake
|
||||
{
|
||||
class ParticleEmitter
|
||||
{
|
||||
public:
|
||||
float Amount = 0.0f;
|
||||
float Life = 5.0f;
|
||||
Vector3 Gravity = Vector3(0, 0, 0);
|
||||
float GravityRandom = 0.0f;
|
||||
float Radius = 1.0f;
|
||||
float Rate = 0.0f;
|
||||
Color ParticleColor;
|
||||
|
||||
private:
|
||||
float RateTimer = 0.0f;
|
||||
std::mt19937 m_MT;
|
||||
std::uniform_real_distribution<float> m_Random;
|
||||
|
||||
void RecreateRandom();
|
||||
|
||||
public:
|
||||
ParticleEmitter();
|
||||
~ParticleEmitter() = default;
|
||||
|
||||
void SpawnParticle();
|
||||
void Update(Timestep ts);
|
||||
|
||||
void SetRadius(float radius);
|
||||
std::vector<Particle> Particles;
|
||||
};
|
||||
}
|
||||
64
Nuake/src/Scene/Systems/ParticleSystem.cpp
Normal file
64
Nuake/src/Scene/Systems/ParticleSystem.cpp
Normal file
@@ -0,0 +1,64 @@
|
||||
#include "ParticleSystem.h"
|
||||
|
||||
#include "src/Scene/Scene.h"
|
||||
#include "src/Scene/Entities/Entity.h"
|
||||
#include "src/Scene/Components/ParticleEmitterComponent.h"
|
||||
|
||||
|
||||
namespace Nuake
|
||||
{
|
||||
ParticleSystem::ParticleSystem(Scene* scene)
|
||||
{
|
||||
m_Scene = scene;
|
||||
}
|
||||
|
||||
bool ParticleSystem::Init()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void ParticleSystem::Update(Timestep ts)
|
||||
{
|
||||
auto& view = m_Scene->m_Registry.view<TransformComponent, ParticleEmitterComponent>();
|
||||
for (auto& e : view)
|
||||
{
|
||||
auto [transformComponent, emitterComponent] = view.get<TransformComponent, ParticleEmitterComponent>(e);
|
||||
Entity ent = Entity({ e, m_Scene });
|
||||
|
||||
// Copy emitter settings from component to real emitter
|
||||
auto& emitter = emitterComponent.Emitter;
|
||||
emitter.Amount = emitterComponent.Amount;
|
||||
emitter.ParticleColor = emitterComponent.ParticleColor;
|
||||
emitter.Gravity = emitterComponent.Gravity;
|
||||
emitter.GravityRandom = emitterComponent.GravityRandom;
|
||||
emitter.SetRadius(emitterComponent.Radius);
|
||||
emitter.Life = emitterComponent.Life;
|
||||
emitter.Rate = emitterComponent.Rate;
|
||||
|
||||
// Spawn particle if possible
|
||||
emitterComponent.Emitter.SpawnParticle();
|
||||
}
|
||||
}
|
||||
|
||||
void ParticleSystem::FixedUpdate(Timestep ts)
|
||||
{
|
||||
auto& view = m_Scene->m_Registry.view<TransformComponent, ParticleEmitterComponent>();
|
||||
for (auto& e : view)
|
||||
{
|
||||
auto [transformComponent, emitterComponent] = view.get<TransformComponent, ParticleEmitterComponent>(e);
|
||||
Entity ent = Entity({ e, m_Scene });
|
||||
|
||||
emitterComponent.Emitter.Update(ts);
|
||||
}
|
||||
}
|
||||
|
||||
void ParticleSystem::EditorUpdate()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void ParticleSystem::Exit()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
21
Nuake/src/Scene/Systems/ParticleSystem.h
Normal file
21
Nuake/src/Scene/Systems/ParticleSystem.h
Normal file
@@ -0,0 +1,21 @@
|
||||
#pragma once
|
||||
#include <src/Scene/Systems/System.h>
|
||||
#include <src/Core/Maths.h>
|
||||
|
||||
#include <random>
|
||||
|
||||
|
||||
namespace Nuake
|
||||
{
|
||||
class ParticleSystem : public System
|
||||
{
|
||||
public:
|
||||
ParticleSystem(Scene* scene);
|
||||
bool Init() override;
|
||||
void Update(Timestep ts) override;
|
||||
void Draw() override {}
|
||||
void EditorUpdate() override;
|
||||
void FixedUpdate(Timestep ts) override;
|
||||
void Exit() override;
|
||||
};
|
||||
}
|
||||
@@ -56,6 +56,9 @@ namespace Nuake {
|
||||
|
||||
void ScriptingSystem::FixedUpdate(Timestep ts)
|
||||
{
|
||||
if (!Engine::IsPlayMode())
|
||||
return;
|
||||
|
||||
auto entities = m_Scene->m_Registry.view<WrenScriptComponent>();
|
||||
for (auto& e : entities)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user