PageRenderTime 30ms CodeModel.GetById 2ms app.highlight 23ms RepoModel.GetById 3ms app.codeStats 0ms

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

http://github.com/xbmc/xbmc
C++ | 169 lines | 120 code | 21 blank | 28 comment | 14 complexity | db921e54c34514b7e6674b9e63c20647 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 <goo.hh>
 26#include <hyperspace.hh>
 27#include <implicit.hh>
 28#include <nebula.hh>
 29#include <vector.hh>
 30
 31namespace Goo {
 32	int _resolution;
 33	float _unitSize;
 34	float _volumeSize;
 35	int _arraySize;
 36
 37	std::vector<Implicit> _surface;
 38	std::vector<bool> _useSurface;
 39
 40	float _centerX, _centerZ;
 41	float _shiftX, _shiftZ;
 42
 43	float _goo[4];
 44	float _gooPhase[4] = { 0.0f, 1.0f, 2.0f, 3.0f };
 45	float _gooSpeed[4] = {
 46		0.1f + Common::randomFloat(0.4f),
 47		0.1f + Common::randomFloat(0.4f),
 48		0.1f + Common::randomFloat(0.4f),
 49		0.1f + Common::randomFloat(0.4f)
 50	};
 51	float _gooRGB[4];
 52
 53	float function(const Vector&);
 54};
 55
 56#define AT(x, y) ((x) * _arraySize + (y))
 57
 58void Goo::init() {
 59	_volumeSize = 2.0f;
 60	_resolution = (Hack::resolution < 5 ? 5 : Hack::resolution);
 61	_unitSize = _volumeSize / float(_resolution);
 62	_arraySize = 2 * int(0.99f + Hack::fogDepth / _volumeSize);
 63
 64	Implicit::init(_resolution, _resolution, _resolution, _unitSize);
 65
 66	stdx::construct_n(_surface, _arraySize * _arraySize, &function);
 67	stdx::construct_n(_useSurface, _arraySize * _arraySize, false);
 68}
 69
 70void Goo::update(float heading, float fov) {
 71	float halfFov = 0.5f * fov;
 72
 73	_centerX = _unitSize * float(int(0.5f + Hack::camera.x() / _unitSize));
 74	_centerZ = _unitSize * float(int(0.5f + Hack::camera.z() / _unitSize));
 75
 76	float clip[3][2];
 77	clip[0][0] = std::cos(heading + halfFov);
 78	clip[0][1] = -std::sin(heading + halfFov);
 79	clip[1][0] = -std::cos(heading - halfFov);
 80	clip[1][1] = std::sin(heading - halfFov);
 81	clip[2][0] = std::sin(heading);
 82	clip[2][1] = -std::cos(heading);
 83
 84	for (int i = 0; i < _arraySize; ++i) {
 85		for (int j = 0; j < _arraySize; ++j) {
 86			_shiftX = _volumeSize * (0.5f + float(int(i) - int(_arraySize) / 2));
 87			_shiftZ = _volumeSize * (0.5f + float(int(j) - int(_arraySize) / 2));
 88			if (_shiftX * clip[0][0] + _shiftZ * clip[0][1] > _volumeSize * -M_SQRT2) {
 89				if (_shiftX * clip[1][0] + _shiftZ * clip[1][1] > _volumeSize * -M_SQRT2) {
 90					if (_shiftX * clip[2][0] + _shiftZ * clip[2][1] < Hack::fogDepth + _volumeSize * M_SQRT2) {
 91						_shiftX += _centerX;
 92						_shiftZ += _centerZ;
 93						_surface[AT(i, j)].update(0.4f);
 94						_useSurface[AT(i, j)] = true;
 95					}
 96				}
 97			}
 98		}
 99	}
100
101	// calculate color
102	static float gooRGBphase[3] = { -0.1f, -0.1f, -0.1f };
103	static float gooRGBspeed[3] = {
104		Common::randomFloat(0.02f) + 0.02f,
105		Common::randomFloat(0.02f) + 0.02f,
106		Common::randomFloat(0.02f) + 0.02f
107	};
108	for (int i = 0; i < 3; ++i) {
109		gooRGBphase[i] += gooRGBspeed[i] * Common::elapsedTime;
110		if (gooRGBphase[i] >= M_PI * 2.0f) gooRGBphase[i] -= M_PI * 2.0f;
111		_gooRGB[i] = std::sin(gooRGBphase[i]);
112		if (_gooRGB[i] < 0.0f) _gooRGB[i] = 0.0f;
113	}
114
115	// update goo function constants
116	for (int i = 0; i < 4; ++i) {
117		_gooPhase[i] += _gooSpeed[i] * Common::elapsedTime;
118		if (_gooPhase[i] >= M_PI * 2.0f) _gooPhase[i] -= M_PI * 2.0f;
119		_goo[i] = 0.25f * std::cos(_gooPhase[i]);
120	}
121}
122
123void Goo::draw() {
124	glPushAttrib(GL_ENABLE_BIT);
125		Nebula::use();
126		if (Hack::shaders)
127			_gooRGB[3] = Hack::lerp;
128		else
129			_gooRGB[3] = 1.0f;
130
131		glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
132		glBlendFunc(GL_SRC_ALPHA, GL_ONE);
133		glEnable(GL_BLEND);
134		glColor4fv(_gooRGB);
135
136		for (int i = 0; i < _arraySize; ++i) {
137			for (int j = 0; j < _arraySize; ++j) {
138				if (_useSurface[AT(i, j)]) {
139					float shiftX = _centerX + _volumeSize * (0.5f + float(int(i) - int(_arraySize) / 2));
140					float shiftZ = _centerZ + _volumeSize * (0.5f + float(int(j) - int(_arraySize) / 2));
141					glPushMatrix();
142						glTranslatef(shiftX, 0.0f, shiftZ);
143						_surface[AT(i, j)].draw();
144					glPopMatrix();
145					_useSurface[AT(i, j)] = false;
146				}
147			}
148		}
149	glPopAttrib();
150}
151
152float Goo::function(const Vector& XYZ) {
153	float pX = XYZ.x() + _shiftX;
154	float pZ = XYZ.z() + _shiftZ;
155	float camX = pX - Hack::camera.x();
156	float camZ = pZ - Hack::camera.z();
157
158	return
159		// This first term defines upper and lower surfaces.
160		XYZ.y() * XYZ.y() * 1.25f
161		// These terms make the surfaces wavy.
162		+ _goo[0] * std::cos(pX - 2.71f * XYZ.y())
163		+ _goo[1] * std::cos(4.21f * XYZ.y() + pZ)
164		+ _goo[2] * std::cos(1.91f * pX - 1.67f * pZ)
165		+ _goo[3] * std::cos(1.53f * pX + 1.11f * XYZ.y() + 2.11f * pZ)
166		// The last term creates a bubble around the eyepoint so it doesn't
167		// punch through the surface.
168		- 0.1f / (camX * camX + XYZ.y() * XYZ.y() + camZ * camZ);
169}