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

http://github.com/xbmc/xbmc · C++ · 311 lines · 236 code · 33 blank · 42 comment · 29 complexity · e001bfff2b59a4ae24cf7ed2b94dc69b 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 FoundAT2on.
  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. * FoundAT2on, 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 <caustic.hh>
  25. #include <hyperspace.hh>
  26. #define CAUSTIC_RESOLUTION 100
  27. #define CAUSTIC_SIZE 256
  28. #define CAUSTIC_DEPTH 1.0f
  29. #define CAUSTIC_AMPLITUDE 0.01f
  30. #define CAUSTIC_REFRACTION 20.0f
  31. namespace CausticTextures {
  32. std::vector<GLuint> _textures;
  33. void draw(
  34. const stdx::dim2<float, CAUSTIC_RESOLUTION + 1>&,
  35. const float*, const float*,
  36. const stdx::dim2<std::pair<float, float>, CAUSTIC_RESOLUTION + 1>&,
  37. unsigned int, unsigned int, unsigned int, unsigned int
  38. );
  39. };
  40. void CausticTextures::init() {
  41. unsigned int size = CAUSTIC_SIZE;
  42. if (Common::width < size) size = Common::width;
  43. if (Common::height < size) size = Common::height;
  44. float x[CAUSTIC_RESOLUTION + 1];
  45. float z[CAUSTIC_RESOLUTION + 1];
  46. stdx::dim2<float, CAUSTIC_RESOLUTION> y[Hack::frames];
  47. for (unsigned int i = 0; i < Hack::frames; ++i)
  48. y[i].resize(CAUSTIC_RESOLUTION);
  49. stdx::dim2<std::pair<float, float>, CAUSTIC_RESOLUTION + 1> xz(CAUSTIC_RESOLUTION + 1);
  50. stdx::dim2<float, CAUSTIC_RESOLUTION + 1> intensity(CAUSTIC_RESOLUTION + 1);
  51. // set x and z geometry positions
  52. for (unsigned int i = 0; i <= CAUSTIC_RESOLUTION; ++i) {
  53. x[i] = z[i] = float(i) / float(CAUSTIC_RESOLUTION);
  54. }
  55. // set y geometry positions (altitudes)
  56. for (unsigned int k = 0; k < Hack::frames; ++k) {
  57. float offset = M_PI * 2.0f * float(k) / float(Hack::frames);
  58. for (unsigned int i = 0; i < CAUSTIC_RESOLUTION; ++i) {
  59. float xx = M_PI * 2.0f * float(i) / float(CAUSTIC_RESOLUTION);
  60. for (unsigned int j = 0; j < CAUSTIC_RESOLUTION; ++j) {
  61. float zz = M_PI * 2.0f * float(j) / float(CAUSTIC_RESOLUTION);
  62. y[k](i, j) = CAUSTIC_AMPLITUDE * (
  63. 0.08f * std::cos(xx * 2.0f + offset)
  64. + 0.06f * std::cos(-1.0f * xx + 2.0f * zz + offset)
  65. + 0.04f * std::cos(-2.0f * xx - 3.0f * zz + offset)
  66. + 0.01f * std::cos(xx - 7.0f * zz - 2.0f * offset)
  67. + 0.01f * std::cos(3.0f * xx + 5.0f * zz + offset)
  68. + 0.01f * std::cos(9.0f * xx + zz - offset)
  69. + 0.005f * std::cos(11.0f * xx + 7.0f * zz - offset)
  70. + 0.005f * std::cos(4.0f * xx - 13.0f * zz + offset)
  71. + 0.003f * std::cos(19.0f * xx - 9.0f * zz - offset)
  72. );
  73. }
  74. }
  75. }
  76. // prepare to draw textures
  77. Common::flush();
  78. glXWaitX();
  79. glPushAttrib(GL_ALL_ATTRIB_BITS);
  80. glDisable(GL_FOG);
  81. glMatrixMode(GL_MODELVIEW);
  82. glPushMatrix();
  83. glLoadIdentity();
  84. glRotatef(-90.0f, 1, 0, 0);
  85. glMatrixMode(GL_PROJECTION);
  86. glPushMatrix();
  87. glReadBuffer(GL_BACK);
  88. glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
  89. glDisable(GL_TEXTURE_2D);
  90. glEnable(GL_BLEND);
  91. std::vector<unsigned char> bitmap(size * size * 3);
  92. // project vertices and create textures
  93. // reciprocal of vertical component of light ray
  94. float recvert = float(CAUSTIC_RESOLUTION) * 0.5f;
  95. for (unsigned int k = 0; k < Hack::frames; ++k) {
  96. // compute projected offsets
  97. // (this uses surface normals, not actual refractions, but it's faster this way)
  98. for (unsigned int i = 0; i < CAUSTIC_RESOLUTION; ++i) {
  99. for (unsigned int j = 0; j < CAUSTIC_RESOLUTION; ++j) {
  100. unsigned int minus, plus;
  101. minus = (i == 0 ? CAUSTIC_RESOLUTION - 1 : i - 1);
  102. plus = (i == CAUSTIC_RESOLUTION - 1 ? 0 : i + 1);
  103. xz(i, j).first = (y[k](plus, j) - y[k](minus, j)) * recvert * (CAUSTIC_DEPTH + y[k](i, j));
  104. minus = (j == 0 ? CAUSTIC_RESOLUTION - 1 : j - 1);
  105. plus = (j == CAUSTIC_RESOLUTION - 1 ? 0 : j + 1);
  106. xz(i, j).second = (y[k](i, plus) - y[k](i, minus)) * recvert * (CAUSTIC_DEPTH + y[k](i, j));
  107. }
  108. }
  109. // copy offsets to edges of xz array
  110. for (unsigned int i = 0; i < CAUSTIC_RESOLUTION; ++i)
  111. xz(i, CAUSTIC_RESOLUTION) = xz(i, 0);
  112. for (unsigned int j = 0; j <= CAUSTIC_RESOLUTION; ++j)
  113. xz(CAUSTIC_RESOLUTION, j) = xz(0, j);
  114. // compute light intensities
  115. float space = 1.0f / float(CAUSTIC_RESOLUTION);
  116. for (unsigned int i = 0; i < CAUSTIC_RESOLUTION; ++i) {
  117. for (unsigned int j = 0; j < CAUSTIC_RESOLUTION; ++j) {
  118. unsigned int xminus = (i == 0 ? CAUSTIC_RESOLUTION - 1 : i - 1);
  119. unsigned int xplus = (i == CAUSTIC_RESOLUTION - 1 ? 0 : i + 1);
  120. unsigned int zminus = (j == 0 ? CAUSTIC_RESOLUTION - 1 : j - 1);
  121. unsigned int zplus = (j == CAUSTIC_RESOLUTION - 1 ? 0 : j + 1);
  122. // this assumes nominal light intensity is 0.25
  123. intensity(i, j) = (1.0f / (float(CAUSTIC_RESOLUTION) * float(CAUSTIC_RESOLUTION)))
  124. / ((std::abs(xz(xplus, j).first - xz(i, j).first + space)
  125. + std::abs(xz(i, j).first - xz(xminus, j).first + space))
  126. * (std::abs(xz(i, zplus).second - xz(i, j).second + space)
  127. + std::abs(xz(i, j).second - xz(i, zminus).second + space)))
  128. - 0.125f;
  129. if (intensity(i, j) > 1.0f)
  130. intensity(i, j) = 1.0f;
  131. }
  132. }
  133. // copy intensities to edges of intensity array
  134. for (unsigned int i = 0; i < CAUSTIC_RESOLUTION; ++i)
  135. intensity(i, CAUSTIC_RESOLUTION) = intensity(i, 0);
  136. for (unsigned int j = 0; j <= CAUSTIC_RESOLUTION; ++j)
  137. intensity(CAUSTIC_RESOLUTION, j) = intensity(0, j);
  138. glMatrixMode(GL_PROJECTION);
  139. glLoadIdentity();
  140. glOrtho(0.0f, 1.0f, 0.0f, 1.0f, -0.5f, 0.5f);
  141. glViewport(
  142. (Common::width - size) >> 1,
  143. (Common::height - size) >> 1,
  144. size, size
  145. );
  146. glBlendFunc(GL_SRC_ALPHA, GL_ONE);
  147. // draw texture
  148. glClear(GL_COLOR_BUFFER_BIT);
  149. // draw most of texture
  150. draw(intensity, x, z, xz, 0, CAUSTIC_RESOLUTION, 0, CAUSTIC_RESOLUTION);
  151. // draw edges of texture that wrap around from opposite sides
  152. glMatrixMode(GL_MODELVIEW);
  153. glPushMatrix();
  154. glTranslatef(-1.0f, 0.0f, 0.0f);
  155. draw(intensity, x, z, xz, CAUSTIC_RESOLUTION * 9 / 10, CAUSTIC_RESOLUTION, 0, CAUSTIC_RESOLUTION);
  156. glPopMatrix();
  157. glPushMatrix();
  158. glTranslatef(1.0f, 0.0f, 0.0f);
  159. draw(intensity, x, z, xz, 0, CAUSTIC_RESOLUTION / 10, 0, CAUSTIC_RESOLUTION);
  160. glPopMatrix();
  161. glPushMatrix();
  162. glTranslatef(0.0f, 0.0f, -1.0f);
  163. draw(intensity, x, z, xz, 0, CAUSTIC_RESOLUTION, CAUSTIC_RESOLUTION * 9 / 10, CAUSTIC_RESOLUTION);
  164. glPopMatrix();
  165. glPushMatrix();
  166. glTranslatef(0.0f, 0.0f, 1.0f);
  167. draw(intensity, x, z, xz, 0, CAUSTIC_RESOLUTION, 0, CAUSTIC_RESOLUTION / 10);
  168. glPopMatrix();
  169. // draw corners too
  170. glPushMatrix();
  171. glTranslatef(-1.0f, 0.0f, -1.0f);
  172. draw(intensity, x, z, xz, CAUSTIC_RESOLUTION * 9 / 10, CAUSTIC_RESOLUTION, CAUSTIC_RESOLUTION * 9 / 10, CAUSTIC_RESOLUTION);
  173. glPopMatrix();
  174. glPushMatrix();
  175. glTranslatef(1.0f, 0.0f, -1.0f);
  176. draw(intensity, x, z, xz, 0, CAUSTIC_RESOLUTION / 10, CAUSTIC_RESOLUTION * 9 / 10, CAUSTIC_RESOLUTION);
  177. glPopMatrix();
  178. glPushMatrix();
  179. glTranslatef(-1.0f, 0.0f, 1.0f);
  180. draw(intensity, x, z, xz, CAUSTIC_RESOLUTION * 9 / 10, CAUSTIC_RESOLUTION, 0, CAUSTIC_RESOLUTION / 10);
  181. glPopMatrix();
  182. glPushMatrix();
  183. glTranslatef(1.0f, 0.0f, 1.0f);
  184. draw(intensity, x, z, xz, 0, CAUSTIC_RESOLUTION / 10, 0, CAUSTIC_RESOLUTION / 10);
  185. glPopMatrix();
  186. // read back texture
  187. glReadPixels(
  188. (Common::width - size) >> 1,
  189. (Common::height - size) >> 1,
  190. size, size,
  191. GL_RGB, GL_UNSIGNED_BYTE, &bitmap.front()
  192. );
  193. glMatrixMode(GL_PROJECTION);
  194. glLoadIdentity();
  195. glOrtho(0.0f, Common::width, 0.0f, Common::height, -0.5f, 0.5f);
  196. glViewport(0, 0, Common::width, Common::height);
  197. unsigned int left = ((Common::width - size) >> 1) - 5;
  198. unsigned int right = left + size + 10;
  199. unsigned int bottom = ((Common::height - size) >> 1) - 5;
  200. unsigned int top = bottom + size + 10;
  201. unsigned int barBottom = bottom - 10;
  202. unsigned int barTop = barBottom - 20;
  203. glBlendFunc(GL_ONE, GL_ZERO);
  204. glLineWidth(2.0f);
  205. glBegin(GL_LINE_STRIP);
  206. glColor3f(0.0f, 0.4f, 0.0f);
  207. glVertex3f(left, 0.0f, bottom);
  208. glVertex3f(right, 0.0f, bottom);
  209. glVertex3f(right, 0.0f, top);
  210. glVertex3f(left, 0.0f, top);
  211. glVertex3f(left, 0.0f, bottom);
  212. glEnd();
  213. glBegin(GL_QUADS);
  214. glColor3f(0.0f, 0.2f, 0.0f);
  215. glVertex3f(left, 0.0f, barBottom);
  216. glVertex3f(left + (k + 1) * float(right - left) / float(Hack::frames), 0.0f, barBottom);
  217. glVertex3f(left + (k + 1) * float(right - left) / float(Hack::frames), 0.0f, barTop);
  218. glVertex3f(left, 0.0f, barTop);
  219. glEnd();
  220. glBegin(GL_LINE_STRIP);
  221. glColor3f(0.0f, 0.4f, 0.0f);
  222. glVertex3f(left, 0.0f, barBottom);
  223. glVertex3f(right, 0.0f, barBottom);
  224. glVertex3f(right, 0.0f, barTop);
  225. glVertex3f(left, 0.0f, barTop);
  226. glVertex3f(left, 0.0f, barBottom);
  227. glEnd();
  228. Common::flush();
  229. // create texture object
  230. _textures.push_back(Common::resources->genTexture(
  231. GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR, GL_REPEAT, GL_REPEAT,
  232. 3, size, size, GL_RGB, GL_UNSIGNED_BYTE, &bitmap.front()
  233. ));
  234. }
  235. glMatrixMode(GL_PROJECTION);
  236. glPopMatrix();
  237. glMatrixMode(GL_MODELVIEW);
  238. glPopMatrix();
  239. glPopAttrib();
  240. }
  241. void CausticTextures::draw(
  242. const stdx::dim2<float, CAUSTIC_RESOLUTION + 1>& intensity,
  243. const float* x, const float* z,
  244. const stdx::dim2<std::pair<float, float>, CAUSTIC_RESOLUTION + 1>& xz,
  245. unsigned int xLo, unsigned int xHi, unsigned int zLo, unsigned int zHi
  246. ) {
  247. for (unsigned int j = zLo; j < zHi; ++j) {
  248. // red
  249. float mult = 1.0f - CAUSTIC_REFRACTION / float(CAUSTIC_RESOLUTION);
  250. glBegin(GL_TRIANGLE_STRIP);
  251. for (unsigned int i = xLo; i <= xHi; ++i) {
  252. glColor3f(intensity(i, j + 1), 0.0f, 0.0f);
  253. glVertex3f(x[i] + xz(i, j + 1).first * mult, 0.0f, z[j + 1] + xz(i, j + 1).second * mult);
  254. glColor3f(intensity(i, j), 0.0f, 0.0f);
  255. glVertex3f(x[i] + xz(i, j).first * mult, 0.0f, z[j] + xz(i, j).second * mult);
  256. }
  257. glEnd();
  258. // green
  259. glBegin(GL_TRIANGLE_STRIP);
  260. for(unsigned int i = xLo; i <= xHi; ++i) {
  261. glColor3f(0.0f, intensity(i, j + 1), 0.0f);
  262. glVertex3f(x[i] + xz(i, j + 1).first, 0.0f, z[j + 1] + xz(i, j + 1).second);
  263. glColor3f(0.0f, intensity(i, j), 0.0f);
  264. glVertex3f(x[i] + xz(i, j).first, 0.0f, z[j] + xz(i, j).second);
  265. }
  266. glEnd();
  267. // blue
  268. mult = 1.0f + CAUSTIC_REFRACTION / float(CAUSTIC_RESOLUTION);
  269. glBegin(GL_TRIANGLE_STRIP);
  270. for(unsigned int i = xLo; i <= xHi; ++i) {
  271. glColor3f(0.0f, 0.0f, intensity(i, j + 1));
  272. glVertex3f(x[i] + xz(i, j + 1).first * mult, 0.0f, z[j + 1] + xz(i, j + 1).second * mult);
  273. glColor3f(0.0f, 0.0f, intensity(i, j));
  274. glVertex3f(x[i] + xz(i, j).first * mult, 0.0f, z[j] + xz(i, j).second * mult);
  275. }
  276. glEnd();
  277. }
  278. }