X-Git-Url: http://de.git.xonotic.org/?p=xonotic%2Fdarkplaces.git;a=blobdiff_plain;f=r_explosion.c;h=48ce2ef3ec4e3566f524cd74b7085d4633aaff0d;hp=3f8daa4b8007d554510bc0367321687af6f4dc57;hb=50099d9c0934fe93646fa2792fa7a9657422333b;hpb=45bff1c2dd893d329c86aa043661187b86da6609 diff --git a/r_explosion.c b/r_explosion.c index 3f8daa4b..48ce2ef3 100644 --- a/r_explosion.c +++ b/r_explosion.c @@ -25,41 +25,40 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define EXPLOSIONGRID 8 #define EXPLOSIONVERTS ((EXPLOSIONGRID+1)*(EXPLOSIONGRID+1)) #define EXPLOSIONTRIS (EXPLOSIONGRID*EXPLOSIONGRID*2) -#define EXPLOSIONSTARTVELOCITY (256.0f) -#define EXPLOSIONFADESTART (1.5f) -#define EXPLOSIONFADERATE (3.0f) -float explosiontexcoords[EXPLOSIONVERTS][2]; -int explosiontris[EXPLOSIONTRIS][3]; -int explosionnoiseindex[EXPLOSIONVERTS]; -vec3_t explosionpoint[EXPLOSIONVERTS]; -vec3_t explosionspherevertvel[EXPLOSIONVERTS]; +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[MAX_EXPLOSIONS]; +static explosion_t explosion[MAX_EXPLOSIONS]; -rtexture_t *explosiontexture; -rtexture_t *explosiontexturefog; +static rtexture_t *explosiontexture; +static rtexture_t *explosiontexturefog; -rtexturepool_t *explosiontexturepool; +static rtexturepool_t *explosiontexturepool; -cvar_t r_explosionclip = {CVAR_SAVE, "r_explosionclip", "1"}; -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)"}; +static cvar_t r_drawexplosions = {0, "r_drawexplosions", "1", "enables rendering of explosion shells (see also cl_particles_explosions_shell)"}; -void r_explosion_start(void) +static void r_explosion_start(void) { int x, y; - qbyte noise1[128][128], noise2[128][128], noise3[128][128], data[128][128][4]; + unsigned char 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); @@ -80,43 +79,39 @@ void r_explosion_start(void) data[y][x][3] = bound(0, a, 255); } } - explosiontexture = R_LoadTexture (explosiontexturepool, "explosiontexture", 128, 128, &data[0][0][0], TEXTYPE_RGBA, TEXF_MIPMAP | TEXF_ALPHA | TEXF_PRECACHE); + 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_LoadTexture (explosiontexturepool, "explosiontexturefog", 128, 128, &data[0][0][0], TEXTYPE_RGBA, TEXF_MIPMAP | TEXF_ALPHA | TEXF_PRECACHE); + 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 } -void r_explosion_shutdown(void) +static void r_explosion_shutdown(void) { R_FreeTexturePool(&explosiontexturepool); } -void r_explosion_newmap(void) +static void r_explosion_newmap(void) { memset(explosion, 0, sizeof(explosion)); } -int R_ExplosionVert(int column, int row) +static int R_ExplosionVert(int column, int row) { int i; - float a, b, c; - i = row * (EXPLOSIONGRID + 1) + column; - a = row * M_PI * 2 / EXPLOSIONGRID; - b = column * M_PI * 2 / EXPLOSIONGRID; - c = cos(b); - explosionpoint[i][0] = cos(a) * c; - explosionpoint[i][1] = sin(a) * c; - explosionpoint[i][2] = -sin(b); - explosionspherevertvel[i][0] = explosionpoint[i][0] * EXPLOSIONSTARTVELOCITY; - explosionspherevertvel[i][1] = explosionpoint[i][1] * EXPLOSIONSTARTVELOCITY; - explosionspherevertvel[i][2] = explosionpoint[i][2] * EXPLOSIONSTARTVELOCITY; - explosiontexcoords[i][0] = (float) column / (float) EXPLOSIONGRID; - explosiontexcoords[i][1] = (float) row / (float) EXPLOSIONGRID; + 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; } @@ -146,151 +141,117 @@ void R_Explosion_Init(void) R_RegisterModule("R_Explosions", r_explosion_start, r_explosion_shutdown, r_explosion_newmap); } -void R_NewExplosion(vec3_t org) +void R_NewExplosion(const vec3_t org) { int i, j; - float dist; - qbyte noise[EXPLOSIONGRID*EXPLOSIONGRID]; + float dist, n; + explosion_t *e; + trace_t trace; + unsigned char noise[EXPLOSIONGRID*EXPLOSIONGRID]; fractalnoisequick(noise, EXPLOSIONGRID, 4); // adjust noise grid size according to explosion - for (i = 0;i < MAX_EXPLOSIONS;i++) + for (i = 0, e = explosion;i < MAX_EXPLOSIONS;i++, e++) { - if (explosion[i].alpha <= 0.01f) + if (!e->alpha) { - explosion[i].starttime = cl.time; - explosion[i].time = explosion[i].starttime - 0.1; - explosion[i].alpha = EXPLOSIONFADESTART; - VectorCopy(org, explosion[i].origin); + 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++) { - // calculate start - VectorCopy(explosion[i].origin, explosion[i].vert[j]); - // calculate velocity - dist = noise[explosionnoiseindex[j]] * (1.0f / 255.0f) + 0.5; - VectorScale(explosionspherevertvel[j], dist, explosion[i].vertvel[j]); + // 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_Move(e->origin, vec3_origin, vec3_origin, e->vert[j], MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, true, false, NULL, false); + VectorCopy(trace.endpos, e->vert[i]); + } } break; } } } -void R_DrawExplosion(explosion_t *e) +static void R_DrawExplosion_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist) { - int i; - float *c, *v, diff[3], centerdir[3], ifog, alpha, dist; - rmeshbufferinfo_t m; - + int surfacelistindex = 0; + const int numtriangles = EXPLOSIONTRIS, numverts = EXPLOSIONVERTS; + rmeshstate_t m; + 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); + GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces + R_Mesh_Matrix(&identitymatrix); + + R_Mesh_ColorPointer(NULL, 0, 0); memset(&m, 0, sizeof(m)); - m.transparent = true; - m.blendfunc1 = GL_SRC_ALPHA; - m.blendfunc2 = GL_ONE; - m.numtriangles = EXPLOSIONTRIS; - m.numverts = EXPLOSIONVERTS; m.tex[0] = R_GetTexture(explosiontexture); - if (R_Mesh_Draw_GetBuffer(&m, false)) + m.pointer_texcoord[0] = explosiontexcoord2f[0]; + R_Mesh_TextureState(&m); + for (surfacelistindex = 0;surfacelistindex < numsurfaces;surfacelistindex++) { - memcpy(m.index, explosiontris, m.numtriangles * sizeof(int[3])); - for (i = 0, v = m.vertex;i < m.numverts;i++, v += 4) - { - v[0] = e->vert[i][0]; - v[1] = e->vert[i][1]; - v[2] = e->vert[i][2]; - } - memcpy(m.texcoords[0], explosiontexcoords, m.numverts * sizeof(float[2])); - alpha = e->alpha; - VectorSubtract(r_origin, e->origin, centerdir); - VectorNormalizeFast(centerdir); - if (fogenabled) - { - for (i = 0, c = m.color;i < EXPLOSIONVERTS;i++, c += 4) - { - VectorSubtract(e->vert[i], e->origin, diff); - VectorNormalizeFast(diff); - dist = (DotProduct(diff, centerdir) * 6.0f - 4.0f) * alpha; - if (dist > 0) - { - // use inverse fog alpha - VectorSubtract(e->vert[i], r_origin, diff); - ifog = 1 - exp(fogdensity/DotProduct(diff,diff)); - dist = dist * ifog; - if (dist < 0) - dist = 0; - else - dist *= m.colorscale; - } - else - dist = 0; - c[0] = c[1] = c[2] = dist; - c[3] = 1; - } - } - else - { - for (i = 0, c = m.color;i < EXPLOSIONVERTS;i++, c += 4) - { - VectorSubtract(e->vert[i], e->origin, diff); - VectorNormalizeFast(diff); - dist = (DotProduct(diff, centerdir) * 6.0f - 4.0f) * alpha; - if (dist < 0) - dist = 0; - else - dist *= m.colorscale; - c[0] = c[1] = c[2] = dist; - c[3] = 1; - } - } + const explosion_t *e = explosion + surfacelist[surfacelistindex]; + R_Mesh_VertexPointer(e->vert[0], 0, 0); + // FIXME: fixed function path can't properly handle r_view.colorscale > 1 + GL_Color(e->alpha * r_view.colorscale, e->alpha * r_view.colorscale, e->alpha * r_view.colorscale, 1); + GL_LockArrays(0, numverts); + R_Mesh_Draw(0, numverts, numtriangles, explosiontris[0], 0, 0); + GL_LockArrays(0, 0); } } -void R_MoveExplosion(explosion_t *e) +static void R_MoveExplosion(explosion_t *e) { int i; - float dot, frictionscale, end[3], impact[3], normal[3], frametime; + float dot, end[3], frametime; + trace_t trace; frametime = cl.time - e->time; e->time = cl.time; - e->alpha = EXPLOSIONFADESTART - (cl.time - e->starttime) * EXPLOSIONFADERATE; - if (e->alpha <= 0.01f) + e->alpha = e->alpha - (e->fade * frametime); + if (e->alpha < 0 || cl.time > e->endtime) { - e->alpha = -1; + e->alpha = 0; return; } - frictionscale = 1 - frametime; - frictionscale = bound(0, frictionscale, 1); for (i = 0;i < EXPLOSIONVERTS;i++) { if (e->vertvel[i][0] || e->vertvel[i][1] || e->vertvel[i][2]) { - VectorScale(e->vertvel[i], frictionscale, e->vertvel[i]); VectorMA(e->vert[i], frametime, e->vertvel[i], end); - if (r_explosionclip.integer) + if (e->clipping) { - if (CL_TraceLine(e->vert[i], end, impact, normal, 0, true) < 1) + trace = CL_Move(e->vert[i], vec3_origin, vec3_origin, end, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, true, false, NULL, false); + if (trace.fraction < 1) { // clip velocity against the wall - dot = DotProduct(e->vertvel[i], normal) * -1.125f; - VectorMA(e->vertvel[i], dot, normal, e->vertvel[i]); + dot = -DotProduct(e->vertvel[i], trace.plane.normal); + VectorMA(e->vertvel[i], dot, trace.plane.normal, e->vertvel[i]); } - VectorCopy(impact, e->vert[i]); + VectorCopy(trace.endpos, e->vert[i]); } else VectorCopy(end, e->vert[i]); } } - for (i = 0;i < EXPLOSIONGRID;i++) - VectorCopy(e->vert[i * (EXPLOSIONGRID + 1)], e->vert[i * (EXPLOSIONGRID + 1) + EXPLOSIONGRID]); - memcpy(e->vert[EXPLOSIONGRID * (EXPLOSIONGRID + 1)], e->vert[0], sizeof(float[3]) * (EXPLOSIONGRID + 1)); } 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.01f) + if (explosion[i].alpha) R_MoveExplosion(&explosion[i]); } @@ -301,7 +262,7 @@ void R_DrawExplosions(void) if (!r_drawexplosions.integer) return; for (i = 0;i < MAX_EXPLOSIONS;i++) - if (explosion[i].alpha > 0.01f) - R_DrawExplosion(&explosion[i]); + if (explosion[i].alpha) + R_MeshQueue_AddTransparent(explosion[i].origin, R_DrawExplosion_TransparentCallback, NULL, i, NULL); }