X-Git-Url: http://de.git.xonotic.org/?p=xonotic%2Fdarkplaces.git;a=blobdiff_plain;f=r_explosion.c;h=11455498a4cedff2d97891ae0a9c330d3e6f1b2c;hp=7bf4e18328ff2be45168d11a996b179d359e5048;hb=85a33377d64ae8438e6582a7b8472f5a4bd41942;hpb=6824d8ddc8a43cae0609be5bbe8bee01fa1a4225 diff --git a/r_explosion.c b/r_explosion.c index 7bf4e183..11455498 100644 --- a/r_explosion.c +++ b/r_explosion.c @@ -21,13 +21,15 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "quakedef.h" #include "cl_collision.h" -#define MAX_EXPLOSIONS 64 +#ifdef MAX_EXPLOSIONS #define EXPLOSIONGRID 8 #define EXPLOSIONVERTS ((EXPLOSIONGRID+1)*(EXPLOSIONGRID+1)) #define EXPLOSIONTRIS (EXPLOSIONGRID*EXPLOSIONGRID*2) +static int numexplosions = 0; + static float explosiontexcoord2f[EXPLOSIONVERTS][2]; -static int explosiontris[EXPLOSIONTRIS][3]; +static unsigned short explosiontris[EXPLOSIONTRIS][3]; static int explosionnoiseindex[EXPLOSIONVERTS]; static vec3_t explosionpoint[EXPLOSIONVERTS]; @@ -48,18 +50,23 @@ explosion_t; static explosion_t explosion[MAX_EXPLOSIONS]; static rtexture_t *explosiontexture; -static rtexture_t *explosiontexturefog; +//static rtexture_t *explosiontexturefog; static rtexturepool_t *explosiontexturepool; +#endif -cvar_t r_explosionclip = {CVAR_SAVE, "r_explosionclip", "1"}; -static cvar_t r_drawexplosions = {0, "r_drawexplosions", "1"}; +cvar_t r_explosionclip = {CVAR_SAVE, "r_explosionclip", "1", "enables collision detection for explosion shell (so that it flattens against walls and floors)"}; +#ifdef MAX_EXPLOSIONS +static cvar_t r_drawexplosions = {0, "r_drawexplosions", "1", "enables rendering of explosion shells (see also cl_particles_explosions_shell)"}; +//extern qboolean r_loadfog; static void r_explosion_start(void) { int x, y; - unsigned char noise1[128][128], noise2[128][128], noise3[128][128], data[128][128][4]; + static unsigned char noise1[128][128], noise2[128][128], noise3[128][128], data[128][128][4]; explosiontexturepool = R_AllocTexturePool(); + explosiontexture = NULL; + //explosiontexturefog = NULL; fractalnoise(&noise1[0][0], 128, 32); fractalnoise(&noise2[0][0], 128, 4); fractalnoise(&noise3[0][0], 128, 4); @@ -73,17 +80,20 @@ static void r_explosion_start(void) g = (j * 256) / 256; b = (j * 128) / 256; a = noise3[y][x] * 3 - 128; - data[y][x][0] = bound(0, r, 255); + data[y][x][2] = bound(0, r, 255); data[y][x][1] = bound(0, g, 255); - data[y][x][2] = bound(0, b, 255); + data[y][x][0] = bound(0, b, 255); data[y][x][3] = bound(0, a, 255); } } - 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 = R_LoadTexture2D(explosiontexturepool, "explosiontexturefog", 128, 128, &data[0][0][0], TEXTYPE_RGBA, TEXF_MIPMAP | TEXF_ALPHA | TEXF_PRECACHE, NULL); + explosiontexture = R_LoadTexture2D(explosiontexturepool, "explosiontexture", 128, 128, &data[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_ALPHA | TEXF_FORCELINEAR, -1, NULL); +// if (r_loadfog) +// { +// 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 = R_LoadTexture2D(explosiontexturepool, "explosiontexture_fog", 128, 128, &data[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_ALPHA | TEXF_FORCELINEAR, NULL); +// } // note that explosions survive the restart } @@ -94,6 +104,7 @@ static void r_explosion_shutdown(void) static void r_explosion_newmap(void) { + numexplosions = 0; memset(explosion, 0, sizeof(explosion)); } @@ -115,9 +126,11 @@ static int R_ExplosionVert(int column, int row) explosionnoiseindex[i] = (row % EXPLOSIONGRID) * EXPLOSIONGRID + (column % EXPLOSIONGRID); return i; } +#endif void R_Explosion_Init(void) { +#ifdef MAX_EXPLOSIONS int i, x, y; i = 0; for (y = 0;y < EXPLOSIONGRID;y++) @@ -135,14 +148,18 @@ void R_Explosion_Init(void) } } +#endif Cvar_RegisterVariable(&r_explosionclip); +#ifdef MAX_EXPLOSIONS Cvar_RegisterVariable(&r_drawexplosions); - R_RegisterModule("R_Explosions", r_explosion_start, r_explosion_shutdown, r_explosion_newmap); + R_RegisterModule("R_Explosions", r_explosion_start, r_explosion_shutdown, r_explosion_newmap, NULL, NULL); +#endif } -void R_NewExplosion(vec3_t org) +void R_NewExplosion(const vec3_t org) { +#ifdef MAX_EXPLOSIONS int i, j; float dist, n; explosion_t *e; @@ -151,8 +168,9 @@ void R_NewExplosion(vec3_t org) fractalnoisequick(noise, EXPLOSIONGRID, 4); // adjust noise grid size according to explosion for (i = 0, e = explosion;i < MAX_EXPLOSIONS;i++, e++) { - if (cl.time >= e->endtime) + if (!e->alpha) { + numexplosions = max(numexplosions, i + 1); e->starttime = cl.time; e->endtime = cl.time + cl_explosions_lifetime.value; e->time = e->starttime; @@ -171,43 +189,39 @@ void R_NewExplosion(vec3_t org) // clip start origin if (e->clipping) { - trace = CL_TraceBox(e->origin, vec3_origin, vec3_origin, e->vert[j], true, NULL, SUPERCONTENTS_SOLID, false); + trace = CL_TraceLine(e->origin, e->vert[j], MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, 0, 0, collision_extendmovelength.value, true, false, NULL, false, false); VectorCopy(trace.endpos, e->vert[i]); } } break; } } +#endif } -static void R_DrawExplosionCallback(const void *calldata1, int calldata2) +#ifdef MAX_EXPLOSIONS +static void R_DrawExplosion_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist) { - int numtriangles, numverts; - float alpha; - rmeshstate_t m; - const explosion_t *e; - e = (explosion_t *)calldata1; - + int surfacelistindex = 0; + const int numtriangles = EXPLOSIONTRIS, numverts = EXPLOSIONVERTS; GL_BlendFunc(GL_SRC_ALPHA, GL_ONE); GL_DepthMask(false); + GL_DepthRange(0, 1); + GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset); 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_CullFace(r_refdef.view.cullface_back); + R_EntityMatrix(&identitymatrix); - GL_Color(alpha, alpha, alpha, 1); - - GL_LockArrays(0, numverts); - R_Mesh_Draw(0, numverts, numtriangles, explosiontris[0]); - GL_LockArrays(0, 0); +// R_Mesh_ResetTextureState(); + R_SetupShader_Generic(explosiontexture, false, false, false); + for (surfacelistindex = 0;surfacelistindex < numsurfaces;surfacelistindex++) + { + const explosion_t *e = explosion + surfacelist[surfacelistindex]; + // FIXME: this can't properly handle r_refdef.view.colorscale > 1 + GL_Color(e->alpha * r_refdef.view.colorscale, e->alpha * r_refdef.view.colorscale, e->alpha * r_refdef.view.colorscale, 1); + R_Mesh_PrepareVertices_Generic_Arrays(numverts, e->vert[0], NULL, explosiontexcoord2f[0]); + R_Mesh_Draw(0, numverts, 0, numtriangles, NULL, NULL, 0, explosiontris[0], NULL, 0); + } } static void R_MoveExplosion(explosion_t *e) @@ -219,6 +233,11 @@ static void R_MoveExplosion(explosion_t *e) frametime = cl.time - e->time; e->time = cl.time; e->alpha = e->alpha - (e->fade * frametime); + if (e->alpha < 0 || cl.time > e->endtime) + { + e->alpha = 0; + return; + } for (i = 0;i < EXPLOSIONVERTS;i++) { if (e->vertvel[i][0] || e->vertvel[i][1] || e->vertvel[i][2]) @@ -226,7 +245,7 @@ static void R_MoveExplosion(explosion_t *e) VectorMA(e->vert[i], frametime, e->vertvel[i], end); if (e->clipping) { - trace = CL_TraceBox(e->vert[i], vec3_origin, vec3_origin, end, true, NULL, SUPERCONTENTS_SOLID, false); + trace = CL_TraceLine(e->vert[i], end, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, 0, 0, collision_extendmovelength.value, true, false, NULL, false, false); if (trace.fraction < 1) { // clip velocity against the wall @@ -240,24 +259,27 @@ static void R_MoveExplosion(explosion_t *e) } } } - - -void R_MoveExplosions(void) -{ - int i; - for (i = 0;i < MAX_EXPLOSIONS;i++) - if (cl.time < explosion[i].endtime) - R_MoveExplosion(&explosion[i]); -} +#endif void R_DrawExplosions(void) { +#ifdef MAX_EXPLOSIONS int i; if (!r_drawexplosions.integer) return; - for (i = 0;i < MAX_EXPLOSIONS;i++) - if (r_refdef.time < explosion[i].endtime) - R_MeshQueue_AddTransparent(explosion[i].origin, R_DrawExplosionCallback, &explosion[i], 0); + + for (i = 0;i < numexplosions;i++) + { + if (explosion[i].alpha) + { + R_MoveExplosion(&explosion[i]); + if (explosion[i].alpha) + R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, explosion[i].origin, R_DrawExplosion_TransparentCallback, NULL, i, NULL); + } + } + while (numexplosions > 0 && explosion[i-1].alpha <= 0) + numexplosions--; +#endif }