1/*
2
3Copyright (c) 2002, Calum Robinson
4All rights reserved.
5
6Redistribution and use in source and binary forms, with or without
7modification, are permitted provided that the following conditions are met:
8
9* Redistributions of source code must retain the above copyright notice, this
10  list of conditions and the following disclaimer.
11
12* Redistributions in binary form must reproduce the above copyright notice,
13  this list of conditions and the following disclaimer in the documentation
14  and/or other materials provided with the distribution.
15
16* Neither the name of the author nor the names of its contributors may be used
17  to endorse or promote products derived from this software without specific
18  prior written permission.
19
20THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
21ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
22WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
24ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
25(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
26LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
27ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
31*/
32#include "Spark.h"
33#include "Shared.h"
34
35#define BIGMYSTERY 1800.0
36#define MAXANGLES 16384
37
38#define fieldCoherence 0
39#define fieldSpeed 12.0f
40#define fieldRange 1000.0f
41
42void InitSpark(Spark *s)
43{
44	int i;
45	for (i=0;i<3;i++)
46	{
47		s->position[i] = RandFlt(-100.0, 100.0);
48	}
49}
50
51void DrawSpark(flurry_info_t *info, Spark *s)
52{
53	const float black[4] = {0.0f,0.0f,0.0f,1.0f};
54	float width,sx,sy;
55	float a;
56	float c = 0.0625f;
57	float screenx;
58	float screeny;
59	float w,z, scale;
60	int k;
61	width = 60000.0f * info->sys_glWidth / 1024.0f;
62
63	z = s->position[2];
64	sx = s->position[0] * info->sys_glWidth / z + info->sys_glWidth * 0.5f;
65	sy = s->position[1] * info->sys_glWidth / z + info->sys_glHeight * 0.5f;
66	w = width*4.0f / z;
67
68	screenx = sx;
69	screeny = sy;
70
71	glPushMatrix();
72	glTranslatef(screenx,screeny,0.0f);
73	scale = w/50.0f;
74	glScalef(scale,scale,0.0f);
75	for (k=0;k<12;k++)
76	{
77		a = ((float) (random() % 3600)) / 10.0f;
78		glRotatef(a,0.0f,0.0f,1.0f);
79		glBegin(GL_QUAD_STRIP);
80		glColor4fv(black);
81		glVertex2f(-3.0f,0.0f);
82		a = 2.0f + (float) (random() & 255) * c;
83		glVertex2f(-3.0f,a);
84		glColor4fv(s->color);
85		glVertex2f(0.0f,0.0f);
86		glColor4fv(black);
87		glVertex2f(0.0f,a);
88		glVertex2f(3.0f,0.0f);
89		glVertex2f(3.0f,a);
90		glEnd();
91	}
92	glPopMatrix();
93}
94
95void UpdateSparkColour(flurry_info_t *info, Spark *s)
96{
97	const float rotationsPerSecond = (float) (2.0*M_PI*fieldSpeed/MAXANGLES);
98	double thisPointInRadians;
99	double thisAngle = info->fTime*rotationsPerSecond;
100	float cf;
101	float cycleTime = 20.0f;
102	float colorRot;
103	float redPhaseShift;
104	float greenPhaseShift;
105	float bluePhaseShift;
106	float baseRed;
107	float baseGreen;
108	float baseBlue;
109	float colorTime;
110
111	if (info->currentColorMode == rainbowColorMode)
112	{
113		cycleTime = 1.5f;
114	}
115	else if (info->currentColorMode == tiedyeColorMode)
116	{
117		cycleTime = 4.5f;
118	}
119	else if (info->currentColorMode == cyclicColorMode)
120	{
121		cycleTime = 20.0f;
122	}
123	else if (info->currentColorMode == slowCyclicColorMode)
124	{
125		cycleTime = 120.0f;
126	}
127	colorRot = (float) (2.0*M_PI/cycleTime);
128	redPhaseShift = 0.0f; /* cycleTime * 0.0f / 3.0f */
129	greenPhaseShift = cycleTime / 3.0f;
130	bluePhaseShift = cycleTime * 2.0f / 3.0f ;
131	colorTime = info->fTime;
132	if (info->currentColorMode == whiteColorMode)
133	{
134		baseRed = 0.1875f;
135		baseGreen = 0.1875f;
136		baseBlue = 0.1875f;
137	}
138	else if (info->currentColorMode == multiColorMode)
139	{
140		baseRed = 0.0625f;
141		baseGreen = 0.0625f;
142		baseBlue = 0.0625f;
143	}
144	else if (info->currentColorMode == darkColorMode)
145	{
146		baseRed = 0.0f;
147		baseGreen = 0.0f;
148		baseBlue = 0.0f;
149	}
150	else
151	{
152		if (info->currentColorMode < slowCyclicColorMode)
153		{
154			colorTime = (info->currentColorMode / 6.0f) * cycleTime;
155		}
156		else
157		{
158			colorTime = info->fTime + info->randomSeed;
159		}
160		baseRed = 0.109375f * ((float) cos((colorTime+redPhaseShift)*colorRot)+1.0f);
161		baseGreen = 0.109375f * ((float) cos((colorTime+greenPhaseShift)*colorRot)+1.0f);
162		baseBlue = 0.109375f * ((float) cos((colorTime+bluePhaseShift)*colorRot)+1.0f);
163	}
164
165	cf = ((float) (cos(7.0*((info->fTime)*rotationsPerSecond)) +
166		cos(3.0*((info->fTime)*rotationsPerSecond)) +
167		cos(13.0*((info->fTime)*rotationsPerSecond))));
168	cf /= 6.0f;
169	cf += 2.0f;
170	thisPointInRadians = 2.0 * M_PI * (double) s->mystery / (double) BIGMYSTERY;
171
172	s->color[0] = baseRed + 0.0625f *
173		(0.5f + (float) cos((15.0 * (thisPointInRadians + 3.0*thisAngle))) +
174		(float) sin((7.0 * (thisPointInRadians + thisAngle))));
175	s->color[1] = baseGreen + 0.0625f *
176		(0.5f + (float) sin(((thisPointInRadians) + thisAngle)));
177	s->color[2] = baseBlue + 0.0625f *
178		(0.5f + (float) cos((37.0 * (thisPointInRadians + thisAngle))));
179}
180
181void UpdateSpark(flurry_info_t *info, Spark *s)
182{
183	const float rotationsPerSecond = (float) (2.0*M_PI*fieldSpeed/MAXANGLES);
184	double thisPointInRadians;
185	double thisAngle = info->fTime*rotationsPerSecond;
186	float cf;
187	int i;
188	double tmpX1,tmpY1,tmpZ1;
189	double tmpX2,tmpY2,tmpZ2;
190	double tmpX3,tmpY3,tmpZ3;
191	double tmpX4,tmpY4,tmpZ4;
192	double rotation;
193	double cr;
194	double sr;
195	float cycleTime = 20.0f;
196	float colorRot;
197	float redPhaseShift;
198	float greenPhaseShift;
199	float bluePhaseShift;
200	float baseRed;
201	float baseGreen;
202	float baseBlue;
203	float colorTime;
204
205	float old[3];
206
207	if (info->currentColorMode == rainbowColorMode) {
208		cycleTime = 1.5f;
209	} else if (info->currentColorMode == tiedyeColorMode) {
210		cycleTime = 4.5f;
211	} else if (info->currentColorMode == cyclicColorMode) {
212		cycleTime = 20.0f;
213	} else if (info->currentColorMode == slowCyclicColorMode) {
214		cycleTime = 120.0f;
215	}
216	colorRot = (float) (2.0*M_PI/cycleTime);
217	redPhaseShift = 0.0f; /* cycleTime * 0.0f / 3.0f */
218	greenPhaseShift = cycleTime / 3.0f;
219	bluePhaseShift = cycleTime * 2.0f / 3.0f ;
220	colorTime = info->fTime;
221	if (info->currentColorMode == whiteColorMode) {
222		baseRed = 0.1875f;
223		baseGreen = 0.1875f;
224		baseBlue = 0.1875f;
225	} else if (info->currentColorMode == multiColorMode) {
226		baseRed = 0.0625f;
227		baseGreen = 0.0625f;
228		baseBlue = 0.0625f;
229	} else if (info->currentColorMode == darkColorMode) {
230		baseRed = 0.0f;
231		baseGreen = 0.0f;
232		baseBlue = 0.0f;
233	} else {
234		if(info->currentColorMode < slowCyclicColorMode) {
235			colorTime = (info->currentColorMode / 6.0f) * cycleTime;
236		} else {
237			colorTime = info->fTime + info->randomSeed;
238		}
239		baseRed = 0.109375f * ((float) cos((colorTime+redPhaseShift)*colorRot)+1.0f);
240		baseGreen = 0.109375f * ((float) cos((colorTime+greenPhaseShift)*colorRot)+1.0f);
241		baseBlue = 0.109375f * ((float) cos((colorTime+bluePhaseShift)*colorRot)+1.0f);
242	}
243
244	for (i=0;i<3;i++) {
245		old[i] = s->position[i];
246	}
247
248	cf = ((float) (cos(7.0*((info->fTime)*rotationsPerSecond)) +
249		cos(3.0*((info->fTime)*rotationsPerSecond)) +
250		cos(13.0*((info->fTime)*rotationsPerSecond))));
251	cf /= 6.0f;
252	cf += 2.0f;
253	thisPointInRadians = 2.0 * M_PI * (double) s->mystery / (double) BIGMYSTERY;
254
255	s->color[0] = baseRed + 0.0625f *
256		(0.5f + (float) cos((15.0 * (thisPointInRadians + 3.0*thisAngle))) +
257		 (float) sin((7.0 * (thisPointInRadians + thisAngle))));
258	s->color[1] = baseGreen + 0.0625f *
259		(0.5f + (float) sin(((thisPointInRadians) + thisAngle)));
260	s->color[2] = baseBlue + 0.0625f *
261		(0.5f + (float) cos((37.0 * (thisPointInRadians + thisAngle))));
262	s->position[0] = fieldRange * cf *
263		(float) cos(11.0 * (thisPointInRadians + (3.0*thisAngle)));
264	s->position[1] = fieldRange * cf *
265		(float) sin(12.0 * (thisPointInRadians + (4.0*thisAngle)));
266	s->position[2] = fieldRange *
267		(float) cos((23.0 * (thisPointInRadians + (12.0*thisAngle))));
268
269	rotation = thisAngle*0.501 + 5.01 * (double) s->mystery / (double) BIGMYSTERY;
270	cr = cos(rotation);
271	sr = sin(rotation);
272	tmpX1 = s->position[0] * cr - s->position[1] * sr;
273	tmpY1 = s->position[1] * cr + s->position[0] * sr;
274	tmpZ1 = s->position[2];
275
276	tmpX2 = tmpX1 * cr - tmpZ1 * sr;
277	tmpY2 = tmpY1;
278	tmpZ2 = tmpZ1 * cr + tmpX1 * sr;
279
280	tmpX3 = tmpX2;
281	tmpY3 = tmpY2 * cr - tmpZ2 * sr;
282	tmpZ3 = tmpZ2 * cr + tmpY2 * sr + seraphDistance;
283
284	rotation = thisAngle*2.501 + 85.01 * (double) s->mystery / (double) BIGMYSTERY;
285	cr = cos(rotation);
286	sr = sin(rotation);
287	tmpX4 = tmpX3 * cr - tmpY3 * sr;
288	tmpY4 = tmpY3 * cr + tmpX3 * sr;
289	tmpZ4 = tmpZ3;
290
291	s->position[0] = (float) tmpX4 + RandBell(5.0f*fieldCoherence);
292	s->position[1] = (float) tmpY4 + RandBell(5.0f*fieldCoherence);
293	s->position[2] = (float) tmpZ4 + RandBell(5.0f*fieldCoherence);
294
295	for (i=0;i<3;i++) {
296		s->delta[i] = (s->position[i] - old[i])/info->fDeltaTime;
297	}
298}
299