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