|
|
- /*
- * Copyright (C) 2017-2019 Christopher J. Howard
- *
- * This file is part of Antkeeper Source Code.
- *
- * Antkeeper Source Code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Antkeeper Source Code is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Antkeeper Source Code. If not, see <http://www.gnu.org/licenses/>.
- */
-
- #include "particle-system.hpp"
- #include "../../game/curl-noise.hpp"
-
- ParticleSystem::ParticleSystem(ComponentManager* componentManager):
- System(componentManager),
- range(nullptr),
- material(nullptr)
- {
- batch.setTransform(Transform::getIdentity());
- batch.setCullingEnabled(false);
- }
-
- ParticleSystem::~ParticleSystem()
- {}
-
- void ParticleSystem::resize(std::size_t count)
- {
- particles.resize(count);
- batch.resize(count);
- range = batch.addRange();
- range->start = 0;
- range->length = particles.size();
- range->material = material;
-
- while (!stack.empty())
- stack.pop();
-
- for (int i = 0; i < particles.size(); ++i)
- {
- Particle& particle = particles[i];
- particle.life = 0.0f;
- particle.size = 0.0f;
-
- Billboard* billboard = batch.getBillboard(i);
- billboard->setDimensions(Vector2(particle.size));
- billboard->resetTweens();
-
- stack.push(i);
- }
- }
-
- void ParticleSystem::emit(const Vector3& position)
- {
- if (!stack.empty())
- {
- std::size_t index = stack.top();
- stack.pop();
-
- Particle& particle = particles[index];
- particle.life = frand(1.0f, 5.0f);
- particle.translation = position;
- particle.size = frand(0.01f, 0.2f);
- particle.speed = frand(2.0f, 3.0f);
- particle.direction = direction + Vector3(frand(-1, 1), 0, frand(-1, 1)) * 0.1f;
- particle.direction = glm::normalize(particle.direction);
-
- Billboard* billboard = batch.getBillboard(index);
- billboard->setTranslation(particle.translation);
- billboard->setRotation(Quaternion(1, 0, 0, 0));
- billboard->setDimensions(Vector2(particle.size));
- billboard->setTintColor(Vector4(1.0f));
- billboard->resetTweens();
- }
- }
-
- void ParticleSystem::update(float t, float dt)
- {
- if (stack.size() == particles.size())
- {
- // Inactive
- return;
- }
-
- batch.reset();
-
- const Vector3 wind = glm::normalize(Vector3(1.0f, 0.0f, -1.0f)) * 1.5f * dt;
- float frequency = 0.4f;
- Vector3 noiseOffset = Vector3(77.7f, 33.3f, 11.1f) * t * 0.01f;
-
- for (std::size_t i = 0; i < particles.size(); ++i)
- {
- Particle& particle = particles[i];
- if (particle.life <= 0.0f)
- {
- continue;
- }
-
-
- Billboard* billboard = batch.getBillboard(i);
-
- bool reset = false;
-
- Vector3 smoke = curl(particle.translation, noiseOffset, frequency) * 8.0f;
-
-
- particle.translation += particle.direction * particle.speed * dt + smoke * dt + wind;
- particle.size += 0.1f * dt;
- particle.life -= dt;
- if (particle.life <= 0.0f)
- {
- particle.size = 0.0f;
- reset = true;
-
- stack.push(i);
- }
-
- billboard->setTranslation(particle.translation);
- billboard->setRotation(Quaternion(1, 0, 0, 0));
- billboard->setDimensions(Vector2(particle.size));
- billboard->setTintColor(Vector4(0.5f));
-
- if (reset)
- {
- billboard->resetTweens();
- }
- }
- }
-
- void ParticleSystem::setMaterial(Material* material)
- {
- this->material = material;
- if (range)
- {
- range->material = material;
- }
- }
-
- void ParticleSystem::setDirection(const Vector3& direction)
- {
- this->direction = direction;
- }
-
- void ParticleSystem::setLifeTime(float time)
- {
- this->lifeTime = time;
- }
-
- void ParticleSystem::setEmissionRate(float frequency)
- {
- this->emissionRate = frequency;
- }
-
|