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

http://github.com/xbmc/xbmc · C++ · 448 lines · 352 code · 62 blank · 34 comment · 23 complexity · c3fdbd448c75eff0224b05b9ee15899a 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 <extensions.hh>
  25. #include <flares.hh>
  26. #include <goo.hh>
  27. #include <hack.hh>
  28. #include <nebula.hh>
  29. #include <particle.hh>
  30. #include <spline.hh>
  31. #include <starburst.hh>
  32. #include <tunnel.hh>
  33. namespace Hack {
  34. unsigned int numStars = 1000;
  35. float starSize = 10.0f;
  36. unsigned int depth = 5;
  37. float fov = 50.0f;
  38. float speed = 10.0f;
  39. unsigned int resolution = 10;
  40. bool shaders = true;
  41. };
  42. namespace Hack {
  43. unsigned int frames;
  44. unsigned int current;
  45. float fogDepth;
  46. Vector camera, dir;
  47. float unroll;
  48. float lerp;
  49. int viewport[4];
  50. double projMat[16];
  51. double modelMat[16];
  52. };
  53. namespace Hack {
  54. enum Arguments {
  55. ARG_STARS = 1,
  56. ARG_SIZE,
  57. ARG_DEPTH,
  58. ARG_FOV,
  59. ARG_SPEED,
  60. ARG_RESOLUTION,
  61. ARG_SHADERS = 0x100, ARG_NO_SHADERS
  62. };
  63. std::vector<StretchedParticle> _stars;
  64. StretchedParticle* _sun;
  65. float gooFunction(const Vector&);
  66. float nextFrame();
  67. error_t parse(int, char*, struct argp_state*);
  68. };
  69. error_t Hack::parse(int key, char* arg, struct argp_state* state) {
  70. switch (key) {
  71. case ARG_STARS:
  72. if (Common::parseArg(arg, numStars, 0u, 10000u))
  73. argp_failure(state, EXIT_FAILURE, 0,
  74. "stars must be between 0 and 10000");
  75. return 0;
  76. case ARG_SIZE:
  77. if (Common::parseArg(arg, starSize, 1.0f, 100.0f))
  78. argp_failure(state, EXIT_FAILURE, 0,
  79. "star size must be between 1 and 100");
  80. return 0;
  81. case ARG_DEPTH:
  82. if (Common::parseArg(arg, depth, 1u, 10u))
  83. argp_failure(state, EXIT_FAILURE, 0,
  84. "depth must be between 1 and 10");
  85. return 0;
  86. case ARG_FOV:
  87. if (Common::parseArg(arg, fov, 10.0f, 150.0f))
  88. argp_failure(state, EXIT_FAILURE, 0,
  89. "field of view must be between 10 and 150");
  90. return 0;
  91. case ARG_SPEED:
  92. if (Common::parseArg(arg, speed, 1.0f, 100.0f))
  93. argp_failure(state, EXIT_FAILURE, 0,
  94. "speed must be between 1 and 100");
  95. return 0;
  96. case ARG_RESOLUTION:
  97. if (Common::parseArg(arg, resolution, 4u, 20u))
  98. argp_failure(state, EXIT_FAILURE, 0,
  99. "resolution must be between 4 and 20");
  100. return 0;
  101. case ARG_SHADERS:
  102. shaders = true;
  103. return 0;
  104. case ARG_NO_SHADERS:
  105. shaders = false;
  106. return 0;
  107. default:
  108. return ARGP_ERR_UNKNOWN;
  109. }
  110. }
  111. const struct argp* Hack::getParser() {
  112. static struct argp_option options[] = {
  113. { NULL, 0, NULL, 0, "Hyperspace options:" },
  114. { "stars", ARG_STARS, "NUM", 0,
  115. "Number of stars (0-10000, default = 1000)" },
  116. { "size", ARG_SIZE, "NUM", 0,
  117. "Star size (1-100, default = 10)" },
  118. { "depth", ARG_DEPTH, "NUM", 0, "Depth (1-10, default = 5)" },
  119. { "fov", ARG_FOV, "NUM", 0, "Field of view (10-150, default = 90)" },
  120. { "speed", ARG_SPEED, "NUM", 0, "Speed (1-100, default = 10)" },
  121. { "resolution", ARG_RESOLUTION, "NUM", 0,
  122. "Resolution (4-20, default = 10)" },
  123. { "shaders", ARG_SHADERS, NULL, OPTION_HIDDEN,
  124. "Disable shaders" },
  125. { "no-shaders", ARG_NO_SHADERS, NULL, OPTION_ALIAS },
  126. {}
  127. };
  128. static struct argp parser =
  129. { options, parse, NULL, "Soar through wormholes in liquid spacetime." };
  130. return &parser;
  131. }
  132. std::string Hack::getShortName() { return "hyperspace"; }
  133. std::string Hack::getName() { return "Hyperspace"; }
  134. float Hack::nextFrame() {
  135. static float time = 0.0f;
  136. time += Common::elapsedTime;
  137. // loop frames every 2 seconds
  138. static float frameTime = 2.0f / float(frames);
  139. while (time > frameTime) {
  140. time -= frameTime;
  141. current++;
  142. if (current == frames) current = 0;
  143. }
  144. return time / frameTime;
  145. }
  146. void Hack::start() {
  147. glViewport(0, 0, Common::width, Common::height);
  148. viewport[0] = 0;
  149. viewport[1] = 0;
  150. viewport[2] = Common::width;
  151. viewport[3] = Common::height;
  152. glMatrixMode(GL_PROJECTION);
  153. glLoadIdentity();
  154. gluPerspective(fov, Common::aspectRatio, 0.001f, 200.0f);
  155. glGetDoublev(GL_PROJECTION_MATRIX, projMat);
  156. glMatrixMode(GL_MODELVIEW);
  157. try {
  158. Shaders::init();
  159. shaders = true;
  160. } catch (...) {
  161. shaders = false;
  162. }
  163. Hack::frames = shaders ? 20 : 60;
  164. glDisable(GL_DEPTH_TEST);
  165. glEnable(GL_BLEND);
  166. glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
  167. glEnable(GL_TEXTURE_2D);
  168. glDisable(GL_LIGHTING);
  169. Flares::init();
  170. Spline::init(depth * 2 + 6);
  171. Tunnel::init();
  172. fogDepth = depth * 2.0f - 2.0f / float(resolution);
  173. Goo::init();
  174. _stars.reserve(numStars);
  175. for (unsigned int i = 0; i < numStars; ++i) {
  176. RGBColor color(
  177. 0.5f + Common::randomFloat(0.5f),
  178. 0.5f + Common::randomFloat(0.5f),
  179. 0.5f + Common::randomFloat(0.5f)
  180. );
  181. switch (Common::randomInt(3)) {
  182. case 0: color.r() = 1.0f; break;
  183. case 1: color.g() = 1.0f; break;
  184. case 2: color.b() = 1.0f; break;
  185. }
  186. _stars.push_back(StretchedParticle(
  187. Vector(
  188. Common::randomFloat(2.0f * fogDepth) - fogDepth,
  189. Common::randomFloat(4.0f) - 2.0f,
  190. Common::randomFloat(2.0f * fogDepth) - fogDepth
  191. ),
  192. Common::randomFloat(starSize * 0.001f) + starSize * 0.001f,
  193. color, fov
  194. ));
  195. }
  196. _sun = new StretchedParticle(
  197. Vector(0.0f, 2.0f, 0.0f), starSize * 0.004f,
  198. RGBColor(1.0f, 1.0f, 1.0f), fov
  199. );
  200. Common::resources->manage(_sun);
  201. StarBurst::init();
  202. Nebula::init();
  203. current = 0;
  204. glEnable(GL_FOG);
  205. float fog_color[4] = { 0.0f, 0.0f, 0.0f, 1.0f };
  206. glFogfv(GL_FOG_COLOR, fog_color);
  207. glFogf(GL_FOG_MODE, GL_LINEAR);
  208. glFogf(GL_FOG_START, fogDepth * 0.7f);
  209. glFogf(GL_FOG_END, fogDepth);
  210. }
  211. void Hack::tick() {
  212. glMatrixMode(GL_MODELVIEW);
  213. // Camera movements
  214. static float heading[3] = { 0.0f, 0.0f, 0.0f }; // current, target, and last
  215. static bool headingChange = true;
  216. static float headingChangeTime[2] = { 20.0f, 0.0f }; // total, elapsed
  217. static float roll[3] = { 0.0f, 0.0f, 0.0f }; // current, target, and last
  218. static bool rollChange = true;
  219. static float rollChangeTime[2] = { 1.0f, 0.0f }; // total, elapsed
  220. headingChangeTime[1] += Common::elapsedTime;
  221. if( headingChangeTime[1] >= headingChangeTime[0]) { // Choose new direction
  222. headingChangeTime[0] = Common::randomFloat(15.0f) + 5.0f;
  223. headingChangeTime[1] = 0.0f;
  224. heading[2] = heading[1]; // last = target
  225. if (headingChange) {
  226. // face forward most of the time
  227. if (Common::randomInt(6))
  228. heading[1] = 0.0f;
  229. // face backward the rest of the time
  230. else if (Common::randomInt(2))
  231. heading[1] = M_PI;
  232. else
  233. heading[1] = -M_PI;
  234. headingChange = false;
  235. } else
  236. headingChange = true;
  237. }
  238. float t = headingChangeTime[1] / headingChangeTime[0];
  239. t = 0.5f * (1.0f - std::cos(M_PI * t));
  240. heading[0] = heading[1] * t + heading[2] * (1.0f - t);
  241. rollChangeTime[1] += Common::elapsedTime;
  242. if (rollChangeTime[1] >= rollChangeTime[0]) { // Choose new roll angle
  243. rollChangeTime[0] = Common::randomFloat(5.0f) + 10.0f;
  244. rollChangeTime[1] = 0.0f;
  245. roll[2] = roll[1]; // last = target
  246. if (rollChange) {
  247. roll[1] = Common::randomFloat(M_PI * 4.0f) - M_PI * 2.0f;
  248. rollChange = false;
  249. } else
  250. rollChange = true;
  251. }
  252. t = rollChangeTime[1] / rollChangeTime[0];
  253. t = 0.5f * (1.0f - std::cos(M_PI * t));
  254. roll[0] = roll[1] * t + roll[2] * (1.0f - t);
  255. Spline::moveAlongPath(speed * Common::elapsedTime * 0.03f);
  256. Spline::update(Common::elapsedTime);
  257. camera = Spline::at(depth + 2, Spline::step);
  258. dir = Spline::direction(depth + 2, Spline::step);
  259. float pathAngle = std::atan2(-dir.x(), -dir.z());
  260. glLoadIdentity();
  261. glRotatef(-roll[0] * R2D, 0, 0, 1);
  262. glRotatef((-pathAngle - heading[0]) * R2D, 0, 1, 0);
  263. glTranslatef(-camera.x(), -camera.y(), -camera.z());
  264. glGetDoublev(GL_MODELVIEW_MATRIX, modelMat);
  265. unroll = roll[0] * R2D;
  266. // calculate diagonal fov
  267. float diagFov = 0.5f * fov * D2R;
  268. diagFov = std::tan(diagFov);
  269. diagFov = std::sqrt(diagFov * diagFov + (diagFov * Common::aspectRatio * diagFov * Common::aspectRatio));
  270. diagFov = 2.0f * std::atan(diagFov);
  271. // clear
  272. glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
  273. glClear(GL_COLOR_BUFFER_BIT);
  274. // pick animated texture frame
  275. lerp = Hack::nextFrame();
  276. // draw stars
  277. glEnable(GL_TEXTURE_2D);
  278. glBindTexture(GL_TEXTURE_2D, Flares::blob);
  279. for (
  280. std::vector<StretchedParticle>::iterator i = _stars.begin();
  281. i < _stars.end();
  282. ++i
  283. ) {
  284. i->update();
  285. i->draw();
  286. }
  287. // draw goo
  288. Goo::update(pathAngle + heading[0], diagFov);
  289. Goo::draw();
  290. // update starburst
  291. StarBurst::update();
  292. StarBurst::draw();
  293. // draw tunnel
  294. Tunnel::draw();
  295. // draw sun with lens flare
  296. glDisable(GL_FOG);
  297. static Vector flarePos(0.0f, 2.0f, 0.0f);
  298. glBindTexture(GL_TEXTURE_2D, Flares::blob);
  299. _sun->draw();
  300. float alpha = 0.5f - 0.005f * (flarePos - camera).length();
  301. if (alpha > 0.0f)
  302. Flares::draw(flarePos, RGBColor(1.0f, 1.0f, 1.0f), alpha);
  303. glEnable(GL_FOG);
  304. Common::flush();
  305. }
  306. void Hack::reshape() {
  307. glViewport(0, 0, Common::width, Common::height);
  308. viewport[0] = 0;
  309. viewport[1] = 0;
  310. viewport[2] = Common::width;
  311. viewport[3] = Common::height;
  312. glMatrixMode(GL_PROJECTION);
  313. glLoadIdentity();
  314. gluPerspective(fov, Common::aspectRatio, 0.001f, 200.0f);
  315. glGetDoublev(GL_PROJECTION_MATRIX, projMat);
  316. glMatrixMode(GL_MODELVIEW);
  317. }
  318. void Hack::stop() {}
  319. void Hack::keyPress(char c, const KeySym&) {
  320. switch (c) {
  321. case 3: case 27:
  322. case 'q': case 'Q':
  323. Common::running = false;
  324. break;
  325. }
  326. }
  327. void Hack::keyRelease(char, const KeySym&) {}
  328. void Hack::pointerMotion(int, int) {}
  329. void Hack::buttonPress(unsigned int) {}
  330. void Hack::buttonRelease(unsigned int) {}
  331. void Hack::pointerEnter() {}
  332. void Hack::pointerLeave() {}
  333. #define _LINUX
  334. #include "../../../addons/include/xbmc_scr_dll.h"
  335. extern "C" {
  336. ADDON_STATUS Create(void* hdl, void* props)
  337. {
  338. if (!props)
  339. return STATUS_UNKNOWN;
  340. SCR_PROPS* scrprops = (SCR_PROPS*)props;
  341. Common::width = scrprops->width;
  342. Common::height = scrprops->height;
  343. Common::aspectRatio = float(Common::width) / float(Common::height);
  344. return STATUS_OK;
  345. }
  346. void Start()
  347. {
  348. Hack::start();
  349. }
  350. void Render()
  351. {
  352. Hack::tick();
  353. }
  354. void Stop()
  355. {
  356. Hack::stop();
  357. }
  358. void Destroy()
  359. {
  360. }
  361. ADDON_STATUS GetStatus()
  362. {
  363. return STATUS_OK;
  364. }
  365. bool HasSettings()
  366. {
  367. return false;
  368. }
  369. unsigned int GetSettings(StructSetting ***sSet)
  370. {
  371. return 0;
  372. }
  373. ADDON_STATUS SetSetting(const char *settingName, const void *settingValue)
  374. {
  375. return STATUS_OK;
  376. }
  377. void FreeSettings()
  378. {
  379. }
  380. void GetInfo(SCR_INFO *info)
  381. {
  382. }
  383. void Remove()
  384. {
  385. }
  386. }