/xbmc/screensavers/rsxs-0.9/src/hyperspace/goo.cc

http://github.com/xbmc/xbmc · C++ · 169 lines · 120 code · 21 blank · 28 comment · 14 complexity · db921e54c34514b7e6674b9e63c20647 MD5 · raw file

  1. /*
  2. * Really Slick XScreenSavers
  3. * Copyright (C) 2002-2006 Michael Chapman
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License version 2 as
  7. * published by the Free Software Foundation.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program; if not, write to the Free Software
  16. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  17. *
  18. *****************************************************************************
  19. *
  20. * This is a Linux port of the Really Slick Screensavers,
  21. * Copyright (C) 2005 Terence M. Welsh, available from www.reallyslick.com
  22. */
  23. #include <common.hh>
  24. #include <goo.hh>
  25. #include <hyperspace.hh>
  26. #include <implicit.hh>
  27. #include <nebula.hh>
  28. #include <vector.hh>
  29. namespace Goo {
  30. int _resolution;
  31. float _unitSize;
  32. float _volumeSize;
  33. int _arraySize;
  34. std::vector<Implicit> _surface;
  35. std::vector<bool> _useSurface;
  36. float _centerX, _centerZ;
  37. float _shiftX, _shiftZ;
  38. float _goo[4];
  39. float _gooPhase[4] = { 0.0f, 1.0f, 2.0f, 3.0f };
  40. float _gooSpeed[4] = {
  41. 0.1f + Common::randomFloat(0.4f),
  42. 0.1f + Common::randomFloat(0.4f),
  43. 0.1f + Common::randomFloat(0.4f),
  44. 0.1f + Common::randomFloat(0.4f)
  45. };
  46. float _gooRGB[4];
  47. float function(const Vector&);
  48. };
  49. #define AT(x, y) ((x) * _arraySize + (y))
  50. void Goo::init() {
  51. _volumeSize = 2.0f;
  52. _resolution = (Hack::resolution < 5 ? 5 : Hack::resolution);
  53. _unitSize = _volumeSize / float(_resolution);
  54. _arraySize = 2 * int(0.99f + Hack::fogDepth / _volumeSize);
  55. Implicit::init(_resolution, _resolution, _resolution, _unitSize);
  56. stdx::construct_n(_surface, _arraySize * _arraySize, &function);
  57. stdx::construct_n(_useSurface, _arraySize * _arraySize, false);
  58. }
  59. void Goo::update(float heading, float fov) {
  60. float halfFov = 0.5f * fov;
  61. _centerX = _unitSize * float(int(0.5f + Hack::camera.x() / _unitSize));
  62. _centerZ = _unitSize * float(int(0.5f + Hack::camera.z() / _unitSize));
  63. float clip[3][2];
  64. clip[0][0] = std::cos(heading + halfFov);
  65. clip[0][1] = -std::sin(heading + halfFov);
  66. clip[1][0] = -std::cos(heading - halfFov);
  67. clip[1][1] = std::sin(heading - halfFov);
  68. clip[2][0] = std::sin(heading);
  69. clip[2][1] = -std::cos(heading);
  70. for (int i = 0; i < _arraySize; ++i) {
  71. for (int j = 0; j < _arraySize; ++j) {
  72. _shiftX = _volumeSize * (0.5f + float(int(i) - int(_arraySize) / 2));
  73. _shiftZ = _volumeSize * (0.5f + float(int(j) - int(_arraySize) / 2));
  74. if (_shiftX * clip[0][0] + _shiftZ * clip[0][1] > _volumeSize * -M_SQRT2) {
  75. if (_shiftX * clip[1][0] + _shiftZ * clip[1][1] > _volumeSize * -M_SQRT2) {
  76. if (_shiftX * clip[2][0] + _shiftZ * clip[2][1] < Hack::fogDepth + _volumeSize * M_SQRT2) {
  77. _shiftX += _centerX;
  78. _shiftZ += _centerZ;
  79. _surface[AT(i, j)].update(0.4f);
  80. _useSurface[AT(i, j)] = true;
  81. }
  82. }
  83. }
  84. }
  85. }
  86. // calculate color
  87. static float gooRGBphase[3] = { -0.1f, -0.1f, -0.1f };
  88. static float gooRGBspeed[3] = {
  89. Common::randomFloat(0.02f) + 0.02f,
  90. Common::randomFloat(0.02f) + 0.02f,
  91. Common::randomFloat(0.02f) + 0.02f
  92. };
  93. for (int i = 0; i < 3; ++i) {
  94. gooRGBphase[i] += gooRGBspeed[i] * Common::elapsedTime;
  95. if (gooRGBphase[i] >= M_PI * 2.0f) gooRGBphase[i] -= M_PI * 2.0f;
  96. _gooRGB[i] = std::sin(gooRGBphase[i]);
  97. if (_gooRGB[i] < 0.0f) _gooRGB[i] = 0.0f;
  98. }
  99. // update goo function constants
  100. for (int i = 0; i < 4; ++i) {
  101. _gooPhase[i] += _gooSpeed[i] * Common::elapsedTime;
  102. if (_gooPhase[i] >= M_PI * 2.0f) _gooPhase[i] -= M_PI * 2.0f;
  103. _goo[i] = 0.25f * std::cos(_gooPhase[i]);
  104. }
  105. }
  106. void Goo::draw() {
  107. glPushAttrib(GL_ENABLE_BIT);
  108. Nebula::use();
  109. if (Hack::shaders)
  110. _gooRGB[3] = Hack::lerp;
  111. else
  112. _gooRGB[3] = 1.0f;
  113. glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
  114. glBlendFunc(GL_SRC_ALPHA, GL_ONE);
  115. glEnable(GL_BLEND);
  116. glColor4fv(_gooRGB);
  117. for (int i = 0; i < _arraySize; ++i) {
  118. for (int j = 0; j < _arraySize; ++j) {
  119. if (_useSurface[AT(i, j)]) {
  120. float shiftX = _centerX + _volumeSize * (0.5f + float(int(i) - int(_arraySize) / 2));
  121. float shiftZ = _centerZ + _volumeSize * (0.5f + float(int(j) - int(_arraySize) / 2));
  122. glPushMatrix();
  123. glTranslatef(shiftX, 0.0f, shiftZ);
  124. _surface[AT(i, j)].draw();
  125. glPopMatrix();
  126. _useSurface[AT(i, j)] = false;
  127. }
  128. }
  129. }
  130. glPopAttrib();
  131. }
  132. float Goo::function(const Vector& XYZ) {
  133. float pX = XYZ.x() + _shiftX;
  134. float pZ = XYZ.z() + _shiftZ;
  135. float camX = pX - Hack::camera.x();
  136. float camZ = pZ - Hack::camera.z();
  137. return
  138. // This first term defines upper and lower surfaces.
  139. XYZ.y() * XYZ.y() * 1.25f
  140. // These terms make the surfaces wavy.
  141. + _goo[0] * std::cos(pX - 2.71f * XYZ.y())
  142. + _goo[1] * std::cos(4.21f * XYZ.y() + pZ)
  143. + _goo[2] * std::cos(1.91f * pX - 1.67f * pZ)
  144. + _goo[3] * std::cos(1.53f * pX + 1.11f * XYZ.y() + 2.11f * pZ)
  145. // The last term creates a bubble around the eyepoint so it doesn't
  146. // punch through the surface.
  147. - 0.1f / (camX * camX + XYZ.y() * XYZ.y() + camZ * camZ);
  148. }