/xbmc/screensavers/rsxs-0.9/src/solarwinds/wind.cc

http://github.com/xbmc/xbmc · C++ · 232 lines · 182 code · 16 blank · 34 comment · 32 complexity · cb1964cb0366c028d5e04183f318dd93 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) 2002 Terence M. Welsh, available from www.reallyslick.com
  22. */
  23. #include <common.hh>
  24. #include <climits>
  25. #include <solarwinds.hh>
  26. #include <resource.hh>
  27. #include <wind.hh>
  28. #define LIGHTSIZE 64
  29. GLuint Wind::_list;
  30. GLuint Wind::_texture;
  31. void Wind::init() {
  32. switch (Hack::geometry) {
  33. case Hack::LIGHTS_GEOMETRY:
  34. {
  35. GLubyte light[LIGHTSIZE][LIGHTSIZE];
  36. for (int i = 0; i < LIGHTSIZE; ++i) {
  37. for(int j = 0; j < LIGHTSIZE; ++j) {
  38. float x = float(i - LIGHTSIZE / 2) / float(LIGHTSIZE / 2);
  39. float y = float(j - LIGHTSIZE / 2) / float(LIGHTSIZE / 2);
  40. float temp = Common::clamp(
  41. 1.0f - float(std::sqrt((x * x) + (y * y))),
  42. 0.0f, 1.0f
  43. );
  44. light[i][j] = GLubyte(255.0f * temp);
  45. }
  46. }
  47. _texture = Common::resources->genTexture(
  48. GL_LINEAR, GL_LINEAR, GL_REPEAT, GL_REPEAT,
  49. 1, LIGHTSIZE, LIGHTSIZE, GL_LUMINANCE, GL_UNSIGNED_BYTE, light,
  50. false
  51. );
  52. glEnable(GL_TEXTURE_2D);
  53. glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
  54. float temp = 0.02f * Hack::size;
  55. _list = Common::resources->genLists(1);
  56. glNewList(_list, GL_COMPILE);
  57. glBindTexture(GL_TEXTURE_2D, _texture);
  58. glBegin(GL_TRIANGLE_STRIP);
  59. glTexCoord2f(0.0f, 0.0f);
  60. glVertex3f(-temp, -temp, 0.0f);
  61. glTexCoord2f(1.0f, 0.0f);
  62. glVertex3f(temp, -temp, 0.0f);
  63. glTexCoord2f(0.0f, 1.0f);
  64. glVertex3f(-temp, temp, 0.0f);
  65. glTexCoord2f(1.0f, 1.0f);
  66. glVertex3f(temp, temp, 0.0f);
  67. glEnd();
  68. glEndList();
  69. }
  70. break;
  71. case Hack::POINTS_GEOMETRY:
  72. glEnable(GL_POINT_SMOOTH);
  73. glHint(GL_POINT_SMOOTH_HINT, GL_NICEST);
  74. break;
  75. case Hack::LINES_GEOMETRY:
  76. glEnable(GL_LINE_SMOOTH);
  77. glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
  78. break;
  79. }
  80. }
  81. Wind::Wind() {
  82. for (unsigned int i = 0; i < Hack::numEmitters; ++i)
  83. _emitters.push_back(Vector(
  84. Common::randomFloat(60.0f) - 30.0f,
  85. Common::randomFloat(60.0f) - 30.0f,
  86. Common::randomFloat(30.0f) - 15.0f
  87. ));
  88. _particlesXYZ.resize(Hack::numParticles, Vector(0.0f, 0.0f, 100.0f));
  89. _particlesRGB.resize(Hack::numParticles, RGBColor());
  90. _whichParticle = 0;
  91. if (Hack::geometry == Hack::LINES_GEOMETRY) {
  92. _lineList.resize(Hack::numParticles, std::make_pair(UINT_MAX, UINT_MAX));
  93. for (unsigned int i = 0; i < Hack::numEmitters; ++i)
  94. _lastParticle.push_back(i);
  95. }
  96. for (unsigned int i = 0; i < NUMCONSTS; ++i) {
  97. _ct[i] = Common::randomFloat(M_PI * 2.0f);
  98. _cv[i] = Common::randomFloat(
  99. 0.00005f * float(Hack::windSpeed) * float(Hack::windSpeed)
  100. ) + 0.00001f * float(Hack::windSpeed) * float(Hack::windSpeed);
  101. }
  102. }
  103. void Wind::update() {
  104. // update constants
  105. for (unsigned int i = 0; i < NUMCONSTS; ++i) {
  106. _ct[i] += _cv[i];
  107. if (_ct[i] > M_PI * 2.0f)
  108. _ct[i] -= M_PI * 2.0f;
  109. _c[i] = std::cos(_ct[i]);
  110. }
  111. static float eVel = Hack::emitterSpeed * 0.01f;
  112. // calculate emissions
  113. for (unsigned int i = 0; i < Hack::numEmitters; ++i) {
  114. // emitter moves toward viewer
  115. _emitters[i].z() += eVel;
  116. if (_emitters[i].z() > 15.0f) // reset emitter
  117. _emitters[i].set(
  118. Common::randomFloat(60.0f) - 30.0f,
  119. Common::randomFloat(60.0f) - 30.0f,
  120. -15.0f
  121. );
  122. _particlesXYZ[_whichParticle] = _emitters[i];
  123. if (Hack::geometry == Hack::LINES_GEOMETRY) {
  124. // link particles to form lines
  125. if (_lineList[_whichParticle].first != UINT_MAX)
  126. _lineList[_lineList[_whichParticle].first].second = UINT_MAX;
  127. _lineList[_whichParticle].first = UINT_MAX;
  128. if (_emitters[i].z() == -15.0f)
  129. _lineList[_whichParticle].second = UINT_MAX;
  130. else
  131. _lineList[_whichParticle].second = _lastParticle[i];
  132. _lineList[_lastParticle[i]].first = _whichParticle;
  133. _lastParticle[i] = _whichParticle;
  134. }
  135. ++_whichParticle;
  136. if (_whichParticle >= Hack::numParticles)
  137. _whichParticle = 0;
  138. }
  139. // calculate particle positions and colors
  140. // first modify constants that affect colors
  141. _c[6] *= 9.0f / Hack::particleSpeed;
  142. _c[7] *= 9.0f / Hack::particleSpeed;
  143. _c[8] *= 9.0f / Hack::particleSpeed;
  144. // then update each particle
  145. static float pVel = Hack::particleSpeed * 0.01f;
  146. for (unsigned int i = 0; i < Hack::numParticles; ++i) {
  147. // store old positions
  148. float x = _particlesXYZ[i].x();
  149. float y = _particlesXYZ[i].y();
  150. float z = _particlesXYZ[i].z();
  151. // make new positions
  152. _particlesXYZ[i].set(
  153. x + (_c[0] * y + _c[1] * z) * pVel,
  154. y + (_c[2] * z + _c[3] * x) * pVel,
  155. z + (_c[4] * x + _c[5] * y) * pVel
  156. );
  157. // calculate colors
  158. _particlesRGB[i].set(
  159. std::abs((_particlesXYZ[i].x() - x) * _c[6]),
  160. std::abs((_particlesXYZ[i].y() - y) * _c[7]),
  161. std::abs((_particlesXYZ[i].z() - z) * _c[8])
  162. );
  163. // clamp colors
  164. _particlesRGB[i].clamp();
  165. }
  166. static float pointSize = 0.04f * Hack::size;
  167. static float lineSize = 0.005f * Hack::size;
  168. // draw particles
  169. switch (Hack::geometry) {
  170. case Hack::LIGHTS_GEOMETRY:
  171. for (unsigned int i = 0; i < Hack::numParticles; ++i) {
  172. glColor3fv(_particlesRGB[i].get());
  173. glPushMatrix();
  174. glTranslatef(
  175. _particlesXYZ[i].x(),
  176. _particlesXYZ[i].y(),
  177. _particlesXYZ[i].z()
  178. );
  179. glCallList(_list);
  180. glPopMatrix();
  181. }
  182. break;
  183. case Hack::POINTS_GEOMETRY:
  184. for (unsigned int i = 0; i < Hack::numParticles; ++i) {
  185. float temp = _particlesXYZ[i].z() + 40.0f;
  186. if (temp < 0.01f) temp = 0.01f;
  187. glPointSize(pointSize * temp);
  188. glBegin(GL_POINTS);
  189. glColor3fv(_particlesRGB[i].get());
  190. glVertex3fv(_particlesXYZ[i].get());
  191. glEnd();
  192. }
  193. break;
  194. case Hack::LINES_GEOMETRY:
  195. {
  196. for (unsigned int i = 0; i < Hack::numParticles; ++i) {
  197. float temp = _particlesXYZ[i].z() + 40.0f;
  198. if (temp < 0.01f) temp = 0.01f;
  199. glLineWidth(lineSize * temp);
  200. glBegin(GL_LINES);
  201. if (_lineList[i].second != UINT_MAX) {
  202. glColor3fv(_particlesRGB[i].get());
  203. if (_lineList[i].first == UINT_MAX)
  204. glColor3f(0.0f, 0.0f, 0.0f);
  205. glVertex3fv(_particlesXYZ[i].get());
  206. glColor3fv(_particlesRGB[_lineList[i].second].get());
  207. if (_lineList[_lineList[i].second].second == UINT_MAX)
  208. glColor3f(0.0f, 0.0f, 0.0f);
  209. glVertex3fv(_particlesXYZ[_lineList[i].second].get());
  210. }
  211. glEnd();
  212. }
  213. }
  214. break;
  215. }
  216. }