1 /*
2 * Copyright (C) 2002 Jeremie Allard (Hufo / N.A.A.)
3 *
4 * Note: Credits for the 2d warping field fly to
5 * Hugo Elias: http://freespace.virgin.net/hugo.elias
6 * I've transposed to 3d.
7 *
8 * Ported to Linux by Tugrul Galatali <tugrul@galatali.com>
9 *
10 * hufo_smoke is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
13 *
14 * hufo_smoke is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 */
23
24 #include <stdio.h>
25 #include <cmath>
26
27 // In case cmath doesn't pull in all the usual suspects from math.h
28 #ifndef M_PI
29 #include <math.h>
30 #endif
31
32 #include <GL/gl.h>
33
34 #include "FMotion.h"
35 #include "rsRand.h"
36
37 #define TILE 1.0f
38 #define NBTILEZ 8
39 #define NBTILEY 4
40 #define NBTILEX 8
41
42 #define WARPFACT (TILE*5.0f)
43 #define AFFFACT ((TILE/16.0f)/WARPFACT)
44 #define SPRINGFACT 0.01f
45 #define DYNFACT 0.998f
46 #define MAXLENGTH (WARPFACT*4)
47
48 #define ANGFACT 1
49 #define ANGRND 0.16f
50 #define ANG0 0.16f
51
52 #define SHFT 8
53
54 #define FLOATTOINTCONST2 (((65536.0*16)))
f2int2(float f)55 inline int f2int2 (float f)
56 {
57 f += FLOATTOINTCONST2;
58 return ((*((int *)(void *)&f)) & 0x007fffff) - 0x00400000;
59 }
60
61 #define FLOATTOINTCONST (((1.5*65536*256)))
f2int(float f)62 inline int f2int (float f)
63 {
64 f += FLOATTOINTCONST;
65 return ((*((int *)(void *)&f)) & 0x007fffff) - 0x00400000;
66 }
67
68 #define Float2Int(f) (f2int(f))
69 #define Float2Int2(f) (f2int2(f))
70
71 typedef float real;
72
73 #define SQRT_2 1.414213562f
74 #define SQRT_3 1.732050808f
75 #define SQRT_5 2.236067977f
76 #define SQRT_6 2.449489743f
77
78 #define D0 0
79 #define D1 1
80 #define D2 2
81 #define D1_1 SQRT_2
82 #define D2_1 SQRT_5
83 #define D2_2 2*SQRT_2
84 #define D1_1_1 SQRT_3
85 #define D2_1_1 SQRT_6
86 #define D2_2_1 3
87 #define D2_2_2 3*SQRT_2
88
89 real norms[3][3][3] = {
90 {
91 { TILE * D0, TILE * D1, TILE * D2 },
92 { TILE * D1, TILE * D1_1, TILE * D2_1 },
93 { TILE * D2, TILE * D2_1, TILE * D2_2 },
94 },
95 {
96 { TILE * D1, TILE * D1_1, TILE * D2_1 },
97 { TILE * D1_1, TILE * D1_1_1, TILE * D2_1_1 },
98 { TILE * D2_1, TILE * D2_1_1, TILE * D2_2_1 }
99 },
100 {
101 { TILE * D2, TILE * D2_1, TILE * D2_2 },
102 { TILE * D2_1, TILE * D2_1_1, TILE * D2_2_1 },
103 { TILE * D2_2, TILE * D2_2_1, TILE * D2_2_2 }
104 }
105 };
106
107 real distvar[3] = { -TILE, 0, TILE };
108
109 struct PARTICLE offset[NBTILEZ][NBTILEY][NBTILEZ];
110
111 real deplfact[1 << SHFT];
112
FMotionInit()113 bool FMotionInit ()
114 {
115 int i;
116
117 for (i = 0; i < (1 << SHFT); ++i)
118 deplfact[i] = i / ((real) (1 << SHFT));
119 int x, y, z;
120 PARTICLE *p;
121
122 //initialise gelly
123 real t, t1, t2, t3, tt, tt1, tt2, tt3, ttt, ttt1, ttt2, ttt3, xf, yf, zf;
124 real f, f1, f2, f3, ff, ff1, ff2, ff3, fff, fff1, fff2, fff3;
125
126 ttt = rsRandf (2 * M_PI);
127 f = rsRandf (ANGRND) + ANG0;
128 ff = rsRandf (ANGRND) + ANG0;
129 fff = rsRandf (ANGRND) + ANG0;
130 ttt1 = rsRandf (2 * M_PI);
131 f1 = rsRandf (ANGRND) + ANG0;
132 ff1 = rsRandf (ANGRND) + ANG0;
133 fff1 = rsRandf (ANGRND) + ANG0;
134 ttt2 = rsRandf (2 * M_PI);
135 f2 = rsRandf (ANGRND) + ANG0;
136 ff2 = rsRandf (ANGRND) + ANG0;
137 fff2 = rsRandf (ANGRND) + ANG0;
138 ttt3 = rsRandf (2 * M_PI);
139 f3 = rsRandf (ANGRND) + ANG0;
140 ff3 = rsRandf (ANGRND) + ANG0;
141 fff3 = rsRandf (ANGRND) + ANG0;
142 p = &offset[0][0][0];
143 for (z = 0; z < NBTILEZ; z++) {
144 zf = real (z);
145 tt = ttt;
146 tt1 = ttt1;
147 tt2 = ttt3;
148 tt3 = ttt3;
149 ttt += fff;
150 ttt1 += fff1;
151 ttt2 += fff2;
152 ttt3 += fff3;
153 for (y = 0; y < NBTILEY; y++) {
154 yf = real (y);
155 t = tt;
156 t1 = tt1;
157 t2 = tt3;
158 t3 = tt3;
159 tt += ff;
160 tt1 += ff1;
161 tt2 += ff2;
162 tt3 += ff3;
163 for (x = 0; x < NBTILEX; x++, p++) {
164 xf = real (x);
165 t += f;
166 t1 += f1;
167 t2 += f2;
168 t3 += f3;
169 p->p.x() = (real) (WARPFACT * (sin (ANGFACT * (t2 - xf)) + cos (ANGFACT * (t2 + yf)) + sin (ANGFACT * (t - yf)) - cos (ANGFACT * (t + xf)))); //+x*TILE);
170 p->p.y() = (real) (WARPFACT * (sin (ANGFACT * (t1 - xf)) + cos (ANGFACT * (t3 + yf)) + sin (ANGFACT * (t3 - yf)) - cos (ANGFACT * (t1 + xf)))); //+y*TILE);
171 p->p.z() = (real) (WARPFACT * (sin (ANGFACT * (t - xf)) + cos (ANGFACT * (t2 + yf)) + sin (ANGFACT * (t - yf)) - cos (ANGFACT * (t2 + xf)))); //+z*TILE);
172 p->v.zero ();
173 }
174 }
175 }
176 return 1;
177 }
178
FMotionQuit()179 void FMotionQuit ()
180 {
181 }
182
FMotionAnimate(const float & dt)183 void FMotionAnimate (const float &dt)
184 {
185 // Handles the wobbling gel, which is used to give the WarpMap it's shape
186 int x, y, z, xi, yi, zi, xh, xl, yh, yl, zh, zl;
187 rsVec spring;
188 real norm;
189 PARTICLE *p, *p2;
190 real ft = SPRINGFACT * dt;
191
192 p = &offset[0][0][0];
193 for (z = 0; z < NBTILEZ; z++) {
194 zh = z + 1;
195 zl = z - 1; //if (zl<0) zl=0; if (zh>tz) zh=tz;
196 for (y = 0; y < NBTILEY; y++) {
197 yh = y + 1;
198 yl = y - 1; //if (yl<0) yl=0; if (yh>ty) yh=ty;
199 for (x = 0; x < NBTILEX; x++, p++) {
200 // Add attraction back to origin of this point
201 p->v += p->p * (-p->p.length() * ft);
202 xh = x + 1;
203 xl = x - 1; //if (xl<0) xl=0; if (xh>tx) xh=tx;
204 for (zi = zl; zi <= zh; zi++) {
205 for (yi = yl; yi <= yh; yi++) {
206 for (xi = xl; xi <= xh; xi++) {
207 if ((xi != x) || (yi != y) || (zi != z)) {
208 norm = norms[abs (zi - z)][abs (yi - y)][abs (xi - x)];
209 p2 = &offset[zi & (NBTILEZ - 1)][yi & (NBTILEY - 1)][xi & (NBTILEX - 1)];
210 spring = p2->p;
211 spring -= p->p;
212 spring.x() += distvar[xi - x + 1];
213 spring.y() += distvar[yi - y + 1];
214 spring.z() += distvar[zi - z + 1];
215 spring *= (norm - spring.length ()) * ft;
216 p2->v += spring;
217 }
218 }
219 }
220 }
221 }
222 }
223 }
224 p = &offset[0][0][0];
225 ft = (real) pow (DYNFACT, dt);
226 for (z = 0; z < NBTILEZ; z++) {
227 for (y = 0; y < NBTILEY; y++) {
228 for (x = 0; x < NBTILEX; x++, p++) {
229 p->p += p->v * dt;
230 if (p->p.length2 () > (MAXLENGTH * MAXLENGTH)) {
231 p->v.zero ();
232 } else
233 p->v *= ft;
234 }
235 }
236 }
237 }
238
239 #define Point2STX(p) ( (Float2Int((p.x())*(TILE*(1<<SHFT)))+((NBTILEX/2)<<SHFT)) & ((NBTILEX<<SHFT)-1) )
240 #define Point2STY(p) ( (Float2Int((p.y())*(TILE*(1<<SHFT)))+((NBTILEY/2)<<SHFT)) & ((NBTILEY<<SHFT)-1) )
241 #define Point2STZ(p) ( (Float2Int((p.z())*(TILE*(1<<SHFT)))) & ((NBTILEZ<<SHFT)-1) )
242
FMotionWarp(rsVec & p,const float & dt)243 void FMotionWarp (rsVec &p, const float &dt)
244 {
245 int sx, sy, sz, x2, y2, z2;
246
247 sx = Point2STX (p);
248 sy = Point2STY (p);
249 sz = Point2STZ (p);
250
251 real fx, fy, fz;
252
253 fx = deplfact[sx & ((1 << SHFT) - 1)];
254 fy = deplfact[sy & ((1 << SHFT) - 1)];
255 fz = deplfact[sz & ((1 << SHFT) - 1)];
256 sx >>= SHFT;
257 x2 = (sx + 1) & (NBTILEX - 1);
258 sy >>= SHFT;
259 y2 = (sy + 1) & (NBTILEY - 1);
260 sz >>= SHFT;
261 z2 = (sz + 1) & (NBTILEZ - 1);
262
263 static rsVec v0, v1, v;
264
265 v0.linearInterp (offset[sz][sy][sx].p, offset[sz][sy][sx + 1].p, fx);
266 v1.linearInterp (offset[z2][sy][sx].p, offset[z2][sy][sx + 1].p, fx);
267 v.linearInterp (v0, v1, fz);
268
269 v *= dt;
270 p += v;
271 }
272
273 #define HVCtrX 0.0
274 #define HVCtrY 0.0
275 extern float FireFoc;
276 extern rsVec FireSrc;
277 extern rsMatrix FireM;
278 extern rsVec FireO;
279
280 #define FireFocX FireFoc
281 #define FireFocY FireFoc
282
283 #define ProjEX(p) (HVCtrX+FireFocX*(p).x()/(p).y())
284 #define ProjEY(p) (HVCtrY+FireFocY*(p).z()/(p).y())
285 #define ProjEZ(ez,p) (ez)=-((p).y()*(1.0f/20.0f)-1.0f)
286
AffFMotion()287 void AffFMotion ()
288 {
289 int x, y, z;
290 PARTICLE *p;
291 real xf, yf, zf;
292 real ex, ey;
293 real ez;
294 rsVec p1, p2, o;
295
296 p = &offset[0][0][0];
297
298 glBegin (GL_LINES);
299
300 o = FireSrc;
301 o.x() -= TILE * NBTILEX / 2;
302 o.y() -= TILE * NBTILEY / 2;
303 o.transVec(FireM);
304 o += FireO;
305 for (z = 0; z < NBTILEZ; z++) {
306 zf = z * TILE;
307 for (y = 0; y < NBTILEY; y++) {
308 yf = y * TILE;
309 for (x = 0; x < NBTILEX; x++, p++) {
310 xf = x * TILE;
311 p1.x() = xf;
312 p1.y() = yf;
313 p1.z() = zf;
314 p2 = p1 + p->p * AFFFACT;
315 p1.transVec(FireM);
316 p1 += o;
317 p2.transVec(FireM);
318 p2 += o;
319 if (p1.y() > 0 && p2.y() > 0) {
320 ex = ProjEX (p1);
321 ey = ProjEY (p1);
322 ProjEZ (ez, p1);
323 glVertex3f (ex, ey, ez);
324 ex = ProjEX (p2);
325 ey = ProjEY (p2);
326 ProjEZ (ez, p2);
327 glVertex3f (ex, ey, ez);
328 }
329 }
330 }
331 }
332
333 glEnd ();
334 }
335