X-Git-Url: http://de.git.xonotic.org/?p=xonotic%2Fdarkplaces.git;a=blobdiff_plain;f=r_explosion.c;h=430e399c08533ef30bc8f9fdbd27fff52e771139;hp=bff9f5cff00be67a2bd96f84aed097129ba9f9e0;hb=066c77541b654eb4665614c07126b864b9d5e2f7;hpb=6b7b09432f660c26297ea84b4ce1b05e8c4011bf diff --git a/r_explosion.c b/r_explosion.c index bff9f5cf..430e399c 100644 --- a/r_explosion.c +++ b/r_explosion.c @@ -8,7 +8,7 @@ of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. @@ -19,96 +19,110 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "quakedef.h" - -float TraceLine (vec3_t start, vec3_t end, vec3_t impact, vec3_t normal); +#include "cl_collision.h" #define MAX_EXPLOSIONS 64 -#define EXPLOSIONBANDS 16 -#define EXPLOSIONSEGMENTS 16 -#define EXPLOSIONVERTS ((EXPLOSIONBANDS+1)*(EXPLOSIONSEGMENTS+1)) -#define EXPLOSIONTRIS (EXPLOSIONVERTS*2) -#define EXPLOSIONSTARTRADIUS (0.0f) -#define EXPLOSIONSTARTVELOCITY (400.0f) -#define EXPLOSIONFADESTART (1.5f) -#define EXPLOSIONFADERATE (6.0f) - -vec3_t explosionspherevert[EXPLOSIONVERTS]; -vec3_t explosionspherevertvel[EXPLOSIONVERTS]; -float explosiontexcoords[EXPLOSIONVERTS][2]; -int explosiontris[EXPLOSIONTRIS][3]; -vec3_t explosionpoint[EXPLOSIONVERTS]; +#define EXPLOSIONGRID 8 +#define EXPLOSIONVERTS ((EXPLOSIONGRID+1)*(EXPLOSIONGRID+1)) +#define EXPLOSIONTRIS (EXPLOSIONGRID*EXPLOSIONGRID*2) + +static float explosiontexcoord2f[EXPLOSIONVERTS][2]; +static int explosiontris[EXPLOSIONTRIS][3]; +static int explosionnoiseindex[EXPLOSIONVERTS]; +static vec3_t explosionpoint[EXPLOSIONVERTS]; typedef struct explosion_s { + float starttime; + float endtime; + float time; float alpha; + float fade; + vec3_t origin; vec3_t vert[EXPLOSIONVERTS]; vec3_t vertvel[EXPLOSIONVERTS]; + qboolean clipping; } explosion_t; -explosion_t explosion[128]; +static explosion_t explosion[MAX_EXPLOSIONS]; -int explosiontexture; -int explosiontexturefog; +static rtexture_t *explosiontexture; +static rtexture_t *explosiontexturefog; -cvar_t r_explosionclip = {"r_explosionclip", "0"}; +static rtexturepool_t *explosiontexturepool; -int R_ExplosionVert(int column, int row) -{ - int i; - float a, b, c; - i = row * (EXPLOSIONSEGMENTS + 1) + column; - a = row * M_PI * 2 / EXPLOSIONBANDS; - b = column * M_PI * 2 / EXPLOSIONSEGMENTS; - c = cos(b); - explosionpoint[i][0] = cos(a) * c; - explosionpoint[i][1] = sin(a) * c; - explosionpoint[i][2] = -sin(b); - explosiontexcoords[i][0] = (float) column / (float) EXPLOSIONSEGMENTS; - explosiontexcoords[i][1] = (float) row / (float) EXPLOSIONBANDS; - return i; -} +cvar_t r_explosionclip = {CVAR_SAVE, "r_explosionclip", "1"}; +static cvar_t r_drawexplosions = {0, "r_drawexplosions", "1"}; -void r_explosion_start() +static void r_explosion_start(void) { int x, y; - byte noise1[128][128], noise2[128][128], data[128][128][4]; - fractalnoise(&noise1[0][0], 128, 8); - fractalnoise(&noise2[0][0], 128, 8); + qbyte noise1[128][128], noise2[128][128], noise3[128][128], data[128][128][4]; + explosiontexturepool = R_AllocTexturePool(); + fractalnoise(&noise1[0][0], 128, 32); + fractalnoise(&noise2[0][0], 128, 4); + fractalnoise(&noise3[0][0], 128, 4); for (y = 0;y < 128;y++) { for (x = 0;x < 128;x++) { int j, r, g, b, a; - j = noise1[y][x] * 3 - 128; + j = (noise1[y][x] * noise2[y][x]) * 3 / 256 - 128; r = (j * 512) / 256; g = (j * 256) / 256; b = (j * 128) / 256; - a = noise2[y][x]; + a = noise3[y][x] * 3 - 128; data[y][x][0] = bound(0, r, 255); data[y][x][1] = bound(0, g, 255); data[y][x][2] = bound(0, b, 255); data[y][x][3] = bound(0, a, 255); } } - explosiontexture = GL_LoadTexture ("explosiontexture", 128, 128, &data[0][0][0], true, true, 4); + explosiontexture = R_LoadTexture2D(explosiontexturepool, "explosiontexture", 128, 128, &data[0][0][0], TEXTYPE_RGBA, TEXF_MIPMAP | TEXF_ALPHA | TEXF_PRECACHE, NULL); for (y = 0;y < 128;y++) for (x = 0;x < 128;x++) data[y][x][0] = data[y][x][1] = data[y][x][2] = 255; - explosiontexturefog = GL_LoadTexture ("explosiontexturefog", 128, 128, &data[0][0][0], true, true, 4); + explosiontexturefog = R_LoadTexture2D(explosiontexturepool, "explosiontexturefog", 128, 128, &data[0][0][0], TEXTYPE_RGBA, TEXF_MIPMAP | TEXF_ALPHA | TEXF_PRECACHE, NULL); + // note that explosions survive the restart +} + +static void r_explosion_shutdown(void) +{ + R_FreeTexturePool(&explosiontexturepool); +} + +static void r_explosion_newmap(void) +{ + memset(explosion, 0, sizeof(explosion)); } -void r_explosion_shutdown() +static int R_ExplosionVert(int column, int row) { + int i; + float yaw, pitch; + // top and bottom rows are all one position... + if (row == 0 || row == EXPLOSIONGRID) + column = 0; + i = row * (EXPLOSIONGRID + 1) + column; + yaw = ((double) column / EXPLOSIONGRID) * M_PI * 2; + pitch = (((double) row / EXPLOSIONGRID) - 0.5) * M_PI; + explosionpoint[i][0] = cos(yaw) * cos(pitch); + explosionpoint[i][1] = sin(yaw) * cos(pitch); + explosionpoint[i][2] = 1 * -sin(pitch); + explosiontexcoord2f[i][0] = (float) column / (float) EXPLOSIONGRID; + explosiontexcoord2f[i][1] = (float) row / (float) EXPLOSIONGRID; + explosionnoiseindex[i] = (row % EXPLOSIONGRID) * EXPLOSIONGRID + (column % EXPLOSIONGRID); + return i; } -void R_Explosion_Init() +void R_Explosion_Init(void) { int i, x, y; i = 0; - for (y = 0;y < EXPLOSIONBANDS;y++) + for (y = 0;y < EXPLOSIONGRID;y++) { - for (x = 0;x < EXPLOSIONSEGMENTS;x++) + for (x = 0;x < EXPLOSIONGRID;x++) { explosiontris[i][0] = R_ExplosionVert(x , y ); explosiontris[i][1] = R_ExplosionVert(x + 1, y ); @@ -120,143 +134,130 @@ void R_Explosion_Init() i++; } } - for (i = 0;i < EXPLOSIONVERTS;i++) - { - explosionspherevert[i][0] = explosionpoint[i][0] * EXPLOSIONSTARTRADIUS; - explosionspherevert[i][1] = explosionpoint[i][1] * EXPLOSIONSTARTRADIUS; - explosionspherevert[i][2] = explosionpoint[i][2] * EXPLOSIONSTARTRADIUS; - explosionspherevertvel[i][0] = explosionpoint[i][0] * EXPLOSIONSTARTVELOCITY; - explosionspherevertvel[i][1] = explosionpoint[i][1] * EXPLOSIONSTARTVELOCITY; - explosionspherevertvel[i][2] = explosionpoint[i][2] * EXPLOSIONSTARTVELOCITY; - } Cvar_RegisterVariable(&r_explosionclip); + Cvar_RegisterVariable(&r_drawexplosions); - R_RegisterModule("R_Explosions", r_explosion_start, r_explosion_shutdown); + R_RegisterModule("R_Explosions", r_explosion_start, r_explosion_shutdown, r_explosion_newmap); } void R_NewExplosion(vec3_t org) { int i, j; - for (i = 0;i < MAX_EXPLOSIONS;i++) + float dist, n; + explosion_t *e; + trace_t trace; + qbyte noise[EXPLOSIONGRID*EXPLOSIONGRID]; + fractalnoisequick(noise, EXPLOSIONGRID, 4); // adjust noise grid size according to explosion + for (i = 0, e = explosion;i < MAX_EXPLOSIONS;i++, e++) { - if (explosion[i].alpha <= 0.0f) + if (cl.time >= e->endtime) { - explosion[i].alpha = EXPLOSIONFADESTART; + e->starttime = cl.time; + e->endtime = cl.time + cl_explosions_lifetime.value; + e->time = e->starttime; + e->alpha = cl_explosions_alpha_start.value; + e->fade = (cl_explosions_alpha_start.value - cl_explosions_alpha_end.value) / cl_explosions_lifetime.value; + e->clipping = r_explosionclip.integer != 0; + VectorCopy(org, e->origin); for (j = 0;j < EXPLOSIONVERTS;j++) { - explosion[i].vert[j][0] = explosionspherevert[j][0] + org[0]; - explosion[i].vert[j][1] = explosionspherevert[j][1] + org[1]; - explosion[i].vert[j][2] = explosionspherevert[j][2] + org[2]; - explosion[i].vertvel[j][0] = explosionspherevertvel[j][0]; - explosion[i].vertvel[j][1] = explosionspherevertvel[j][1]; - explosion[i].vertvel[j][2] = explosionspherevertvel[j][2]; + // calculate start origin and velocity + n = noise[explosionnoiseindex[j]] * (1.0f / 255.0f) + 0.5; + dist = n * cl_explosions_size_start.value; + VectorMA(e->origin, dist, explosionpoint[j], e->vert[j]); + dist = n * (cl_explosions_size_end.value - cl_explosions_size_start.value) / cl_explosions_lifetime.value; + VectorScale(explosionpoint[j], dist, e->vertvel[j]); + // clip start origin + if (e->clipping) + { + trace = CL_TraceBox(e->origin, vec3_origin, vec3_origin, e->vert[j], true, NULL, SUPERCONTENTS_SOLID, false); + VectorCopy(trace.endpos, e->vert[i]); + } } break; } } } -void R_DrawExplosion(explosion_t *e) +static void R_DrawExplosionCallback(const void *calldata1, int calldata2) { - int i, index, *indexlist = &explosiontris[0][0], alpha = bound(0, e->alpha * 255.0f, 255); - float s = cl.time * 1, t = cl.time * 0.75; - s -= (int) s; - t -= (int) t; - /* - glColor4f(1,1,1,e->alpha); - glDisable(GL_TEXTURE_2D); -// glBindTexture(GL_TEXTURE_2D, explosiontexture); - if (gl_vertexarrays.value) - { - qglVertexPointer(3, GL_FLOAT, 0, (float *) &e->vert[0][0]); -// qglTexCoordPointer(2, GL_FLOAT, 0, (float *) &explosiontexcoords[0][0]); - glEnableClientState(GL_VERTEX_ARRAY); -// glEnableClientState(GL_TEXTURE_COORD_ARRAY); - qglDrawElements(GL_TRIANGLES, EXPLOSIONTRIS, GL_UNSIGNED_INT, indexlist); -// glDisableClientState(GL_TEXTURE_COORD_ARRAY); - glDisableClientState(GL_VERTEX_ARRAY); - } - else - { - glBegin(GL_TRIANGLES); - for (i = 0;i < EXPLOSIONTRIS * 3;i++) - { - index = *indexlist++; -// glTexCoord2fv(explosiontexcoords[index]); - glVertex3fv(e->vert[index]); - } - glEnd(); - } - glEnable(GL_TEXTURE_2D); - */ - for (i = 0;i < EXPLOSIONTRIS;i++) - { - transpolybegin(explosiontexture, 0, explosiontexturefog, TPOLYTYPE_ALPHA); - 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); - 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); - 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); - transpolyend(); - } + int numtriangles, numverts; + float alpha; + rmeshstate_t m; + const explosion_t *e; + e = calldata1; + + GL_BlendFunc(GL_SRC_ALPHA, GL_ONE); + GL_DepthMask(false); + GL_DepthTest(true); + R_Mesh_Matrix(&r_identitymatrix); + + numtriangles = EXPLOSIONTRIS; + numverts = EXPLOSIONVERTS; + alpha = e->alpha; + + memset(&m, 0, sizeof(m)); + m.tex[0] = R_GetTexture(explosiontexture); + m.pointer_texcoord[0] = explosiontexcoord2f[0]; + m.pointer_vertex = e->vert[0]; + R_Mesh_State(&m); + + GL_Color(alpha, alpha, alpha, 1); + + GL_LockArrays(0, numverts); + R_Mesh_Draw(0, numverts, numtriangles, explosiontris[0]); + GL_LockArrays(0, 0); } -void R_MoveExplosion(explosion_t *e, float frametime) +static void R_MoveExplosion(explosion_t *e) { int i; - vec3_t end; - e->alpha -= frametime * EXPLOSIONFADERATE; + float dot, end[3], frametime; + trace_t trace; + + frametime = cl.time - e->time; + e->time = cl.time; + e->alpha = e->alpha - (e->fade * frametime); for (i = 0;i < EXPLOSIONVERTS;i++) { if (e->vertvel[i][0] || e->vertvel[i][1] || e->vertvel[i][2]) { - end[0] = e->vert[i][0] + frametime * e->vertvel[i][0]; - end[1] = e->vert[i][1] + frametime * e->vertvel[i][1]; - end[2] = e->vert[i][2] + frametime * e->vertvel[i][2]; - if (r_explosionclip.value) + VectorMA(e->vert[i], frametime, e->vertvel[i], end); + if (e->clipping) { - float f, dot; - vec3_t impact, normal; - f = TraceLine(e->vert[i], end, impact, normal); - VectorCopy(impact, e->vert[i]); - if (f < 1) + trace = CL_TraceBox(e->vert[i], vec3_origin, vec3_origin, end, true, NULL, SUPERCONTENTS_SOLID, false); + if (trace.fraction < 1) { // clip velocity against the wall - dot = -DotProduct(e->vertvel[i], normal); - e->vertvel[i][0] += normal[0] * dot; - e->vertvel[i][1] += normal[1] * dot; - e->vertvel[i][2] += normal[2] * dot; + dot = -DotProduct(e->vertvel[i], trace.plane.normal); + VectorMA(e->vertvel[i], dot, trace.plane.normal, e->vertvel[i]); } + VectorCopy(trace.endpos, e->vert[i]); } else - { VectorCopy(end, e->vert[i]); - } } } } -void R_MoveExplosions() + +void R_MoveExplosions(void) { int i; - float frametime; - frametime = cl.time - cl.oldtime; for (i = 0;i < MAX_EXPLOSIONS;i++) - { - if (explosion[i].alpha > 0.0f) - { - R_MoveExplosion(&explosion[i], frametime); - } - } + if (cl.time < explosion[i].endtime) + R_MoveExplosion(&explosion[i]); } -void R_DrawExplosions() +void R_DrawExplosions(void) { int i; + + if (!r_drawexplosions.integer) + return; for (i = 0;i < MAX_EXPLOSIONS;i++) - { - if (explosion[i].alpha > 0.0f) - { - R_DrawExplosion(&explosion[i]); - } - } + if (r_refdef.time < explosion[i].endtime) + R_MeshQueue_AddTransparent(explosion[i].origin, R_DrawExplosionCallback, &explosion[i], 0); } +