diff --git a/Broken Engine/Source/ComponentParticleEmitter.cpp b/Broken Engine/Source/ComponentParticleEmitter.cpp index 5ac61ab8b..d1c5e6de7 100644 --- a/Broken Engine/Source/ComponentParticleEmitter.cpp +++ b/Broken Engine/Source/ComponentParticleEmitter.cpp @@ -73,7 +73,7 @@ ComponentParticleEmitter::~ComponentParticleEmitter() for (int i = 0; i < maxParticles; ++i) { - App->particles->particlesToDraw.erase(particles[i]); + App->particles->particlesToDraw.erase(particles[i]->distanceToCam); delete particles[i]; particles[i] = nullptr; } @@ -140,13 +140,13 @@ void ComponentParticleEmitter::Enable() particleSystem = App->physics->mPhysics->createParticleSystem(maxParticles, perParticleRestOffset); particleSystem->setMaxMotionDistance(100); - if (collision_active) - { - physx::PxFilterData filterData; - filterData.word0 = (1 << GO->layer); - filterData.word1 = App->physics->layer_list.at(GO->layer).LayerGroup; - particleSystem->setSimulationFilterData(filterData); - } + //if (collision_active) + //{ + // physx::PxFilterData filterData; + // filterData.word0 = (1 << GO->layer); + // filterData.word1 = App->physics->layer_list.at(GO->layer).LayerGroup; + // particleSystem->setSimulationFilterData(filterData); + //} if (particleSystem) App->physics->AddParticleActor(particleSystem, GO); @@ -168,10 +168,9 @@ void ComponentParticleEmitter::Disable() void ComponentParticleEmitter::UpdateParticles(float dt) { - int currentPlayTime = App->time->GetGameplayTimePassed() * 1000; - // Create particle depending on the time + //Create particle depending on the time if (emisionActive && App->GetAppState() == AppState::PLAY && !App->time->gamePaused) { if ((currentPlayTime - spawnClock > emisionRate )||playNow) { @@ -198,13 +197,13 @@ void ComponentParticleEmitter::UpdateParticles(float dt) } } - if (collision_active) - { - physx::PxFilterData filterData; - filterData.word0 = (1 << GO->layer); // word0 = own ID - filterData.word1 = App->physics->layer_list.at(GO->layer).LayerGroup; // word1 = ID mask to filter pairs that trigger a contact callback; - particleSystem->setSimulationFilterData(filterData); - } + //if (collision_active) + //{ + // physx::PxFilterData filterData; + // filterData.word0 = (1 << GO->layer); // word0 = own ID + // filterData.word1 = App->physics->layer_list.at(GO->layer).LayerGroup; // word1 = ID mask to filter pairs that trigger a contact callback; + // particleSystem->setSimulationFilterData(filterData); + //} //Update particles //lock SDK buffers of *PxParticleSystem* ps for reading @@ -313,10 +312,21 @@ void ComponentParticleEmitter::SortParticles() if (*flagsIt & physx::PxParticleFlag::eVALID) { - float distance = App->renderer3D->active_camera->frustum.NearPlane().Distance(particles[i]->position); + float distance = 1.0f/App->renderer3D->active_camera->frustum.NearPlane().Distance(particles[i]->position); + + //drawingIndices[1.0f / distance] = i; + + bool particleSent = false; + while (!particleSent) { + if (App->particles->particlesToDraw.find(distance) == App->particles->particlesToDraw.end()) { + App->particles->particlesToDraw[distance] = particles[i]; + particles[i]->distanceToCam = distance; + particleSent = true; + } + else + distance -= 0.00001; - drawingIndices[1.0f / distance] = i; - App->particles->particlesToDraw[particles[i]] = 1.0f / distance; + } } } @@ -418,6 +428,8 @@ json ComponentParticleEmitter::Save() const { json node; + node["PlayOnAwake"] = playOnAwake; + node["Active"] = this->active; node["positionX"] = std::to_string(emitterPosition.x); @@ -567,7 +579,7 @@ void ComponentParticleEmitter::Load(json& node) scaleCurve = nullptr; rotateCurve = nullptr; - this->active = node["Active"].is_null() ? true : (bool)node["Active"]; + this->active = node["Active"].is_null() ? false : (bool)node["Active"]; //load the strings std::string LpositionX = node["positionX"].is_null() ? "0" : node["positionX"]; @@ -609,6 +621,9 @@ void ComponentParticleEmitter::Load(json& node) followEmitter = node["followEmitter"].is_null() ? true : node["followEmitter"].get(); + playOnAwake = node["PlayOnAwake"].is_null() ? false : node["PlayOnAwake"].get(); + emisionActive = playOnAwake; + std::string LParticlesSize = node["particlesSize"].is_null() ? "0" : node["particlesSize"]; std::string _animation = node["animation"].is_null() ? "0" : node["animation"]; @@ -831,7 +846,8 @@ void ComponentParticleEmitter::Load(json& node) // --- Collisions --- collision_active = node.find("CollisionsActivated") == node.end() ? true : node["CollisionsActivated"].get(); - + SetActiveCollisions(collision_active); + // --- Face Culling --- particlesFaceCulling = node.find("ParticlesFaceCulling") == node.end() ? true : node["ParticlesFaceCulling"].get(); @@ -856,20 +872,34 @@ void ComponentParticleEmitter::Load(json& node) void ComponentParticleEmitter::CreateInspectorNode() { - // --- Loop --- + //Play on awake ImGui::NewLine(); - if (ImGui::Checkbox("##PELoop", &loop)) - if (loop) { - emisionActive = true; - firstEmision = true; - } - + ImGui::Checkbox("##PlayOnAwake", &playOnAwake); + if (App->GetAppState() != AppState::PLAY) + emisionActive = playOnAwake; ImGui::SameLine(); - ImGui::Text("Loop"); + ImGui::Text("Play on awake"); + + // --- Loop --- + if (ImGui::Checkbox("##PELoop", &loop)) + if (loop) + { + emisionActive = true; + firstEmision = true; + } + + ImGui::SameLine(); ImGui::Text("Loop"); + //Follow emitter + ImGui::Checkbox("##SFollow emitter", &followEmitter); + ImGui::SameLine(); ImGui::Text("Follow emitter"); + + // Duration + ImGui::NewLine(); ImGui::Text("Duration"); ImGui::SameLine(); ImGui::DragInt("##PEDuration", &duration); + //Emitter position ImGui::Text("Position"); @@ -988,12 +1018,8 @@ void ComponentParticleEmitter::CreateInspectorNode() if (forceChanged) particleSystem->setExternalAcceleration(externalAcceleration); - - //Follow emitter - ImGui::Text("Follow emitter"); - ImGui::Checkbox("##SFollow emitter", &followEmitter); - //Emision rate + ImGui::NewLine(); ImGui::Text("Emision rate (ms)"); ImGui::SetNextItemWidth(ImGui::GetWindowWidth() * 0.3f); ImGui::DragFloat("##SEmision rate", &emisionRate, 1.0f, 1.0f, 100000.0f); @@ -1050,13 +1076,17 @@ void ComponentParticleEmitter::CreateInspectorNode() int maxParticles = particlesPerCreation / emisionRate * particlesLifeTime; ImGui::Text("Total particles alive: %d", maxParticles); + + ImGui::NewLine(); ImGui::Separator(); // --- Collisions --- if (ImGui::TreeNode("Collision Options")) { - ImGui::Text("Enable Collisions"); - ImGui::Checkbox("##PE_EnableColl", &collision_active); + if (ImGui::Checkbox("##PE_EnableColl", &collision_active)) + SetActiveCollisions(collision_active); + + ImGui::SameLine(); ImGui::Text("Enable Collisions"); ImGui::TreePop(); } @@ -1414,7 +1444,7 @@ void ComponentParticleEmitter::CreateInspectorNode() { // Shadows & Lighting ImGui::NewLine(); - ImGui::SameLine(); + ImGui::NewLine(); ImGui::SameLine(); ImGui::Checkbox("Light Affected ", &m_AffectedByLight); ImGui::SameLine(); ImGui::Checkbox("Scene Color Affected", &m_AffectedBySceneColor); @@ -1598,6 +1628,23 @@ double ComponentParticleEmitter::GetRandomValue(double min, double max) //EREASE return App->RandomNumberGenerator.GetDoubleRNinRange(min, max); } +void ComponentParticleEmitter::SetActiveCollisions(bool collisionsActive) +{ + if (collisionsActive){ + physx::PxFilterData filterData; + filterData.word0 = (1 << GO->layer); + filterData.word1 = App->physics->layer_list.at(GO->layer).LayerGroup; + particleSystem->setSimulationFilterData(filterData); + } + else{ + physx::PxFilterData filterData; + filterData.word0 = 0; + filterData.word1 = 0; + particleSystem->setSimulationFilterData(filterData); + + } +} + void ComponentParticleEmitter::CreateParticles(uint particlesAmount) { uint particlesToCreate = particlesAmount; diff --git a/Broken Engine/Source/ComponentParticleEmitter.h b/Broken Engine/Source/ComponentParticleEmitter.h index 1a5a814d4..9d7e01958 100644 --- a/Broken Engine/Source/ComponentParticleEmitter.h +++ b/Broken Engine/Source/ComponentParticleEmitter.h @@ -83,6 +83,9 @@ class BROKEN_API ComponentParticleEmitter : public Component double GetRandomValue(double min, double max); //MUST EREASE IN THE FUTURE void HandleEditorBlendingSelector(); + // -- Decide if particles collide with the envioronment or not -- + void SetActiveCollisions(bool collisionsActive); + private: physx::PxParticleSystem* particleSystem = nullptr; @@ -104,7 +107,7 @@ class BROKEN_API ComponentParticleEmitter : public Component float3 eulerRotation = float3::zero; Quat emitterRotation = Quat::identity; int particlesPerCreation = 1; - physx::PxVec3 size = { 0,0,0 }; + physx::PxVec3 size = { 0.01,0.01,0.01 }; float emisionRate = 500.0f; //in milliseconds physx::PxVec3 externalAcceleration = { 0,10,0 }; physx::PxVec3 particlesVelocity = { 0,0,0 }; @@ -112,6 +115,7 @@ class BROKEN_API ComponentParticleEmitter : public Component physx::PxVec3 velocityRandomFactor2 = { 0,0,0 }; bool loop = true; bool emisionActive = true; + bool playOnAwake = false; int duration = 1000; uint emisionStart = 0; diff --git a/Broken Engine/Source/ModuleParticles.cpp b/Broken Engine/Source/ModuleParticles.cpp index fe358e916..28f446f1d 100644 --- a/Broken Engine/Source/ModuleParticles.cpp +++ b/Broken Engine/Source/ModuleParticles.cpp @@ -75,18 +75,18 @@ void ModuleParticles::DrawParticles(bool shadowsPass) Plane cameraPlanes[6]; App->renderer3D->culling_camera->frustum.GetPlanes(cameraPlanes); - std::map::iterator it = particlesToDraw.begin(); + std::map::iterator it = particlesToDraw.begin(); while (it != particlesToDraw.end()) { - if ((*it).first->emitter != nullptr) + if ((*it).second->emitter != nullptr) { //Check if the particles are inside the frustum of the camera bool draw = true; for (int i = 0; i < 6; ++i) { //If the particles is on the positive side of one ore more planes, it's outside the frustum - bool shadowsHandle = ((shadowsPass && (*it).first->emitter->m_CastShadows == false) || (!shadowsPass && (*it).first->emitter->m_OnlyShadows)); - if (cameraPlanes[i].IsOnPositiveSide((*it).first->position) || shadowsHandle) + bool shadowsHandle = ((shadowsPass && (*it).second->emitter->m_CastShadows == false) || (!shadowsPass && (*it).second->emitter->m_OnlyShadows)); + if (cameraPlanes[i].IsOnPositiveSide((*it).second->position) || shadowsHandle) { draw = false; break; @@ -95,19 +95,19 @@ void ModuleParticles::DrawParticles(bool shadowsPass) if (draw) { - if (!shadowsPass && (*it).first->emitter) + if (!shadowsPass && (*it).second->emitter) { - (*it).first->emitter->SetEmitterBlending(); - if ((*it).first->emitter->particlesFaceCulling) + (*it).second->emitter->SetEmitterBlending(); + if ((*it).second->emitter->particlesFaceCulling) glEnable(GL_CULL_FACE); else glDisable(GL_CULL_FACE); } - (*it).first->Draw(shadowsPass); + (*it).second->Draw(shadowsPass); if (!shadowsPass) - if ((*it).first->emitter->particlesFaceCulling == false) + if ((*it).second->emitter->particlesFaceCulling == false) glEnable(GL_CULL_FACE); } } diff --git a/Broken Engine/Source/ModuleParticles.h b/Broken Engine/Source/ModuleParticles.h index 8f6993fc9..c268851be 100644 --- a/Broken Engine/Source/ModuleParticles.h +++ b/Broken Engine/Source/ModuleParticles.h @@ -29,7 +29,7 @@ class BROKEN_API ModuleParticles : public Module public: - std::map particlesToDraw; + std::map particlesToDraw; std::vector particleEmitters; }; diff --git a/Broken Engine/Source/Particle.h b/Broken Engine/Source/Particle.h index a5a645a39..dc4e2952d 100644 --- a/Broken Engine/Source/Particle.h +++ b/Broken Engine/Source/Particle.h @@ -33,6 +33,8 @@ class BROKEN_API Particle { float3 rotationSpeed = { 0,0,0 }; float3 scaleSpeed = { 0,0,0 }; float3 emitterSpawnPosition = { 0,0,0 }; + float distanceToCam = 0.0f; + int startFrame = 0; bool h_billboard = false;