2 Copyright (C) 1996-1997 Id Software, Inc.
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.
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.
13 See the GNU General Public License for more details.
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.
23 float TraceLine (vec3_t start, vec3_t end, vec3_t impact, vec3_t normal);
25 #define MAX_EXPLOSIONS 64
26 #define EXPLOSIONGRID 16
27 #define EXPLOSIONVERTS ((EXPLOSIONGRID+1)*(EXPLOSIONGRID+1))
28 #define EXPLOSIONTRIS (EXPLOSIONVERTS*2)
29 #define EXPLOSIONSTARTRADIUS (0.0f)
30 #define EXPLOSIONSTARTVELOCITY (500.0f)
31 #define EXPLOSIONFADESTART (1.5f)
32 #define EXPLOSIONFADERATE (6.0f)
34 vec3_t explosionspherevert[EXPLOSIONVERTS];
35 vec3_t explosionspherevertvel[EXPLOSIONVERTS];
36 float explosiontexcoords[EXPLOSIONVERTS][2];
37 int explosiontris[EXPLOSIONTRIS][3];
38 int explosionnoiseindex[EXPLOSIONVERTS];
39 vec3_t explosionpoint[EXPLOSIONVERTS];
41 typedef struct explosion_s
45 vec3_t vert[EXPLOSIONVERTS];
46 vec3_t vertvel[EXPLOSIONVERTS];
50 explosion_t explosion[128];
52 rtexture_t *explosiontexture;
53 rtexture_t *explosiontexturefog;
55 cvar_t r_explosionclip = {"r_explosionclip", "0"};
57 int R_ExplosionVert(int column, int row)
61 i = row * (EXPLOSIONGRID + 1) + column;
62 a = row * M_PI * 2 / EXPLOSIONGRID;
63 b = column * M_PI * 2 / EXPLOSIONGRID;
65 explosionpoint[i][0] = cos(a) * c;
66 explosionpoint[i][1] = sin(a) * c;
67 explosionpoint[i][2] = -sin(b);
68 explosionnoiseindex[i] = (row & (EXPLOSIONGRID - 1)) * EXPLOSIONGRID + (column & (EXPLOSIONGRID - 1));
69 explosiontexcoords[i][0] = (float) column / (float) EXPLOSIONGRID;
70 explosiontexcoords[i][1] = (float) row / (float) EXPLOSIONGRID;
74 void r_explosion_start()
77 byte noise1[128][128], noise2[128][128], data[128][128][4];
78 fractalnoise(&noise1[0][0], 128, 2);
79 fractalnoise(&noise2[0][0], 128, 2);
80 for (y = 0;y < 128;y++)
82 for (x = 0;x < 128;x++)
85 j = noise1[y][x] * 3 - 128;
90 data[y][x][0] = bound(0, r, 255);
91 data[y][x][1] = bound(0, g, 255);
92 data[y][x][2] = bound(0, b, 255);
93 data[y][x][3] = bound(0, a, 255);
96 explosiontexture = R_LoadTexture ("explosiontexture", 128, 128, &data[0][0][0], TEXF_MIPMAP | TEXF_ALPHA | TEXF_RGBA | TEXF_PRECACHE);
97 for (y = 0;y < 128;y++)
98 for (x = 0;x < 128;x++)
99 data[y][x][0] = data[y][x][1] = data[y][x][2] = 255;
100 explosiontexturefog = R_LoadTexture ("explosiontexturefog", 128, 128, &data[0][0][0], TEXF_MIPMAP | TEXF_ALPHA | TEXF_RGBA | TEXF_PRECACHE);
103 void r_explosion_shutdown()
107 void R_Explosion_Init()
111 for (y = 0;y < EXPLOSIONGRID;y++)
113 for (x = 0;x < EXPLOSIONGRID;x++)
115 explosiontris[i][0] = R_ExplosionVert(x , y );
116 explosiontris[i][1] = R_ExplosionVert(x + 1, y );
117 explosiontris[i][2] = R_ExplosionVert(x , y + 1);
119 explosiontris[i][0] = R_ExplosionVert(x + 1, y );
120 explosiontris[i][1] = R_ExplosionVert(x + 1, y + 1);
121 explosiontris[i][2] = R_ExplosionVert(x , y + 1);
125 for (i = 0;i < EXPLOSIONVERTS;i++)
127 explosionspherevert[i][0] = explosionpoint[i][0] * EXPLOSIONSTARTRADIUS;
128 explosionspherevert[i][1] = explosionpoint[i][1] * EXPLOSIONSTARTRADIUS;
129 explosionspherevert[i][2] = explosionpoint[i][2] * EXPLOSIONSTARTRADIUS;
130 explosionspherevertvel[i][0] = explosionpoint[i][0] * EXPLOSIONSTARTVELOCITY;
131 explosionspherevertvel[i][1] = explosionpoint[i][1] * EXPLOSIONSTARTVELOCITY;
132 explosionspherevertvel[i][2] = explosionpoint[i][2] * EXPLOSIONSTARTVELOCITY;
135 Cvar_RegisterVariable(&r_explosionclip);
137 R_RegisterModule("R_Explosions", r_explosion_start, r_explosion_shutdown);
140 void R_NewExplosion(vec3_t org)
144 byte noise[EXPLOSIONGRID*EXPLOSIONGRID];
145 fractalnoise(noise, EXPLOSIONGRID, 2);
146 for (i = 0;i < MAX_EXPLOSIONS;i++)
148 if (explosion[i].alpha <= 0.0f)
150 explosion[i].alpha = EXPLOSIONFADESTART;
151 for (j = 0;j < EXPLOSIONVERTS;j++)
153 dist = noise[explosionnoiseindex[j]] * (1.0f / 512.0f) + 0.5;
154 explosion[i].vert[j][0] = explosionspherevert[j][0] * dist + org[0];
155 explosion[i].vert[j][1] = explosionspherevert[j][1] * dist + org[1];
156 explosion[i].vert[j][2] = explosionspherevert[j][2] * dist + org[2];
157 explosion[i].vertvel[j][0] = explosionspherevertvel[j][0] * dist;
158 explosion[i].vertvel[j][1] = explosionspherevertvel[j][1] * dist;
159 explosion[i].vertvel[j][2] = explosionspherevertvel[j][2] * dist;
166 void R_DrawExplosion(explosion_t *e)
168 int i, index, *indexlist = &explosiontris[0][0], alpha = bound(0, e->alpha * 128.0f, 128), texnum, fogtexnum;
171 // t = cl.time * 0.75;
177 glColor4f(1,1,1,e->alpha);
178 glDisable(GL_TEXTURE_2D);
179 // glBindTexture(GL_TEXTURE_2D, explosiontexture);
180 glVertexPointer(3, GL_FLOAT, 0, (float *) &e->vert[0][0]);
181 // glTexCoordPointer(2, GL_FLOAT, 0, (float *) &explosiontexcoords[0][0]);
182 glEnableClientState(GL_VERTEX_ARRAY);
183 // glEnableClientState(GL_TEXTURE_COORD_ARRAY);
184 glDrawElements(GL_TRIANGLES, EXPLOSIONTRIS, GL_UNSIGNED_INT, indexlist);
185 // glDisableClientState(GL_TEXTURE_COORD_ARRAY);
186 glDisableClientState(GL_VERTEX_ARRAY);
187 glEnable(GL_TEXTURE_2D);
189 texnum = R_GetTexture(explosiontexture);
190 fogtexnum = R_GetTexture(explosiontexturefog);
191 for (i = 0;i < EXPLOSIONTRIS;i++)
193 transpolybegin(texnum, 0, fogtexnum, TPOLYTYPE_ALPHA);
194 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);
195 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);
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);
201 void R_MoveExplosion(explosion_t *e, float frametime)
205 e->alpha -= frametime * EXPLOSIONFADERATE;
206 for (i = 0;i < EXPLOSIONVERTS;i++)
208 if (e->vertvel[i][0] || e->vertvel[i][1] || e->vertvel[i][2])
210 end[0] = e->vert[i][0] + frametime * e->vertvel[i][0];
211 end[1] = e->vert[i][1] + frametime * e->vertvel[i][1];
212 end[2] = e->vert[i][2] + frametime * e->vertvel[i][2];
213 if (r_explosionclip.value)
216 vec3_t impact, normal;
217 f = TraceLine(e->vert[i], end, impact, normal);
218 VectorCopy(impact, e->vert[i]);
221 // clip velocity against the wall
222 dot = -DotProduct(e->vertvel[i], normal);
223 e->vertvel[i][0] += normal[0] * dot;
224 e->vertvel[i][1] += normal[1] * dot;
225 e->vertvel[i][2] += normal[2] * dot;
230 VectorCopy(end, e->vert[i]);
236 void R_MoveExplosions()
240 frametime = cl.time - cl.oldtime;
241 for (i = 0;i < MAX_EXPLOSIONS;i++)
243 if (explosion[i].alpha > 0.0f)
245 if (explosion[i].starttime > cl.time)
247 explosion[i].alpha = 0;
250 R_MoveExplosion(&explosion[i], frametime);
255 void R_DrawExplosions()
258 for (i = 0;i < MAX_EXPLOSIONS;i++)
260 if (explosion[i].alpha > 0.0f)
262 R_DrawExplosion(&explosion[i]);