updated makefile and added r_explosion.c (forgot)
[divverent/darkplaces.git] / r_explosion.c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
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.  
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19 */
20
21 #include "quakedef.h"
22
23 float TraceLine (vec3_t start, vec3_t end, vec3_t impact, vec3_t normal);
24
25 #define MAX_EXPLOSIONS 64
26 #define EXPLOSIONBANDS 16
27 #define EXPLOSIONSEGMENTS 16
28 #define EXPLOSIONVERTS ((EXPLOSIONBANDS+1)*(EXPLOSIONSEGMENTS+1))
29 #define EXPLOSIONTRIS (EXPLOSIONVERTS*2)
30 #define EXPLOSIONSTARTRADIUS (0.0f)
31 #define EXPLOSIONSTARTVELOCITY (400.0f)
32 #define EXPLOSIONFADESTART (1.5f)
33 #define EXPLOSIONFADERATE (6.0f)
34
35 vec3_t explosionspherevert[EXPLOSIONVERTS];
36 vec3_t explosionspherevertvel[EXPLOSIONVERTS];
37 float explosiontexcoords[EXPLOSIONVERTS][2];
38 int explosiontris[EXPLOSIONTRIS][3];
39 vec3_t explosionpoint[EXPLOSIONVERTS];
40
41 typedef struct explosion_s
42 {
43         float alpha;
44         vec3_t vert[EXPLOSIONVERTS];
45         vec3_t vertvel[EXPLOSIONVERTS];
46 }
47 explosion_t;
48
49 explosion_t explosion[128];
50
51 int             explosiontexture;
52 int             explosiontexturefog;
53
54 cvar_t r_explosionclip = {"r_explosionclip", "0"};
55
56 int R_ExplosionVert(int column, int row)
57 {
58         int i;
59         float a, b, c;
60         i = row * (EXPLOSIONSEGMENTS + 1) + column;
61         a = row * M_PI * 2 / EXPLOSIONBANDS;
62         b = column * M_PI * 2 / EXPLOSIONSEGMENTS;
63         c = cos(b);
64         explosionpoint[i][0] = cos(a) * c;
65         explosionpoint[i][1] = sin(a) * c;
66         explosionpoint[i][2] = -sin(b);
67         explosiontexcoords[i][0] = (float) column / (float) EXPLOSIONSEGMENTS;
68         explosiontexcoords[i][1] = (float) row / (float) EXPLOSIONBANDS;
69         return i;
70 }
71
72 void r_explosion_start()
73 {
74         int x, y;
75         byte noise1[128][128], noise2[128][128], data[128][128][4];
76         fractalnoise(&noise1[0][0], 128, 8);
77         fractalnoise(&noise2[0][0], 128, 8);
78         for (y = 0;y < 128;y++)
79         {
80                 for (x = 0;x < 128;x++)
81                 {
82                         int j, r, g, b, a;
83                         j = noise1[y][x] * 3 - 128;
84                         r = (j * 512) / 256;
85                         g = (j * 256) / 256;
86                         b = (j * 128) / 256;
87                         a = noise2[y][x];
88                         data[y][x][0] = bound(0, r, 255);
89                         data[y][x][1] = bound(0, g, 255);
90                         data[y][x][2] = bound(0, b, 255);
91                         data[y][x][3] = bound(0, a, 255);
92                 }
93         }
94         explosiontexture = GL_LoadTexture ("explosiontexture", 128, 128, &data[0][0][0], true, true, 4);
95         for (y = 0;y < 128;y++)
96                 for (x = 0;x < 128;x++)
97                         data[y][x][0] = data[y][x][1] = data[y][x][2] = 255;
98         explosiontexturefog = GL_LoadTexture ("explosiontexturefog", 128, 128, &data[0][0][0], true, true, 4);
99 }
100
101 void r_explosion_shutdown()
102 {
103 }
104
105 void R_Explosion_Init()
106 {
107         int i, x, y;
108         i = 0;
109         for (y = 0;y < EXPLOSIONBANDS;y++)
110         {
111                 for (x = 0;x < EXPLOSIONSEGMENTS;x++)
112                 {
113                         explosiontris[i][0] = R_ExplosionVert(x    , y    );
114                         explosiontris[i][1] = R_ExplosionVert(x + 1, y    );
115                         explosiontris[i][2] = R_ExplosionVert(x    , y + 1);
116                         i++;
117                         explosiontris[i][0] = R_ExplosionVert(x + 1, y    );
118                         explosiontris[i][1] = R_ExplosionVert(x + 1, y + 1);
119                         explosiontris[i][2] = R_ExplosionVert(x    , y + 1);
120                         i++;
121                 }
122         }
123         for (i = 0;i < EXPLOSIONVERTS;i++)
124         {
125                 explosionspherevert[i][0] = explosionpoint[i][0] * EXPLOSIONSTARTRADIUS;
126                 explosionspherevert[i][1] = explosionpoint[i][1] * EXPLOSIONSTARTRADIUS;
127                 explosionspherevert[i][2] = explosionpoint[i][2] * EXPLOSIONSTARTRADIUS;
128                 explosionspherevertvel[i][0] = explosionpoint[i][0] * EXPLOSIONSTARTVELOCITY;
129                 explosionspherevertvel[i][1] = explosionpoint[i][1] * EXPLOSIONSTARTVELOCITY;
130                 explosionspherevertvel[i][2] = explosionpoint[i][2] * EXPLOSIONSTARTVELOCITY;
131         }
132
133         Cvar_RegisterVariable(&r_explosionclip);
134
135         R_RegisterModule("R_Explosions", r_explosion_start, r_explosion_shutdown);
136 }
137
138 void R_NewExplosion(vec3_t org)
139 {
140         int i, j;
141         for (i = 0;i < MAX_EXPLOSIONS;i++)
142         {
143                 if (explosion[i].alpha <= 0.0f)
144                 {
145                         explosion[i].alpha = EXPLOSIONFADESTART;
146                         for (j = 0;j < EXPLOSIONVERTS;j++)
147                         {
148                                 explosion[i].vert[j][0] = explosionspherevert[j][0] + org[0];
149                                 explosion[i].vert[j][1] = explosionspherevert[j][1] + org[1];
150                                 explosion[i].vert[j][2] = explosionspherevert[j][2] + org[2];
151                                 explosion[i].vertvel[j][0] = explosionspherevertvel[j][0];
152                                 explosion[i].vertvel[j][1] = explosionspherevertvel[j][1];
153                                 explosion[i].vertvel[j][2] = explosionspherevertvel[j][2];
154                         }
155                         break;
156                 }
157         }
158 }
159
160 void R_DrawExplosion(explosion_t *e)
161 {
162         int i, index, *indexlist = &explosiontris[0][0], alpha = bound(0, e->alpha * 255.0f, 255);
163         float s = cl.time * 1, t = cl.time * 0.75;
164         s -= (int) s;
165         t -= (int) t;
166         /*
167         glColor4f(1,1,1,e->alpha);
168         glDisable(GL_TEXTURE_2D);
169 //      glBindTexture(GL_TEXTURE_2D, explosiontexture);
170         if (gl_vertexarrays.value)
171         {
172                 qglVertexPointer(3, GL_FLOAT, 0, (float *) &e->vert[0][0]);
173 //              qglTexCoordPointer(2, GL_FLOAT, 0, (float *) &explosiontexcoords[0][0]);
174                 glEnableClientState(GL_VERTEX_ARRAY);
175 //              glEnableClientState(GL_TEXTURE_COORD_ARRAY);
176                 qglDrawElements(GL_TRIANGLES, EXPLOSIONTRIS, GL_UNSIGNED_INT, indexlist);
177 //              glDisableClientState(GL_TEXTURE_COORD_ARRAY);
178                 glDisableClientState(GL_VERTEX_ARRAY);
179         }
180         else
181         {
182                 glBegin(GL_TRIANGLES);
183                 for (i = 0;i < EXPLOSIONTRIS * 3;i++)
184                 {
185                         index = *indexlist++;
186 //                      glTexCoord2fv(explosiontexcoords[index]);
187                         glVertex3fv(e->vert[index]);
188                 }
189                 glEnd();
190         }
191         glEnable(GL_TEXTURE_2D);
192         */
193         for (i = 0;i < EXPLOSIONTRIS;i++)
194         {
195                 transpolybegin(explosiontexture, 0, explosiontexturefog, TPOLYTYPE_ALPHA);
196                 index = *indexlist++;transpolyvert(e->vert[index][0], e->vert[index][1], e->vert[index][2], explosiontexcoords[index][0] + s, explosiontexcoords[index][1] + t, 255, 255, 255, alpha);
197                 index = *indexlist++;transpolyvert(e->vert[index][0], e->vert[index][1], e->vert[index][2], explosiontexcoords[index][0] + s, explosiontexcoords[index][1] + t, 255, 255, 255, alpha);
198                 index = *indexlist++;transpolyvert(e->vert[index][0], e->vert[index][1], e->vert[index][2], explosiontexcoords[index][0] + s, explosiontexcoords[index][1] + t, 255, 255, 255, alpha);
199                 transpolyend();
200         }
201 }
202
203 void R_MoveExplosion(explosion_t *e, float frametime)
204 {
205         int i;
206         vec3_t end;
207         e->alpha -= frametime * EXPLOSIONFADERATE;
208         for (i = 0;i < EXPLOSIONVERTS;i++)
209         {
210                 if (e->vertvel[i][0] || e->vertvel[i][1] || e->vertvel[i][2])
211                 {
212                         end[0] = e->vert[i][0] + frametime * e->vertvel[i][0];
213                         end[1] = e->vert[i][1] + frametime * e->vertvel[i][1];
214                         end[2] = e->vert[i][2] + frametime * e->vertvel[i][2];
215                         if (r_explosionclip.value)
216                         {
217                                 float f, dot;
218                                 vec3_t impact, normal;
219                                 f = TraceLine(e->vert[i], end, impact, normal);
220                                 VectorCopy(impact, e->vert[i]);
221                                 if (f < 1)
222                                 {
223                                         // clip velocity against the wall
224                                         dot = -DotProduct(e->vertvel[i], normal);
225                                         e->vertvel[i][0] += normal[0] * dot;
226                                         e->vertvel[i][1] += normal[1] * dot;
227                                         e->vertvel[i][2] += normal[2] * dot;
228                                 }
229                         }
230                         else
231                         {
232                                 VectorCopy(end, e->vert[i]);
233                         }
234                 }
235         }
236 }
237
238 void R_MoveExplosions()
239 {
240         int i;
241         float frametime;
242         frametime = cl.time - cl.oldtime;
243         for (i = 0;i < MAX_EXPLOSIONS;i++)
244         {
245                 if (explosion[i].alpha > 0.0f)
246                 {
247                         R_MoveExplosion(&explosion[i], frametime);
248                 }
249         }
250 }
251
252 void R_DrawExplosions()
253 {
254         int i;
255         for (i = 0;i < MAX_EXPLOSIONS;i++)
256         {
257                 if (explosion[i].alpha > 0.0f)
258                 {
259                         R_DrawExplosion(&explosion[i]);
260                 }
261         }
262 }