]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - r_part.c
minor speedup to VectorNormalize #define's
[xonotic/darkplaces.git] / r_part.c
index 914e54ea029a5ea151e763526fa668bf259dcb4b..b443d834375d2279a5434f2d45fd3a576197acd5 100644 (file)
--- a/r_part.c
+++ b/r_part.c
@@ -20,7 +20,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 
 #include "quakedef.h"
 
-#define MAX_PARTICLES                  4096    // default max # of particles at one
+#define MAX_PARTICLES                  32768   // default max # of particles at one
                                                                                //  time
 #define ABSOLUTE_MIN_PARTICLES 512             // no fewer than this no matter what's
                                                                                //  on the command line
@@ -43,8 +43,17 @@ int                  r_numparticles;
 
 vec3_t                 r_pright, r_pup, r_ppn;
 
+// LordHavoc: reduced duplicate code, and allow particle allocation system independence
+#define ALLOCPARTICLE \
+       if (!free_particles)\
+               return;\
+       p = free_particles;\
+       free_particles = p->next;\
+       p->next = active_particles;\
+       active_particles = p;
+
 cvar_t r_particles = {"r_particles", "1"};
-cvar_t r_dynamicparticles = {"r_dynamicparticles", "1"};
+cvar_t r_dynamicparticles = {"r_dynamicparticles", "0", TRUE};
 
 void fractalnoise(char *noise, int size);
 void fractalnoise_zeroedge(char *noise, int size);
@@ -337,17 +346,13 @@ avelocities[0][i] = (rand()&255) * 0.01;
                forward[1] = cp*sy;
                forward[2] = -sp;
 
-               if (!free_particles)
-                       return;
-               p = free_particles;
-               free_particles = p->next;
-               p->next = active_particles;
-               active_particles = p;
+               ALLOCPARTICLE
 
+//             p->pushvel[0] = p->pushvel[1] = p->pushvel[2] = p->vel[0] = p->vel[1] = p->vel[2] = 0;
                p->texnum = flareparticletexture;
                p->scale = 2;
                p->alpha = 255;
-               p->die = cl.time + 0.01;
+               p->die = cl.time;
                p->color = 0x6f;
                p->type = pt_explode;
                
@@ -408,10 +413,7 @@ void R_ReadPointFile_f (void)
                        Con_Printf ("Not enough free particles\n");
                        break;
                }
-               p = free_particles;
-               free_particles = p->next;
-               p->next = active_particles;
-               active_particles = p;
+               ALLOCPARTICLE
                
                p->texnum = particletexture;
                p->scale = 2;
@@ -419,7 +421,7 @@ void R_ReadPointFile_f (void)
                p->die = 99999;
                p->color = (-c)&15;
                p->type = pt_static;
-               VectorCopy (vec3_origin, p->vel);
+//             p->pushvel[0] = p->pushvel[1] = p->pushvel[2] = p->vel[0] = p->vel[1] = p->vel[2] = 0;
                VectorCopy (org, p->org);
        }
 
@@ -427,6 +429,37 @@ void R_ReadPointFile_f (void)
        Con_Printf ("%i points read\n", c);
 }
 
+/*
+===============
+R_BlastParticles
+
+LordHavoc: blasts away particles in the area, used for explosions to disturb the smoke trail and such
+===============
+*/
+/*
+void R_BlastParticles(vec3_t org, vec_t radius, vec_t power)
+{
+       vec3_t v;
+       particle_t *p;
+       vec_t radius2 = radius * radius, speed, dist, scale = 2.5 * power / radius;
+       p = active_particles;
+       if (!p)
+               return;
+       while (p)
+       {
+               VectorSubtract(p->org, org, v);
+               dist = DotProduct(v,v);
+               if (dist < radius2)
+               {
+                       speed = (radius - sqrt(dist)) * scale;
+                       VectorNormalize(v);
+                       VectorMA(p->pushvel, speed, v, p->pushvel);
+               }
+               p = p->next;
+       }
+}
+*/
+
 /*
 ===============
 R_ParseParticleEffect
@@ -465,16 +498,13 @@ void R_ParticleExplosion (vec3_t org, int smoke)
        int                     i, j;
        particle_t      *p;
        if (!r_particles.value) return; // LordHavoc: particles are optional
-       
+
+       /*
        for (i=0 ; i<1024 ; i++)
        {
-               if (!free_particles)
-                       return;
-               p = free_particles;
-               free_particles = p->next;
-               p->next = active_particles;
-               active_particles = p;
+               ALLOCPARTICLE
 
+//             p->pushvel[0] = p->pushvel[1] = p->pushvel[2] = 0;
                p->texnum = particletexture;
                p->scale = lhrandom(1,3);
                p->alpha = rand()&255;
@@ -489,36 +519,57 @@ void R_ParticleExplosion (vec3_t org, int smoke)
                p->type = pt_fallfadespark;
                for (j=0 ; j<3 ; j++)
                {
-                       p->org[j] = org[j] + ((rand()&15)-8);
+                       p->org[j] = org[j] + lhrandom(-8,8);
                        p->vel[j] = lhrandom(-192, 192);
                }
                p->vel[2] += 160;
        }
+       */
 
-       if (smoke)
+       i = Mod_PointInLeaf(org, cl.worldmodel)->contents;
+       if (i == CONTENTS_SLIME || i == CONTENTS_WATER)
        {
                for (i=0 ; i<32 ; i++)
                {
-                       if (!free_particles)
-                               return;
-                       p = free_particles;
-                       free_particles = p->next;
-                       p->next = active_particles;
-                       active_particles = p;
+                       ALLOCPARTICLE
+
+//                     p->pushvel[0] = p->pushvel[1] = p->pushvel[2] = 0;
+                       p->texnum = bubbleparticletexture;
+                       p->scale = lhrandom(1,2);
+                       p->alpha = 255;
+                       p->color = (rand()&3)+12;
+                       p->type = pt_bubble;
+                       p->die = cl.time + 2;
+                       for (j=0 ; j<3 ; j++)
+                       {
+                               p->org[j] = org[j] + lhrandom(-16,16);
+                               p->vel[j] = lhrandom(-16,16);
+                       }
+               }
+       }
+       else // if (smoke)
+       {
+//             for (i=0 ; i<32 ; i++)
+//             {
+                       ALLOCPARTICLE
 
+//                     p->pushvel[0] = p->pushvel[1] = p->pushvel[2] = 0;
                        p->texnum = smokeparticletexture[rand()&7];
-                       p->scale = 12;
-                       p->alpha = 80;
+//                     p->scale = 12;
+                       p->scale = 30;
+                       p->alpha = 96;
                        p->die = cl.time + 2;
-                       p->type = pt_smoke;
+                       p->type = pt_smokecloud;
                        p->color = (rand()&7) + 8;
                        for (j=0 ; j<3 ; j++)
                        {
-                               p->org[j] = org[j] + ((rand()%96)-48);
-                               p->vel[j] = (rand()&63)-32;
+//                             p->org[j] = org[j] + ((rand()%96)-48);
+//                             p->vel[j] = (rand()&63)-32;
+                               p->org[j] = org[j];
+                               p->vel[j] = 0;
                        }
                }
-       }
+//     }
 }
 
 /*
@@ -536,14 +587,10 @@ void R_ParticleExplosion2 (vec3_t org, int colorStart, int colorLength)
 
        for (i=0; i<512; i++)
        {
-               if (!free_particles)
-                       return;
-               p = free_particles;
-               free_particles = p->next;
-               p->next = active_particles;
-               active_particles = p;
+               ALLOCPARTICLE
 
-               p->texnum = smokeparticletexture[rand()&7];
+//             p->pushvel[0] = p->pushvel[1] = p->pushvel[2] = 0;
+               p->texnum = particletexture;
                p->scale = 1.5;
                p->alpha = 255;
                p->die = cl.time + 0.3;
@@ -573,14 +620,10 @@ void R_BlobExplosion (vec3_t org)
        
        for (i=0 ; i<1024 ; i++)
        {
-               if (!free_particles)
-                       return;
-               p = free_particles;
-               free_particles = p->next;
-               p->next = active_particles;
-               active_particles = p;
+               ALLOCPARTICLE
 
-               p->texnum = smokeparticletexture[rand()&7];
+//             p->pushvel[0] = p->pushvel[1] = p->pushvel[2] = 0;
+               p->texnum = particletexture;
                p->scale = 2;
                p->alpha = 255;
                p->die = cl.time + 1 + (rand()&8)*0.05;
@@ -629,12 +672,7 @@ void R_RunParticleEffect (vec3_t org, vec3_t dir, int color, int count)
        }
        while (count)
        {
-               if (!free_particles)
-                       return;
-               p = free_particles;
-               free_particles = p->next;
-               p->next = active_particles;
-               active_particles = p;
+               ALLOCPARTICLE
                if (count & 7)
                {
                        p->alpha = (count & 7) * 16 + (rand()&15);
@@ -646,6 +684,7 @@ void R_RunParticleEffect (vec3_t org, vec3_t dir, int color, int count)
                        count -= 8;
                }
 
+//             p->pushvel[0] = p->pushvel[1] = p->pushvel[2] = 0;
                p->texnum = particletexture;
                p->scale = 6;
                p->die = cl.time + 1; //lhrandom(0.1, 0.5);
@@ -672,17 +711,13 @@ void R_SparkShower (vec3_t org, vec3_t dir, int count, int type)
        particle_t      *p;
        if (!r_particles.value) return; // LordHavoc: particles are optional
 
-       if (!free_particles)
-               return;
-       p = free_particles;
-       free_particles = p->next;
-       p->next = active_particles;
-       active_particles = p;
+       ALLOCPARTICLE
+//     p->pushvel[0] = p->pushvel[1] = p->pushvel[2] = 0;
        if (type == 0) // sparks
        {
                p->texnum = smokeparticletexture[rand()&7];
-               p->scale = 15;
-               p->alpha = 64;
+               p->scale = 10;
+               p->alpha = 48;
                p->color = (rand()&3)+12;
                p->type = pt_bulletpuff;
                p->die = cl.time + 1;
@@ -703,16 +738,12 @@ void R_SparkShower (vec3_t org, vec3_t dir, int count, int type)
        }
        for (i=0 ; i<count ; i++)
        {
-               if (!free_particles)
-                       return;
-               p = free_particles;
-               free_particles = p->next;
-               p->next = active_particles;
-               active_particles = p;
+               ALLOCPARTICLE
 
+//             p->pushvel[0] = p->pushvel[1] = p->pushvel[2] = 0;
                p->texnum = flareparticletexture;
                p->scale = 2;
-               p->alpha = 255;
+               p->alpha = 192;
                p->die = cl.time + 0.0625 * (rand()&15);
                /*
                if (type == 0) // sparks
@@ -761,13 +792,9 @@ void R_BloodShower (vec3_t mins, vec3_t maxs, float velspeed, int count)
        
        for (i=0 ; i<count ; i++)
        {
-               if (!free_particles)
-                       return;
-               p = free_particles;
-               free_particles = p->next;
-               p->next = active_particles;
-               active_particles = p;
+               ALLOCPARTICLE
 
+//             p->pushvel[0] = p->pushvel[1] = p->pushvel[2] = 0;
                p->texnum = bloodcloudparticletexture;
                p->scale = 12;
                p->alpha = 96 + (rand()&63);
@@ -798,13 +825,9 @@ void R_ParticleCube (vec3_t mins, vec3_t maxs, vec3_t dir, int count, int colorb
        
        for (i=0 ; i<count ; i++)
        {
-               if (!free_particles)
-                       return;
-               p = free_particles;
-               free_particles = p->next;
-               p->next = active_particles;
-               active_particles = p;
+               ALLOCPARTICLE
 
+//             p->pushvel[0] = p->pushvel[1] = p->pushvel[2] = 0;
                p->texnum = flareparticletexture;
                p->scale = 6;
                p->alpha = 255;
@@ -855,12 +878,7 @@ void R_ParticleRain (vec3_t mins, vec3_t maxs, vec3_t dir, int count, int colorb
        
        for (i=0 ; i<count ; i++)
        {
-               if (!free_particles)
-                       return;
-               p = free_particles;
-               free_particles = p->next;
-               p->next = active_particles;
-               active_particles = p;
+               ALLOCPARTICLE
 
                vel[0] = dir[0] + (rand()&31) - 16;
                vel[1] = dir[1] + (rand()&31) - 16;
@@ -869,6 +887,7 @@ void R_ParticleRain (vec3_t mins, vec3_t maxs, vec3_t dir, int count, int colorb
                org[1] = diff[1] * (float) (rand()&1023) * (1.0 / 1024.0) + mins[1];
                org[2] = z;
 
+//             p->pushvel[0] = p->pushvel[1] = p->pushvel[2] = 0;
                p->scale = 1.5;
                p->alpha = 255;
                p->die = t;
@@ -908,13 +927,9 @@ void R_LavaSplash (vec3_t org)
                for (j=-16 ; j<16 ; j+=2)
                        for (k=0 ; k<1 ; k++)
                        {
-                               if (!free_particles)
-                                       return;
-                               p = free_particles;
-                               free_particles = p->next;
-                               p->next = active_particles;
-                               active_particles = p;
+                               ALLOCPARTICLE
                
+//                             p->pushvel[0] = p->pushvel[1] = p->pushvel[2] = 0;
                                p->texnum = flareparticletexture;
                                p->scale = 10;
                                p->alpha = 128;
@@ -954,13 +969,9 @@ void R_TeleportSplash (vec3_t org)
                for (j=-16 ; j<16 ; j+=4)
                        for (k=-24 ; k<32 ; k+=4)
                        {
-                               if (!free_particles)
-                                       return;
-                               p = free_particles;
-                               free_particles = p->next;
-                               p->next = active_particles;
-                               active_particles = p;
+                               ALLOCPARTICLE
                
+//                             p->pushvel[0] = p->pushvel[1] = p->pushvel[2] = 0;
                                p->contents = 0;
                                p->texnum = particletexture;
                                p->scale = 2;
@@ -987,13 +998,9 @@ void R_TeleportSplash (vec3_t org)
                for (j=-24 ; j<24 ; j+=8)
                        for (k=-24 ; k<32 ; k+=8)
                        {
-                               if (!free_particles)
-                                       return;
-                               p = free_particles;
-                               free_particles = p->next;
-                               p->next = active_particles;
-                               active_particles = p;
+                               ALLOCPARTICLE
                
+//                             p->pushvel[0] = p->pushvel[1] = p->pushvel[2] = 0;
                                p->texnum = flareparticletexture;
                                p->scale = 4;
                                p->alpha = lhrandom(32,256);
@@ -1043,13 +1050,9 @@ void R_RocketTrail (vec3_t start, vec3_t end, int type, entity_t *ent)
 
        while (t < nt)
        {
-               if (!free_particles)
-                       return;
-               p = free_particles;
-               free_particles = p->next;
-               p->next = active_particles;
-               active_particles = p;
+               ALLOCPARTICLE
                
+//             p->pushvel[0] = p->pushvel[1] = p->pushvel[2] = 0;
                p->vel[0] = p->vel[1] = p->vel[2] = 0;
                p->die = cl.time + 2;
 
@@ -1076,7 +1079,7 @@ void R_RocketTrail (vec3_t start, vec3_t end, int type, entity_t *ent)
                                {
                                        dec = 0.02f;
                                        p->texnum = smokeparticletexture[rand()&7];
-                                       p->scale = lhrandom(6, 10);
+                                       p->scale = lhrandom(8, 12);
                                        p->alpha = 64 + (rand()&31);
                                        p->color = (rand()&3)+12;
                                        p->type = pt_smoke;
@@ -1108,7 +1111,7 @@ void R_RocketTrail (vec3_t start, vec3_t end, int type, entity_t *ent)
                                p->alpha = 255;
                                p->color = (rand()&3)+68;
                                p->type = pt_bloodcloud;
-                               p->die = cl.time + 2;
+                               p->die = cl.time + 9999;
                                for (j=0 ; j<3 ; j++)
                                {
                                        p->vel[j] = (rand()&15)-8;
@@ -1151,7 +1154,7 @@ void R_RocketTrail (vec3_t start, vec3_t end, int type, entity_t *ent)
                                p->alpha = 192;
                                p->color = (rand()&3)+68;
                                p->type = pt_fadespark2;
-                               p->die = cl.time + 2;
+                               p->die = cl.time + 9999;
                                for (j=0 ; j<3 ; j++)
                                {
                                        p->vel[j] = (rand()&15)-8;
@@ -1207,14 +1210,10 @@ void R_RocketTrail2 (vec3_t start, vec3_t end, int color, entity_t *ent)
        {
                len -= 3;
 
-               if (!free_particles)
-                       return;
-               p = free_particles;
-               free_particles = p->next;
-               p->next = active_particles;
-               active_particles = p;
+               ALLOCPARTICLE
                
-               VectorCopy (vec3_origin, p->vel);
+//             p->pushvel[0] = p->pushvel[1] = p->pushvel[2] = 0;
+               p->vel[0] = p->vel[1] = p->vel[2] = 0;
 
                p->texnum = flareparticletexture;
                p->scale = 8;
@@ -1245,9 +1244,9 @@ void R_DrawParticles (void)
 {
        particle_t              *p, *kill;
        int                             i, r,g,b,a;
-       float                   grav, grav1, time1, time2, time3, dvel, frametime, scale, scale2;
+       float                   grav, grav1, time1, time2, time3, dvel, frametime, scale, scale2/*, f1, f2*/, minparticledist;
        byte                    *color24;
-       vec3_t                  up, right, uprightangles, forward2, up2, right2, v, tempcolor;
+       vec3_t                  up, right, uprightangles, forward2, up2, right2, tempcolor;
 
        // LordHavoc: early out condition
        if (!active_particles)
@@ -1268,6 +1267,9 @@ void R_DrawParticles (void)
        grav = (grav1 = frametime * sv_gravity.value) * 0.05;
        dvel = 1+4*frametime;
 
+       minparticledist = DotProduct(r_refdef.vieworg, vpn) + 16.0f;
+
+       // remove dead particles at beginning of list
        for ( ;; ) 
        {
                kill = active_particles;
@@ -1283,6 +1285,7 @@ void R_DrawParticles (void)
 
        for (p=active_particles ; p ; p=p->next)
        {
+               // remove dead particles following this one
                for ( ;; )
                {
                        kill = p->next;
@@ -1295,14 +1298,10 @@ void R_DrawParticles (void)
                        }
                        break;
                }
-               // LordHavoc: 'removed last in list' condition
-               if (!p)
-                       break;
 
-               VectorSubtract(p->org, r_refdef.vieworg, v);
-               if (DotProduct(v, v) >= 256.0f)
+               // LordHavoc: only render if not too close
+               if (DotProduct(p->org, vpn) >= minparticledist)
                {
-                       scale = p->scale * -0.5;scale2 = p->scale * 0.5;
                        color24 = (byte *) &d_8to24table[(int)p->color];
                        r = color24[0];
                        g = color24[1];
@@ -1322,6 +1321,7 @@ void R_DrawParticles (void)
                                b = (b * (int) tempcolor[2]) >> 7;
                        }
                        transpolybegin(p->texnum, 0, p->texnum, TPOLYTYPE_ALPHA);
+                       scale = p->scale * -0.5;scale2 = p->scale * 0.5;
                        if (p->texnum == rainparticletexture) // rain streak
                        {
                                transpolyvert(p->org[0] + up2[0]*scale  + right2[0]*scale , p->org[1] + up2[1]*scale  + right2[1]*scale , p->org[2] + up2[2]*scale  + right2[2]*scale , 0,1,r,g,b,a);
@@ -1339,9 +1339,36 @@ void R_DrawParticles (void)
                        transpolyend();
                }
 
-               p->org[0] += p->vel[0]*frametime;
-               p->org[1] += p->vel[1]*frametime;
-               p->org[2] += p->vel[2]*frametime;
+               /*
+               if (p->pushvel[0] || p->pushvel[1] || p->pushvel[2])
+               {
+                       p->org[0] += (p->vel[0]+p->pushvel[0])*frametime;
+                       p->org[1] += (p->vel[1]+p->pushvel[1])*frametime;
+                       p->org[2] += (p->vel[2]+p->pushvel[2])*frametime;
+                       f1 = sqrt(DotProduct(p->pushvel,p->pushvel));
+                       f2 = f1 - frametime * 32;
+                       if (f2 <= 0)
+                               p->pushvel[0] = p->pushvel[1] = p->pushvel[2] = 0;
+                       else
+                       {
+                               f2 /= f1;
+                               p->pushvel[0] *= f2;
+                               p->pushvel[1] *= f2;
+                               p->pushvel[2] *= f2;
+                       }
+               }
+               else
+               {
+                       if (p->type != pt_smokecloud)
+                       {
+               */
+                               p->org[0] += p->vel[0]*frametime;
+                               p->org[1] += p->vel[1]*frametime;
+                               p->org[2] += p->vel[2]*frametime;
+               /*
+                       }
+               }
+               */
                
                switch (p->type)
                {
@@ -1403,7 +1430,8 @@ void R_DrawParticles (void)
                case pt_dust:
                        p->ramp += time1;
                        p->scale -= frametime * 4;
-                       if (p->ramp >= 8 || p->scale <= 0)
+                       p->alpha -= frametime * 48;
+                       if (p->ramp >= 8 || p->scale < 1 || p->alpha < 1)
                                p->die = -1;
                        else
                                p->color = ramp3[(int)p->ramp];
@@ -1411,8 +1439,8 @@ void R_DrawParticles (void)
                        break;
 // LordHavoc: for smoke trails
                case pt_smoke:
-                       p->scale += frametime * 4;
-                       p->alpha -= frametime * 48;
+                       p->scale += frametime * 6;
+                       p->alpha -= frametime * 128;
 //                     p->vel[2] += grav;
                        if (p->alpha < 1)
                                p->die = -1;
@@ -1434,6 +1462,11 @@ void R_DrawParticles (void)
                                p->die = -1;
                        break;
                case pt_bloodcloud:
+                       if (Mod_PointInLeaf(p->org, cl.worldmodel)->contents != CONTENTS_EMPTY)
+                       {
+                               p->die = -1;
+                               break;
+                       }
                        p->scale += frametime * 4;
                        p->alpha -= frametime * 64;
                        p->vel[2] -= grav;
@@ -1485,6 +1518,12 @@ void R_DrawParticles (void)
                        if (p->alpha < 1)
                                p->die = -1;
                        break;
+               case pt_smokecloud:
+                       p->scale += frametime * 60;
+                       p->alpha -= frametime * 96;
+                       if (p->alpha < 1)
+                               p->die = -1;
+                       break;
                }
        }
 }