/xbmc/screensavers/rsxs-0.9/src/euphoria/euphoria.cc

http://github.com/xbmc/xbmc · C++ · 475 lines · 381 code · 58 blank · 36 comment · 19 complexity · 1ddb63e4a7bca23c695e3b4fd4aaa66c 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 <euphoria.hh>
  25. #include <hack.hh>
  26. #include <pngimage.hh>
  27. #include <wisp.hh>
  28. namespace Hack {
  29. unsigned int numWisps = 5;
  30. unsigned int numBackWisps = 0;
  31. unsigned int density = 25;
  32. float visibility = 35.0f;
  33. float speed = 15.0f;
  34. float feedback = 0.0f;
  35. float feedbackSpeed = 1.0f;
  36. unsigned int feedbackSize = 8;
  37. std::string texture;
  38. bool wireframe = false;
  39. };
  40. namespace Hack {
  41. enum Arguments {
  42. ARG_WISPS = 1,
  43. ARG_BACKWISPS,
  44. ARG_DENSITY,
  45. ARG_VISIBILITY,
  46. ARG_SPEED,
  47. ARG_FEEDBACK,
  48. ARG_FEEDBACKSPEED,
  49. ARG_FEEDBACKSIZE,
  50. ARG_TEXTURE,
  51. ARG_WIREFRAME = 0x100, ARG_NO_WIREFRAME,
  52. ARG_NO_TEXTURE = 0x200, ARG_PLASMA_TEXTURE, ARG_STRINGY_TEXTURE,
  53. ARG_LINES_TEXTURE, ARG_RANDOM_TEXTURE
  54. };
  55. float _fr[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
  56. float _fv[4];
  57. float _f[4];
  58. float _lr[3] = { 0.0f, 0.0f, 0.0f };
  59. float _lv[3];
  60. float _l[3];
  61. GLuint _tex;
  62. GLuint _feedbackTex;
  63. unsigned int _feedbackTexSize;
  64. stdx::dim3<GLubyte, 3> _feedbackMap;
  65. std::vector<Wisp> _backWisps;
  66. std::vector<Wisp> _wisps;
  67. error_t parse(int, char*, struct argp_state*);
  68. };
  69. error_t Hack::parse(int key, char* arg, struct argp_state* state) {
  70. retry:
  71. switch (key) {
  72. case ARG_WISPS:
  73. if (Common::parseArg(arg, numWisps, 0u, 100u))
  74. argp_failure(state, EXIT_FAILURE, 0,
  75. "number of wisps must be between 0 and 100");
  76. return 0;
  77. case ARG_BACKWISPS:
  78. if (Common::parseArg(arg, numBackWisps, 0u, 100u))
  79. argp_failure(state, EXIT_FAILURE, 0,
  80. "number of background layers must be between 0 and 100");
  81. return 0;
  82. case ARG_DENSITY:
  83. if (Common::parseArg(arg, density, 2u, 100u))
  84. argp_failure(state, EXIT_FAILURE, 0,
  85. "mesh density must be between 2 and 100");
  86. return 0;
  87. case ARG_VISIBILITY:
  88. if (Common::parseArg(arg, visibility, 1.0f, 100.0f))
  89. argp_failure(state, EXIT_FAILURE, 0,
  90. "mesh visibility must be between 1 and 100");
  91. return 0;
  92. case ARG_SPEED:
  93. if (Common::parseArg(arg, speed, 1.0f, 100.0f))
  94. argp_failure(state, EXIT_FAILURE, 0,
  95. "motion speed must be between 1 and 100");
  96. return 0;
  97. case ARG_FEEDBACK:
  98. if (Common::parseArg(arg, feedback, 0.0f, 100.0f))
  99. argp_failure(state, EXIT_FAILURE, 0,
  100. "feedback intensity must be between 0 and 100");
  101. return 0;
  102. case ARG_FEEDBACKSPEED:
  103. if (Common::parseArg(arg, feedbackSpeed, 1.0f, 100.0f))
  104. argp_failure(state, EXIT_FAILURE, 0,
  105. "feedback speed must be between 1 and 100");
  106. return 0;
  107. case ARG_FEEDBACKSIZE:
  108. if (Common::parseArg(arg, feedbackSize, 1u, 10u))
  109. argp_failure(state, EXIT_FAILURE, 0,
  110. "feedback speed must be between 1 and 10");
  111. return 0;
  112. case ARG_WIREFRAME:
  113. wireframe = true;
  114. return 0;
  115. case ARG_NO_WIREFRAME:
  116. wireframe = false;
  117. return 0;
  118. case ARG_TEXTURE:
  119. texture = arg;
  120. return 0;
  121. case ARG_NO_TEXTURE:
  122. texture = "";
  123. return 0;
  124. case ARG_PLASMA_TEXTURE:
  125. texture = "plasma.png";
  126. return 0;
  127. case ARG_STRINGY_TEXTURE:
  128. texture = "stringy.png";
  129. return 0;
  130. case ARG_LINES_TEXTURE:
  131. texture = "lines.png";
  132. return 0;
  133. case ARG_RANDOM_TEXTURE:
  134. key = Common::randomInt(3) + ARG_PLASMA_TEXTURE;
  135. goto retry;
  136. default:
  137. return ARGP_ERR_UNKNOWN;
  138. }
  139. }
  140. const struct argp* Hack::getParser() {
  141. static struct argp_option options[] = {
  142. { NULL, 0, NULL, 0, "Global options:" },
  143. { "wisps", ARG_WISPS, "NUM", 0, "Number of wisps (0-100, default = 5)" },
  144. { "background", ARG_BACKWISPS, "NUM", 0,
  145. "Number of background layers (0-100, default = 0)" },
  146. { NULL, 0, NULL, 0, "Wisp mesh options:" },
  147. { "density", ARG_DENSITY, "NUM", 0,
  148. "Mesh density (2-100, default = 25)" },
  149. { "speed", ARG_SPEED, "NUM", 0,
  150. "Motion speed (1-100, default = 15)" },
  151. { "visibility", ARG_VISIBILITY, "NUM", 0,
  152. "Mesh visibility (1-100, default = 35)" },
  153. { "wireframe", ARG_WIREFRAME, NULL, 0,
  154. "Enable wireframe mesh" },
  155. { "no-wireframe", ARG_NO_WIREFRAME, NULL, OPTION_ALIAS | OPTION_HIDDEN },
  156. { "texture", ARG_TEXTURE, "FILE", 0,
  157. "Wisp texture (default = no texture)" },
  158. { NULL, 0, NULL, 0, "Predefined textures:" },
  159. { "plain", ARG_NO_TEXTURE, NULL, 0 },
  160. { "plasma", ARG_PLASMA_TEXTURE, NULL, 0 },
  161. { "stringy", ARG_STRINGY_TEXTURE, NULL, 0 },
  162. { "lines", ARG_LINES_TEXTURE, NULL, 0 },
  163. { "random", ARG_RANDOM_TEXTURE, NULL, 0 },
  164. { NULL, 0, NULL, 0, "Feedback options:" },
  165. { "feedback", ARG_FEEDBACK, "NUM", 0,
  166. "Feedback intensity (0-100, default = 0)" },
  167. { "feedbackspeed", ARG_FEEDBACKSPEED, "NUM", 0,
  168. "Feedback speed (1-100, default = 1)" },
  169. { "feedbacksize", ARG_FEEDBACKSIZE, "NUM", 0,
  170. "Feedback size (1-10, default = 3)" },
  171. {}
  172. };
  173. static struct argp parser = {
  174. options, parse, NULL,
  175. "Draws patterned wisps, with optional psychadelic feedback."
  176. };
  177. return &parser;
  178. }
  179. std::string Hack::getShortName() { return "euphoria"; }
  180. std::string Hack::getName() { return "Euphoria"; }
  181. void Hack::start() {
  182. glViewport(0, 0, Common::width, Common::height);
  183. _tex = 0;
  184. if (texture.length()) {
  185. glEnable(GL_TEXTURE_2D);
  186. glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
  187. _tex = Common::resources->genTexture(
  188. GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR, GL_REPEAT, GL_REPEAT,
  189. PNG(texture)
  190. );
  191. }
  192. if (feedback > 0.0f) {
  193. _feedbackTexSize = 1 << feedbackSize;
  194. while (
  195. (_feedbackTexSize > Common::width) ||
  196. (_feedbackTexSize > Common::height)
  197. )
  198. _feedbackTexSize >>= 1;
  199. // feedback texture setup
  200. glEnable(GL_TEXTURE_2D);
  201. _feedbackMap.resize(_feedbackTexSize, _feedbackTexSize);
  202. _feedbackTex = Common::resources->genTexture(
  203. GL_LINEAR, GL_LINEAR, GL_CLAMP, GL_CLAMP,
  204. 3, _feedbackTexSize, _feedbackTexSize,
  205. GL_RGB, GL_UNSIGNED_BYTE, &_feedbackMap.front(), false
  206. );
  207. // feedback velocity variable setup
  208. _fv[0] = feedbackSpeed * (Common::randomFloat(0.025f) + 0.025f);
  209. _fv[1] = feedbackSpeed * (Common::randomFloat(0.05f) + 0.05f);
  210. _fv[2] = feedbackSpeed * (Common::randomFloat(0.05f) + 0.05f);
  211. _fv[3] = feedbackSpeed * (Common::randomFloat(0.1f) + 0.1f);
  212. _lv[0] = feedbackSpeed * (Common::randomFloat(0.0025f) + 0.0025f);
  213. _lv[1] = feedbackSpeed * (Common::randomFloat(0.0025f) + 0.0025f);
  214. _lv[2] = feedbackSpeed * (Common::randomFloat(0.0025f) + 0.0025f);
  215. }
  216. // Initialize wisps
  217. stdx::construct_n(_wisps, numWisps);
  218. stdx::construct_n(_backWisps, numBackWisps);
  219. }
  220. void Hack::tick() {
  221. Common::run();
  222. // setup regular drawing area just in case feedback isn't used
  223. glMatrixMode(GL_PROJECTION);
  224. glPushMatrix();
  225. glLoadIdentity();
  226. gluPerspective(20.0, Common::aspectRatio, 0.01, 20);
  227. glMatrixMode(GL_MODELVIEW);
  228. glPushMatrix();
  229. glLoadIdentity();
  230. glTranslatef(0.0, 0.0, -5.0);
  231. glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
  232. glClear(GL_COLOR_BUFFER_BIT);
  233. glEnable(GL_BLEND);
  234. glBlendFunc(GL_ONE, GL_ONE);
  235. glLineWidth(2.0f);
  236. glEnable(GL_LINE_SMOOTH);
  237. glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
  238. // Update wisps
  239. stdx::call_all(_wisps, &Wisp::update);
  240. stdx::call_all(_backWisps, &Wisp::update);
  241. if (feedback > 0.0f) {
  242. static float feedbackIntensity = feedback / 101.0f;
  243. // update feedback variables
  244. for (unsigned int i = 0; i < 4; ++i) {
  245. _fr[i] += Common::elapsedSecs * _fv[i];
  246. if (_fr[i] > M_PI * 2.0f)
  247. _fr[i] -= M_PI * 2.0f;
  248. }
  249. _f[0] = 30.0f * std::cos(_fr[0]);
  250. _f[1] = 0.2f * std::cos(_fr[1]);
  251. _f[2] = 0.2f * std::cos(_fr[2]);
  252. _f[3] = 0.8f * std::cos(_fr[3]);
  253. for (unsigned int i = 0; i < 3; ++i) {
  254. _lr[i] += Common::elapsedSecs * _lv[i];
  255. if (_lr[i] > M_PI * 2.0f)
  256. _lr[i] -= M_PI * 2.0f;
  257. _l[i] = std::cos(_lr[i]);
  258. _l[i] = _l[i] * _l[i];
  259. }
  260. // Create drawing area for feedback texture
  261. glViewport(0, 0, _feedbackTexSize, _feedbackTexSize);
  262. glMatrixMode(GL_PROJECTION);
  263. glLoadIdentity();
  264. gluPerspective(30.0, Common::aspectRatio, 0.01f, 20.0f);
  265. glMatrixMode(GL_MODELVIEW);
  266. // Draw
  267. glClear(GL_COLOR_BUFFER_BIT);
  268. glColor3f(feedbackIntensity, feedbackIntensity, feedbackIntensity);
  269. glBindTexture(GL_TEXTURE_2D, _feedbackTex);
  270. glPushMatrix();
  271. glTranslatef(_f[1] * _l[1], _f[2] * _l[1], _f[3] * _l[2]);
  272. glRotatef(_f[0] * _l[0], 0, 0, 1);
  273. glBegin(GL_TRIANGLE_STRIP);
  274. glTexCoord2f(-0.5f, -0.5f);
  275. glVertex3f(-Common::aspectRatio * 2.0f, -2.0f, 1.25f);
  276. glTexCoord2f(1.5f, -0.5f);
  277. glVertex3f(Common::aspectRatio * 2.0f, -2.0f, 1.25f);
  278. glTexCoord2f(-0.5f, 1.5f);
  279. glVertex3f(-Common::aspectRatio * 2.0f, 2.0f, 1.25f);
  280. glTexCoord2f(1.5f, 1.5f);
  281. glVertex3f(Common::aspectRatio * 2.0f, 2.0f, 1.25f);
  282. glEnd();
  283. glPopMatrix();
  284. glBindTexture(GL_TEXTURE_2D, _tex);
  285. stdx::call_all(_backWisps, &Wisp::drawAsBackground);
  286. stdx::call_all(_wisps, &Wisp::draw);
  287. // readback feedback texture
  288. glReadBuffer(GL_BACK);
  289. glPixelStorei(GL_UNPACK_ROW_LENGTH, _feedbackTexSize);
  290. glBindTexture(GL_TEXTURE_2D, _feedbackTex);
  291. glReadPixels(0, 0, _feedbackTexSize, _feedbackTexSize, GL_RGB,
  292. GL_UNSIGNED_BYTE, &_feedbackMap.front());
  293. glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, _feedbackTexSize, _feedbackTexSize,
  294. GL_RGB, GL_UNSIGNED_BYTE, &_feedbackMap.front());
  295. // create regular drawing area
  296. glViewport(0, 0, Common::width, Common::height);
  297. glMatrixMode(GL_PROJECTION);
  298. glLoadIdentity();
  299. gluPerspective(20.0, Common::aspectRatio, 0.01f, 20.0f);
  300. glMatrixMode(GL_MODELVIEW);
  301. // Draw again
  302. glClear(GL_COLOR_BUFFER_BIT);
  303. glColor3f(feedbackIntensity, feedbackIntensity, feedbackIntensity);
  304. glPushMatrix();
  305. glTranslatef(_f[1] * _l[1], _f[2] * _l[1], _f[3] * _l[2]);
  306. glRotatef(_f[0] * _l[0], 0, 0, 1);
  307. glBegin(GL_TRIANGLE_STRIP);
  308. glTexCoord2f(-0.5f, -0.5f);
  309. glVertex3f(-Common::aspectRatio * 2.0f, -2.0f, 1.25f);
  310. glTexCoord2f(1.5f, -0.5f);
  311. glVertex3f(Common::aspectRatio * 2.0f, -2.0f, 1.25f);
  312. glTexCoord2f(-0.5f, 1.5f);
  313. glVertex3f(-Common::aspectRatio * 2.0f, 2.0f, 1.25f);
  314. glTexCoord2f(1.5f, 1.5f);
  315. glVertex3f(Common::aspectRatio * 2.0f, 2.0f, 1.25f);
  316. glEnd();
  317. glPopMatrix();
  318. glBindTexture(GL_TEXTURE_2D, _tex);
  319. } else
  320. glClear(GL_COLOR_BUFFER_BIT);
  321. stdx::call_all(_backWisps, &Wisp::drawAsBackground);
  322. stdx::call_all(_wisps, &Wisp::draw);
  323. glMatrixMode(GL_MODELVIEW);
  324. glPopMatrix();
  325. glMatrixMode(GL_PROJECTION);
  326. glPopMatrix();
  327. //Common::flush();
  328. // Clear the error flag
  329. glGetError();
  330. }
  331. void Hack::reshape() {
  332. glViewport(0, 0, Common::width, Common::height);
  333. // setup regular drawing area just in case feedback isn't used
  334. glMatrixMode(GL_PROJECTION);
  335. glLoadIdentity();
  336. gluPerspective(20.0, Common::aspectRatio, 0.01, 20);
  337. glMatrixMode(GL_MODELVIEW);
  338. glLoadIdentity();
  339. glTranslatef(0.0, 0.0, -5.0);
  340. }
  341. void Hack::stop() {
  342. _wisps.clear();
  343. _backWisps.clear();
  344. _feedbackMap.clear();
  345. }
  346. void Hack::keyPress(char c, const KeySym&) {
  347. switch (c) {
  348. case 3: case 27:
  349. case 'q': case 'Q':
  350. Common::running = false;
  351. break;
  352. }
  353. }
  354. void Hack::keyRelease(char, const KeySym&) {}
  355. void Hack::pointerMotion(int, int) {}
  356. void Hack::buttonPress(unsigned int) {}
  357. void Hack::buttonRelease(unsigned int) {}
  358. void Hack::pointerEnter() {}
  359. void Hack::pointerLeave() {}
  360. #define _LINUX
  361. #include "../../../addons/include/xbmc_scr_dll.h"
  362. extern "C" {
  363. ADDON_STATUS ADDON_Create(void* hdl, void* props)
  364. {
  365. if (!props)
  366. return ADDON_STATUS_UNKNOWN;
  367. SCR_PROPS* scrprops = (SCR_PROPS*)props;
  368. Common::width = scrprops->width;
  369. Common::height = scrprops->height;
  370. Common::aspectRatio = float(Common::width) / float(Common::height);
  371. Common::init(0, NULL);
  372. return ADDON_STATUS_OK;
  373. }
  374. void Start()
  375. {
  376. Hack::start();
  377. }
  378. void Render()
  379. {
  380. Hack::tick();
  381. }
  382. void ADDON_Stop()
  383. {
  384. Hack::stop();
  385. }
  386. void ADDON_Destroy()
  387. {
  388. }
  389. ADDON_STATUS ADDON_GetStatus()
  390. {
  391. return ADDON_STATUS_OK;
  392. }
  393. bool ADDON_HasSettings()
  394. {
  395. return false;
  396. }
  397. unsigned int ADDON_GetSettings(ADDON_StructSetting ***sSet)
  398. {
  399. return 0;
  400. }
  401. ADDON_STATUS ADDON_SetSetting(const char *settingName, const void *settingValue)
  402. {
  403. return ADDON_STATUS_OK;
  404. }
  405. void ADDON_FreeSettings()
  406. {
  407. }
  408. void ADDON_Announce(const char *flag, const char *sender, const char *message, const void *data)
  409. {
  410. }
  411. void GetInfo(SCR_INFO *info)
  412. {
  413. }
  414. void Remove()
  415. {
  416. }
  417. }