PageRenderTime 83ms CodeModel.GetById 10ms app.highlight 68ms RepoModel.GetById 1ms app.codeStats 0ms

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