PageRenderTime 67ms CodeModel.GetById 14ms app.highlight 48ms RepoModel.GetById 1ms app.codeStats 0ms

/xbmc/screensavers/rsxs-0.9/src/solarwinds/wind.cc

http://github.com/xbmc/xbmc
C++ | 232 lines | 182 code | 16 blank | 34 comment | 32 complexity | cb1964cb0366c028d5e04183f318dd93 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 <climits>
 26#include <solarwinds.hh>
 27#include <resource.hh>
 28#include <wind.hh>
 29
 30#define LIGHTSIZE 64
 31
 32GLuint Wind::_list;
 33GLuint Wind::_texture;
 34
 35void Wind::init() {
 36	switch (Hack::geometry) {
 37	case Hack::LIGHTS_GEOMETRY:
 38		{
 39			GLubyte light[LIGHTSIZE][LIGHTSIZE];
 40			for (int i = 0; i < LIGHTSIZE; ++i) {
 41				for(int j = 0; j < LIGHTSIZE; ++j) {
 42					float x = float(i - LIGHTSIZE / 2) / float(LIGHTSIZE / 2);
 43					float y = float(j - LIGHTSIZE / 2) / float(LIGHTSIZE / 2);
 44					float temp = Common::clamp(
 45						1.0f - float(std::sqrt((x * x) + (y * y))),
 46						0.0f, 1.0f
 47					);
 48					light[i][j] = GLubyte(255.0f * temp);
 49				}
 50			}
 51			_texture = Common::resources->genTexture(
 52				GL_LINEAR, GL_LINEAR, GL_REPEAT, GL_REPEAT,
 53				1, LIGHTSIZE, LIGHTSIZE, GL_LUMINANCE, GL_UNSIGNED_BYTE, light,
 54				false
 55			);
 56			glEnable(GL_TEXTURE_2D);
 57			glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
 58
 59			float temp = 0.02f * Hack::size;
 60			_list = Common::resources->genLists(1);
 61			glNewList(_list, GL_COMPILE);
 62				glBindTexture(GL_TEXTURE_2D, _texture);
 63				glBegin(GL_TRIANGLE_STRIP);
 64					glTexCoord2f(0.0f, 0.0f);
 65					glVertex3f(-temp, -temp, 0.0f);
 66					glTexCoord2f(1.0f, 0.0f);
 67					glVertex3f(temp, -temp, 0.0f);
 68					glTexCoord2f(0.0f, 1.0f);
 69					glVertex3f(-temp, temp, 0.0f);
 70					glTexCoord2f(1.0f, 1.0f);
 71					glVertex3f(temp, temp, 0.0f);
 72				glEnd();
 73			glEndList();
 74		}
 75		break;
 76	case Hack::POINTS_GEOMETRY:
 77		glEnable(GL_POINT_SMOOTH);
 78		glHint(GL_POINT_SMOOTH_HINT, GL_NICEST);
 79		break;
 80	case Hack::LINES_GEOMETRY:
 81		glEnable(GL_LINE_SMOOTH);
 82		glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
 83		break;
 84	}
 85}
 86
 87Wind::Wind() {
 88	for (unsigned int i = 0; i < Hack::numEmitters; ++i)
 89		_emitters.push_back(Vector(
 90			Common::randomFloat(60.0f) - 30.0f,
 91			Common::randomFloat(60.0f) - 30.0f,
 92			Common::randomFloat(30.0f) - 15.0f
 93		));
 94
 95	_particlesXYZ.resize(Hack::numParticles, Vector(0.0f, 0.0f, 100.0f));
 96	_particlesRGB.resize(Hack::numParticles, RGBColor());
 97
 98	_whichParticle = 0;
 99
100	if (Hack::geometry == Hack::LINES_GEOMETRY) {
101		_lineList.resize(Hack::numParticles, std::make_pair(UINT_MAX, UINT_MAX));
102		for (unsigned int i = 0; i < Hack::numEmitters; ++i)
103			_lastParticle.push_back(i);
104	}
105
106	for (unsigned int i = 0; i < NUMCONSTS; ++i) {
107		_ct[i] = Common::randomFloat(M_PI * 2.0f);
108		_cv[i] = Common::randomFloat(
109			0.00005f * float(Hack::windSpeed) * float(Hack::windSpeed)
110		) + 0.00001f * float(Hack::windSpeed) * float(Hack::windSpeed);
111	}
112}
113
114void Wind::update() {
115	// update constants
116	for (unsigned int i = 0; i < NUMCONSTS; ++i) {
117		_ct[i] += _cv[i];
118		if (_ct[i] > M_PI * 2.0f)
119			_ct[i] -= M_PI * 2.0f;
120		_c[i] = std::cos(_ct[i]);
121	}
122
123	static float eVel = Hack::emitterSpeed * 0.01f;
124
125	// calculate emissions
126	for (unsigned int i = 0; i < Hack::numEmitters; ++i) {
127		// emitter moves toward viewer
128		_emitters[i].z() += eVel;
129		if (_emitters[i].z() > 15.0f)	// reset emitter
130			_emitters[i].set(
131				Common::randomFloat(60.0f) - 30.0f,
132				Common::randomFloat(60.0f) - 30.0f,
133				-15.0f
134			);
135		_particlesXYZ[_whichParticle] = _emitters[i];
136		if (Hack::geometry == Hack::LINES_GEOMETRY) {
137			// link particles to form lines
138			if (_lineList[_whichParticle].first != UINT_MAX)
139				_lineList[_lineList[_whichParticle].first].second = UINT_MAX;
140			_lineList[_whichParticle].first = UINT_MAX;
141			if (_emitters[i].z() == -15.0f)
142				_lineList[_whichParticle].second = UINT_MAX;
143			else
144				_lineList[_whichParticle].second = _lastParticle[i];
145			_lineList[_lastParticle[i]].first = _whichParticle;
146			_lastParticle[i] = _whichParticle;
147		}
148		++_whichParticle;
149		if (_whichParticle >= Hack::numParticles)
150			_whichParticle = 0;
151	}
152
153	// calculate particle positions and colors
154	// first modify constants that affect colors
155	_c[6] *= 9.0f / Hack::particleSpeed;
156	_c[7] *= 9.0f / Hack::particleSpeed;
157	_c[8] *= 9.0f / Hack::particleSpeed;
158	// then update each particle
159	static float pVel = Hack::particleSpeed * 0.01f;
160	for (unsigned int i = 0; i < Hack::numParticles; ++i) {
161		// store old positions
162		float x = _particlesXYZ[i].x();
163		float y = _particlesXYZ[i].y();
164		float z = _particlesXYZ[i].z();
165		// make new positions
166		_particlesXYZ[i].set(
167			x + (_c[0] * y + _c[1] * z) * pVel,
168			y + (_c[2] * z + _c[3] * x) * pVel,
169			z + (_c[4] * x + _c[5] * y) * pVel
170		);
171		// calculate colors
172		_particlesRGB[i].set(
173			std::abs((_particlesXYZ[i].x() - x) * _c[6]),
174			std::abs((_particlesXYZ[i].y() - y) * _c[7]),
175			std::abs((_particlesXYZ[i].z() - z) * _c[8])
176		);
177		// clamp colors
178		_particlesRGB[i].clamp();
179	}
180
181	static float pointSize = 0.04f * Hack::size;
182	static float lineSize = 0.005f * Hack::size;
183
184	// draw particles
185	switch (Hack::geometry) {
186	case Hack::LIGHTS_GEOMETRY:
187		for (unsigned int i = 0; i < Hack::numParticles; ++i) {
188			glColor3fv(_particlesRGB[i].get());
189			glPushMatrix();
190				glTranslatef(
191					_particlesXYZ[i].x(),
192					_particlesXYZ[i].y(),
193					_particlesXYZ[i].z()
194				);
195				glCallList(_list);
196			glPopMatrix();
197		}
198		break;
199	case Hack::POINTS_GEOMETRY:
200		for (unsigned int i = 0; i < Hack::numParticles; ++i) {
201			float temp = _particlesXYZ[i].z() + 40.0f;
202			if (temp < 0.01f) temp = 0.01f;
203			glPointSize(pointSize * temp);
204			glBegin(GL_POINTS);
205				glColor3fv(_particlesRGB[i].get());
206				glVertex3fv(_particlesXYZ[i].get());
207			glEnd();
208		}
209		break;
210	case Hack::LINES_GEOMETRY:
211		{
212			for (unsigned int i = 0; i < Hack::numParticles; ++i) {
213				float temp = _particlesXYZ[i].z() + 40.0f;
214				if (temp < 0.01f) temp = 0.01f;
215				glLineWidth(lineSize * temp);
216				glBegin(GL_LINES);
217					if (_lineList[i].second != UINT_MAX) {
218						glColor3fv(_particlesRGB[i].get());
219						if (_lineList[i].first == UINT_MAX)
220							glColor3f(0.0f, 0.0f, 0.0f);
221						glVertex3fv(_particlesXYZ[i].get());
222						glColor3fv(_particlesRGB[_lineList[i].second].get());
223						if (_lineList[_lineList[i].second].second == UINT_MAX)
224							glColor3f(0.0f, 0.0f, 0.0f);
225						glVertex3fv(_particlesXYZ[_lineList[i].second].get());
226					}
227				glEnd();
228			}
229		}
230		break;
231	}
232}