💿🐜 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.

176 lines
4.7 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 "lens.hpp"
  20. #include "camera-rig.hpp"
  21. #include "../entity/systems/particle-system.hpp"
  22. Lens::Lens(const Model* model, Animator* animator):
  23. wasActive(false),
  24. particleSystem(nullptr)
  25. {
  26. // Setup model instance
  27. modelInstance.setModel(model);
  28. modelInstance.setCullingEnabled(false);
  29. // Setup spotlight
  30. spotlight.setColor(Vector3(1.0f));
  31. spotlight.setIntensity(1000.0f);
  32. spotlight.setAttenuation(Vector3(1, 0, 1));
  33. spotlight.setCutoff(std::cos(glm::radians(45.0f)));
  34. spotlight.setExponent(150.0f);
  35. spotlight.setActive(false);
  36. unfocusedDistance = 18.0f;
  37. unfocusDuration = 0.25f;
  38. focusedDistance = 12.0f;
  39. focusDuration = 0.75f;
  40. lensDistance = unfocusedDistance;
  41. focused = false;
  42. lastDistance = unfocusedDistance;
  43. sunDirection = Vector3(0, -1, 0);
  44. // Construct focus animation clip
  45. AnimationChannel<float>* channel;
  46. focusClip.setInterpolator(easeOutCubic<float>);
  47. channel = focusClip.addChannel(0);
  48. channel->insertKeyframe(0.0f, 0.0f);
  49. channel->insertKeyframe(focusDuration, 1.0f);
  50. // Construct unfocus animation clip
  51. unfocusClip.setInterpolator(easeOutCubic<float>);
  52. channel = unfocusClip.addChannel(0);
  53. channel->insertKeyframe(0.0f, 0.0f);
  54. channel->insertKeyframe(unfocusDuration, 1.0f);
  55. // Setup focus animation callbacks
  56. focusAnimation.setTimeFrame(focusClip.getTimeFrame());
  57. focusAnimation.setClip(&focusClip);
  58. focusAnimation.setAnimateCallback
  59. (
  60. [this](std::size_t id, float distance)
  61. {
  62. this->lensDistance = lerp(lastDistance, focusedDistance, distance);
  63. }
  64. );
  65. focusAnimation.setEndCallback
  66. (
  67. [this]()
  68. {
  69. this->focused = true;
  70. }
  71. );
  72. // Setup unfocus animation callbacks
  73. unfocusAnimation.setTimeFrame(unfocusClip.getTimeFrame());
  74. unfocusAnimation.setClip(&unfocusClip);
  75. unfocusAnimation.setAnimateCallback
  76. (
  77. [this](std::size_t id, float distance)
  78. {
  79. this->lensDistance = lerp(lastDistance, unfocusedDistance, distance);
  80. }
  81. );
  82. // Add animations to animator
  83. animator->addAnimation(&focusAnimation);
  84. animator->addAnimation(&unfocusAnimation);
  85. }
  86. Lens::~Lens()
  87. {}
  88. void Lens::update(float dt)
  89. {
  90. //Quaternion alignment = glm::rotation(Vector3(0, 1, 0), -sunDirection) * glm::angleAxis(glm::radians(90.0f), Vector3(0, 1, 0));
  91. Quaternion alignment = glm::rotation(Vector3(0, 1, 0), -sunDirection) * glm::angleAxis(orbitCam->getAzimuth() + glm::radians(90.0f), Vector3(0, 1, 0));
  92. Quaternion rotation = glm::normalize(alignment);
  93. Vector3 translation = pick + sunDirection * -lensDistance;
  94. modelInstance.setTranslation(translation);
  95. modelInstance.setRotation(rotation);
  96. float t = (1.0 - (lensDistance - focusedDistance) / (unfocusedDistance - focusedDistance));
  97. float unfocusedIntensity = 250.0f * 2.0f;
  98. float focusedIntensity = 1000.0f * 2.0f;
  99. float intensity = easeInExpo(unfocusedIntensity, focusedIntensity, t);
  100. float unfocusedExponent = 100.0f;
  101. float focusedExponent = 5000.0f;
  102. float exponent = easeInExpo(unfocusedExponent, focusedExponent, t);
  103. spotlight.setIntensity(intensity);
  104. spotlight.setExponent(exponent);
  105. spotlight.setTranslation(pick + sunDirection * -lensDistance);
  106. spotlight.setDirection(sunDirection);
  107. if (active && !wasActive)
  108. {
  109. modelInstance.resetTweens();
  110. spotlight.resetTweens();
  111. modelInstance.setActive(true);
  112. spotlight.setActive(true);
  113. }
  114. else if (!active && wasActive)
  115. {
  116. modelInstance.setActive(false);
  117. spotlight.setActive(false);
  118. }
  119. if (active && focused)
  120. {
  121. int count = 10;
  122. for (int i = 0; i < count; ++i)
  123. particleSystem->emit(pick);
  124. }
  125. wasActive = active;
  126. }
  127. void Lens::focus()
  128. {
  129. lastDistance = lensDistance;
  130. unfocusAnimation.stop();
  131. focusAnimation.rewind();
  132. focusAnimation.play();
  133. }
  134. void Lens::unfocus()
  135. {
  136. lastDistance = lensDistance;
  137. focusAnimation.stop();
  138. unfocusAnimation.rewind();
  139. unfocusAnimation.play();
  140. focused = false;
  141. }
  142. void Lens::setSunDirection(const Vector3& direction)
  143. {
  144. sunDirection = direction;
  145. }
  146. void Lens::setParticleSystem(ParticleSystem* particleSystem)
  147. {
  148. this->particleSystem = particleSystem;
  149. }