PageRenderTime 51ms CodeModel.GetById 15ms app.highlight 32ms RepoModel.GetById 1ms app.codeStats 0ms

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