]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - cl_particles.c
- Got rid of all the FILE* stuff in the FS code, relying on low-level
[xonotic/darkplaces.git] / cl_particles.c
index c185062e58a7a3d8b4978267b925599c82ec9d69..3d129b61f4081ff6f3663e67d23445f1458d8112 100644 (file)
@@ -180,7 +180,7 @@ float CL_TraceLine (vec3_t start, vec3_t end, vec3_t impact, vec3_t normal, int
 
 typedef enum
 {
-       pt_dead, pt_static, pt_rain, pt_bubble, pt_blood, pt_grow, pt_decal, pt_decalfade, pt_ember
+       pt_dead, pt_static, pt_rain, pt_bubble, pt_blood, pt_grow, pt_decal, pt_ember
 }
 ptype_t;
 
@@ -327,6 +327,7 @@ void CL_Particles_Init (void)
 {
        int             i;
 
+// COMMANDLINEOPTION: Client: -particles <number> changes maximum number of particles at once, default 32768
        i = COM_CheckParm ("-particles");
 
        if (i && i < com_argc - 1)
@@ -370,6 +371,15 @@ void CL_Particles_Init (void)
        CL_Particles_Clear();
 }
 
+void CL_Particles_Shutdown (void)
+{
+#ifdef WORKINGLQUAKE
+       // No clue what to do here...
+#else
+       Mem_FreePool (&cl_part_mempool);
+#endif
+}
+
 // list of all 26 parameters:
 // ptype - any of the pt_ enum values (pt_static, pt_blood, etc), see ptype_t near the top of this file
 // porientation - PARTICLE_ enum values (PARTICLE_BILLBOARD, PARTICLE_SPARK, etc)
@@ -781,46 +791,53 @@ void CL_RunParticleEffect (vec3_t org, vec3_t dir, int color, int count)
 CL_SparkShower
 ===============
 */
-void CL_SparkShower (vec3_t org, vec3_t dir, int count)
+void CL_SparkShower (vec3_t org, vec3_t dir, int count, vec_t gravityscale)
 {
-       vec3_t org2, org3;
        int k;
 
-       if (cl_stainmaps.integer)
-               R_Stain(org, 32, 96, 96, 96, 24, 128, 128, 128, 24);
-       CL_SpawnDecalParticleForPoint(org, 6, 3, 255, tex_bulletdecal[rand()&7], 0xFFFFFF, 0xFFFFFF);
-
        if (!cl_particles.integer) return;
 
-       if (cl_particles_bulletimpacts.integer)
+       if (cl_particles_sparks.integer)
        {
-               // smoke puff
-               if (cl_particles_smoke.integer)
+               // sparks
+               count *= cl_particles_quality.value;
+               while(count--)
                {
-                       k = count * 0.25 * cl_particles_quality.value;
-                       while(k--)
-                       {
-                               org2[0] = org[0] + 0.125f * lhrandom(-count, count);
-                               org2[1] = org[1] + 0.125f * lhrandom(-count, count);
-                               org2[2] = org[2] + 0.125f * lhrandom(-count, count);
-                               CL_TraceLine(org, org2, org3, NULL, true, NULL, SUPERCONTENTS_SOLID);
-                               particle(pt_grow, PARTICLE_BILLBOARD, 0x101010, 0x202020, tex_smoke[rand()&7], true, PBLEND_ADD, 3, 3, (1.0f / cl_particles_quality.value) * 255, (1.0f / cl_particles_quality.value) * 1024, 9999, -0.2, 0, org3[0], org3[1], org3[2], lhrandom(-8, 8), lhrandom(-8, 8), lhrandom(0, 16), 15, 0, 0, 0, 0.2, 0);
-                       }
+                       k = particlepalette[0x68 + (rand() & 7)];
+                       particle(pt_static, PARTICLE_SPARK, k, k, tex_particle, false, PBLEND_ADD, 0.4f, 0.015f, (1.0f / cl_particles_quality.value) * lhrandom(64, 255), (1.0f / cl_particles_quality.value) * 512, 9999, gravityscale, 0, org[0], org[1], org[2], lhrandom(-64, 64) + dir[0], lhrandom(-64, 64) + dir[1], lhrandom(0, 128) + dir[2], 0, 0, 0, 0, 0, 0);
                }
+       }
+}
+
+void CL_Smoke (vec3_t org, vec3_t dir, int count)
+{
+       vec3_t org2, org3;
+       int k;
+
+       if (!cl_particles.integer) return;
 
-               if (cl_particles_sparks.integer)
+       // smoke puff
+       if (cl_particles_smoke.integer)
+       {
+               k = count * 0.25 * cl_particles_quality.value;
+               while(k--)
                {
-                       // sparks
-                       count *= cl_particles_quality.value;
-                       while(count--)
-                       {
-                               k = particlepalette[0x68 + (rand() & 7)];
-                               particle(pt_static, PARTICLE_SPARK, k, k, tex_particle, false, PBLEND_ADD, 0.4f, 0.015f, (1.0f / cl_particles_quality.value) * lhrandom(64, 255), (1.0f / cl_particles_quality.value) * 512, 9999, 1, 0, org[0], org[1], org[2], lhrandom(-64, 64) + dir[0], lhrandom(-64, 64) + dir[1], lhrandom(0, 128) + dir[2], 0, 0, 0, 0, 0.2, 0);
-                       }
+                       org2[0] = org[0] + 0.125f * lhrandom(-count, count);
+                       org2[1] = org[1] + 0.125f * lhrandom(-count, count);
+                       org2[2] = org[2] + 0.125f * lhrandom(-count, count);
+                       CL_TraceLine(org, org2, org3, NULL, true, NULL, SUPERCONTENTS_SOLID);
+                       particle(pt_grow, PARTICLE_BILLBOARD, 0x101010, 0x202020, tex_smoke[rand()&7], true, PBLEND_ADD, 3, 3, (1.0f / cl_particles_quality.value) * 255, (1.0f / cl_particles_quality.value) * 1024, 9999, 0, 0, org3[0], org3[1], org3[2], lhrandom(-8, 8), lhrandom(-8, 8), lhrandom(-8, 8), 15, 0, 0, 0, 0, 0);
                }
        }
 }
 
+void CL_BulletMark (vec3_t org)
+{
+       if (cl_stainmaps.integer)
+               R_Stain(org, 32, 96, 96, 96, 24, 128, 128, 128, 24);
+       CL_SpawnDecalParticleForPoint(org, 6, 3, 255, tex_bulletdecal[rand()&7], 0xFFFFFF, 0xFFFFFF);
+}
+
 void CL_PlasmaBurn (vec3_t org)
 {
        if (cl_stainmaps.integer)
@@ -1124,6 +1141,7 @@ void CL_RocketTrail (vec3_t start, vec3_t end, int type, int color, entity_t *en
        if (speed)
                speed = 1.0f / speed;
        VectorSubtract(ent->state_current.origin, ent->state_previous.origin, vel);
+       color = particlepalette[color];
 #endif
        VectorScale(vel, speed, vel);
 
@@ -1340,8 +1358,8 @@ void CL_MoveParticles (void)
                                        Matrix4x4_Transform3x3(&hitent->inversematrix, normal, p->relativedirection);
                                        VectorAdd(p->relativeorigin, p->relativedirection, p->relativeorigin);
 #endif
-                                       p->time2 = cl.time + cl_decals_time.value;
-                                       p->die = p->time2 + cl_decals_fadetime.value;
+                                       p->time2 = cl.time;
+                                       p->die = p->time2 + cl_decals_time.value + cl_decals_fadetime.value;
                                        p->alphafade = 0;
                                        VectorCopy(normal, p->vel2);
                                        VectorClear(p->vel);
@@ -1434,22 +1452,7 @@ void CL_MoveParticles (void)
                                p->scaley += frametime * p->time2;
                                break;
                        case pt_decal:
-#ifndef WORKINGLQUAKE
-                               if (p->owner->model == p->ownermodel)
-                               {
-                                       Matrix4x4_Transform(&p->owner->matrix, p->relativeorigin, p->org);
-                                       Matrix4x4_Transform3x3(&p->owner->matrix, p->relativedirection, p->vel2);
-                                       if (cl.time > p->time2)
-                                       {
-                                               p->alphafade = p->alpha / (p->die - cl.time);
-                                               p->type = pt_decalfade;
-                                       }
-                               }
-                               else
-                                       p->type = pt_dead;
-#endif
-                               break;
-                       case pt_decalfade:
+                               p->alphafade = cl.time > (p->time2 + cl_decals_time.value) ? (p->alpha / cl_decals_fadetime.value) : 0;
 #ifndef WORKINGLQUAKE
                                if (p->owner->model == p->ownermodel)
                                {
@@ -1497,7 +1500,7 @@ static particletexture_t particletexture[MAX_PARTICLETEXTURES];
 
 static cvar_t r_drawparticles = {0, "r_drawparticles", "1"};
 
-#define PARTICLETEXTURESIZE 32
+#define PARTICLETEXTURESIZE 64
 #define PARTICLEFONTSIZE (PARTICLETEXTURESIZE*8)
 
 static qbyte shadebubble(float dx, float dy, vec3_t light)
@@ -1626,10 +1629,10 @@ static void R_InitParticleTexture (void)
                        m = 0;
                        for (y = 0;y < PARTICLETEXTURESIZE;y++)
                        {
-                               dy = (y - 0.5f*PARTICLETEXTURESIZE) / (PARTICLETEXTURESIZE*0.5f+1);
+                               dy = (y - 0.5f*PARTICLETEXTURESIZE) / (PARTICLETEXTURESIZE*0.5f-1);
                                for (x = 0;x < PARTICLETEXTURESIZE;x++)
                                {
-                                       dx = (x - 0.5f*PARTICLETEXTURESIZE) / (PARTICLETEXTURESIZE*0.5f+1);
+                                       dx = (x - 0.5f*PARTICLETEXTURESIZE) / (PARTICLETEXTURESIZE*0.5f-1);
                                        d = (noise2[y][x] - 128) * 3 + 192;
                                        if (d > 0)
                                                d = d * (1-(dx*dx+dy*dy));
@@ -1653,10 +1656,10 @@ static void R_InitParticleTexture (void)
                f2 = 255.0f * ((15.0f - i) / 15.0f);
                for (y = 0;y < PARTICLETEXTURESIZE;y++)
                {
-                       dy = (y - 0.5f*PARTICLETEXTURESIZE) / (PARTICLETEXTURESIZE*0.5f+1);
+                       dy = (y - 0.5f*PARTICLETEXTURESIZE) / (PARTICLETEXTURESIZE*0.5f-1);
                        for (x = 0;x < PARTICLETEXTURESIZE;x++)
                        {
-                               dx = (x - 0.5f*PARTICLETEXTURESIZE) / (PARTICLETEXTURESIZE*0.5f+1);
+                               dx = (x - 0.5f*PARTICLETEXTURESIZE) / (PARTICLETEXTURESIZE*0.5f-1);
                                f = f2 * (1.0 - 4.0f * fabs(radius - sqrt(dx*dx+dy*dy)));
                                data[y][x][3] = (int) (bound(0.0f, f, 255.0f));
                        }
@@ -1668,10 +1671,10 @@ static void R_InitParticleTexture (void)
        memset(&data[0][0][0], 255, sizeof(data));
        for (y = 0;y < PARTICLETEXTURESIZE;y++)
        {
-               dy = (y - 0.5f*PARTICLETEXTURESIZE) / (PARTICLETEXTURESIZE*0.5f+1);
+               dy = (y - 0.5f*PARTICLETEXTURESIZE) / (PARTICLETEXTURESIZE*0.5f-1);
                for (x = 0;x < PARTICLETEXTURESIZE;x++)
                {
-                       dx = (x - 0.5f*PARTICLETEXTURESIZE) / (PARTICLETEXTURESIZE*0.5f+1);
+                       dx = (x - 0.5f*PARTICLETEXTURESIZE) / (PARTICLETEXTURESIZE*0.5f-1);
                        d = 256 * (1 - (dx*dx+dy*dy));
                        d = bound(0, d, 255);
                        data[y][x][3] = (qbyte) d;
@@ -1685,7 +1688,7 @@ static void R_InitParticleTexture (void)
        VectorNormalize(light);
        for (y = 0;y < PARTICLETEXTURESIZE;y++)
        {
-               dy = (y - 0.5f*PARTICLETEXTURESIZE) / (PARTICLETEXTURESIZE*0.5f+1);
+               dy = (y - 0.5f*PARTICLETEXTURESIZE) / (PARTICLETEXTURESIZE*0.5f-1);
                // stretch upper half of bubble by +50% and shrink lower half by -50%
                // (this gives an elongated teardrop shape)
                if (dy > 0.5f)
@@ -1694,7 +1697,7 @@ static void R_InitParticleTexture (void)
                        dy = (dy - 0.5f) / 1.5f;
                for (x = 0;x < PARTICLETEXTURESIZE;x++)
                {
-                       dx = (x - 0.5f*PARTICLETEXTURESIZE) / (PARTICLETEXTURESIZE*0.5f+1);
+                       dx = (x - 0.5f*PARTICLETEXTURESIZE) / (PARTICLETEXTURESIZE*0.5f-1);
                        // shrink bubble width to half
                        dx *= 2.0f;
                        data[y][x][3] = shadebubble(dx, dy, light);
@@ -1708,10 +1711,10 @@ static void R_InitParticleTexture (void)
        VectorNormalize(light);
        for (y = 0;y < PARTICLETEXTURESIZE;y++)
        {
-               dy = (y - 0.5f*PARTICLETEXTURESIZE) / (PARTICLETEXTURESIZE*0.5f+1);
+               dy = (y - 0.5f*PARTICLETEXTURESIZE) / (PARTICLETEXTURESIZE*0.5f-1);
                for (x = 0;x < PARTICLETEXTURESIZE;x++)
                {
-                       dx = (x - 0.5f*PARTICLETEXTURESIZE) / (PARTICLETEXTURESIZE*0.5f+1);
+                       dx = (x - 0.5f*PARTICLETEXTURESIZE) / (PARTICLETEXTURESIZE*0.5f-1);
                        data[y][x][3] = shadebubble(dx, dy, light);
                }
        }
@@ -1759,6 +1762,11 @@ static void R_InitParticleTexture (void)
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
 #else
+
+#if 0
+       Image_WriteTGARGBA ("particles/particlefont.tga", PARTICLEFONTSIZE, PARTICLEFONTSIZE, particletexturedata);
+#endif
+
        particlefonttexture = loadtextureimage(particletexturepool, "particles/particlefont.tga", 0, 0, false, TEXF_ALPHA | TEXF_PRECACHE);
        if (!particlefonttexture)
                particlefonttexture = R_LoadTexture2D(particletexturepool, "particlefont", PARTICLEFONTSIZE, PARTICLEFONTSIZE, particletexturedata, TEXTYPE_RGBA, TEXF_ALPHA | TEXF_PRECACHE, NULL);
@@ -1770,16 +1778,20 @@ static void R_InitParticleTexture (void)
        m = 0;
        for (y = 0;y < 64;y++)
        {
-               dy = (y - 0.5f*64) / (64*0.5f+1);
+               dy = (y - 0.5f*64) / (64*0.5f-1);
                for (x = 0;x < 16;x++)
                {
-                       dx = (x - 0.5f*16) / (16*0.5f+1);
-                       d = (1 - (dx*dx)) * noise3[y][x];
+                       dx = (x - 0.5f*16) / (16*0.5f-2);
+                       d = (1 - sqrt(fabs(dx))) * noise3[y][x];
                        data2[y][x][0] = data2[y][x][1] = data2[y][x][2] = (qbyte) bound(0, d, 255);
                        data2[y][x][3] = 255;
                }
        }
 
+#if 0
+       Image_WriteTGARGBA ("particles/nexbeam.tga", 64, 64, &data2[0][0][0]);
+#endif
+
        particletexture[tex_beam].texture = loadtextureimage(particletexturepool, "particles/nexbeam.tga", 0, 0, false, TEXF_ALPHA | TEXF_PRECACHE);
        if (!particletexture[tex_beam].texture)
                particletexture[tex_beam].texture = R_LoadTexture2D(particletexturepool, "nexbeam", 16, 64, &data2[0][0][0], TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
@@ -1946,8 +1958,8 @@ void R_DrawParticleCallback(const void *calldata1, int calldata2)
                R_CalcBeam_Vertex3f(particle_vertex3f, p->org, p->vel2, p->scalex);
                VectorSubtract(p->vel2, p->org, up);
                VectorNormalizeFast(up);
-               v[0] = DotProduct(p->org, up) * (1.0f / 64.0f) - cl.time * 0.25;
-               v[1] = DotProduct(p->vel2, up) * (1.0f / 64.0f) - cl.time * 0.25;
+               v[0] = DotProduct(p->org, up) * (1.0f / 64.0f);
+               v[1] = DotProduct(p->vel2, up) * (1.0f / 64.0f);
                particle_texcoord2f[0] = 1;particle_texcoord2f[1] = v[0];
                particle_texcoord2f[2] = 0;particle_texcoord2f[3] = v[0];
                particle_texcoord2f[4] = 0;particle_texcoord2f[5] = v[1];
@@ -2011,7 +2023,12 @@ void R_DrawParticles (void)
                {
                        c_particles++;
                        if (DotProduct(p->org, r_viewforward) >= minparticledist || p->orientation == PARTICLE_BEAM)
-                               R_MeshQueue_AddTransparent(p->org, R_DrawParticleCallback, p, 0);
+                       {
+                               if (p->type == pt_decal)
+                                       R_DrawParticleCallback(p, 0);
+                               else
+                                       R_MeshQueue_AddTransparent(p->org, R_DrawParticleCallback, p, 0);
+                       }
                }
        }
 #endif