💿🐜 Antkeeper source code https://antkeeper.com
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

161 lines
3.8 KiB

  1. /*
  2. * Copyright (C) 2017-2019 Christopher J. Howard
  3. *
  4. * This file is part of Antkeeper Source Code.
  5. *
  6. * Antkeeper Source Code is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * Antkeeper Source Code is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with Antkeeper Source Code. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. #include "particle-system.hpp"
  20. #include "../../game/curl-noise.hpp"
  21. ParticleSystem::ParticleSystem(ComponentManager* componentManager):
  22. System(componentManager),
  23. range(nullptr),
  24. material(nullptr)
  25. {
  26. batch.setTransform(Transform::getIdentity());
  27. batch.setCullingEnabled(false);
  28. }
  29. ParticleSystem::~ParticleSystem()
  30. {}
  31. void ParticleSystem::resize(std::size_t count)
  32. {
  33. particles.resize(count);
  34. batch.resize(count);
  35. range = batch.addRange();
  36. range->start = 0;
  37. range->length = particles.size();
  38. range->material = material;
  39. while (!stack.empty())
  40. stack.pop();
  41. for (int i = 0; i < particles.size(); ++i)
  42. {
  43. Particle& particle = particles[i];
  44. particle.life = 0.0f;
  45. particle.size = 0.0f;
  46. Billboard* billboard = batch.getBillboard(i);
  47. billboard->setDimensions(Vector2(particle.size));
  48. billboard->resetTweens();
  49. stack.push(i);
  50. }
  51. }
  52. void ParticleSystem::emit(const Vector3& position)
  53. {
  54. if (!stack.empty())
  55. {
  56. std::size_t index = stack.top();
  57. stack.pop();
  58. Particle& particle = particles[index];
  59. particle.life = frand(1.0f, 5.0f);
  60. particle.translation = position;
  61. particle.size = frand(0.01f, 0.2f);
  62. particle.speed = frand(2.0f, 3.0f);
  63. particle.direction = direction + Vector3(frand(-1, 1), 0, frand(-1, 1)) * 0.1f;
  64. particle.direction = glm::normalize(particle.direction);
  65. Billboard* billboard = batch.getBillboard(index);
  66. billboard->setTranslation(particle.translation);
  67. billboard->setRotation(Quaternion(1, 0, 0, 0));
  68. billboard->setDimensions(Vector2(particle.size));
  69. billboard->setTintColor(Vector4(1.0f));
  70. billboard->resetTweens();
  71. }
  72. }
  73. void ParticleSystem::update(float t, float dt)
  74. {
  75. if (stack.size() == particles.size())
  76. {
  77. // Inactive
  78. return;
  79. }
  80. batch.reset();
  81. const Vector3 wind = glm::normalize(Vector3(1.0f, 0.0f, -1.0f)) * 1.5f * dt;
  82. float frequency = 0.4f;
  83. Vector3 noiseOffset = Vector3(77.7f, 33.3f, 11.1f) * t * 0.01f;
  84. for (std::size_t i = 0; i < particles.size(); ++i)
  85. {
  86. Particle& particle = particles[i];
  87. if (particle.life <= 0.0f)
  88. {
  89. continue;
  90. }
  91. Billboard* billboard = batch.getBillboard(i);
  92. bool reset = false;
  93. Vector3 smoke = curl(particle.translation, noiseOffset, frequency) * 8.0f;
  94. particle.translation += particle.direction * particle.speed * dt + smoke * dt + wind;
  95. particle.size += 0.1f * dt;
  96. particle.life -= dt;
  97. if (particle.life <= 0.0f)
  98. {
  99. particle.size = 0.0f;
  100. reset = true;
  101. stack.push(i);
  102. }
  103. billboard->setTranslation(particle.translation);
  104. billboard->setRotation(Quaternion(1, 0, 0, 0));
  105. billboard->setDimensions(Vector2(particle.size));
  106. billboard->setTintColor(Vector4(0.5f));
  107. if (reset)
  108. {
  109. billboard->resetTweens();
  110. }
  111. }
  112. }
  113. void ParticleSystem::setMaterial(Material* material)
  114. {
  115. this->material = material;
  116. if (range)
  117. {
  118. range->material = material;
  119. }
  120. }
  121. void ParticleSystem::setDirection(const Vector3& direction)
  122. {
  123. this->direction = direction;
  124. }
  125. void ParticleSystem::setLifeTime(float time)
  126. {
  127. this->lifeTime = time;
  128. }
  129. void ParticleSystem::setEmissionRate(float frequency)
  130. {
  131. this->emissionRate = frequency;
  132. }