optimized handling of decals, which increased timedemo bigass1.dem from 185fps to...
authorhavoc <havoc@d7cf8633-e32d-0410-b094-e92efae38249>
Wed, 26 Apr 2006 14:22:55 +0000 (14:22 +0000)
committerhavoc <havoc@d7cf8633-e32d-0410-b094-e92efae38249>
Wed, 26 Apr 2006 14:22:55 +0000 (14:22 +0000)
git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@6334 d7cf8633-e32d-0410-b094-e92efae38249

cl_particles.c
client.h

index 92ee63f..21d7ae5 100644 (file)
@@ -485,7 +485,10 @@ static particle_t *particle(particletype_t *ptype, int pcolor1, int pcolor2, int
        part->vel[1] = pvy + velocityjitter * v[1];
        part->vel[2] = pvz + velocityjitter * v[2];
        part->time2 = 0;
-       part->friction = pfriction;
+       // FIXME: change parameters to have separate air and liquid friction
+       // (as supported by effectinfo.txt)
+       part->airfriction = pfriction;
+       part->liquidfriction = pfriction * 4;
        return part;
 }
 
@@ -500,9 +503,11 @@ void CL_SpawnDecalParticleForSurface(int hitent, const vec3_t org, const vec3_t
                p->time2 = cl.time;
                p->owner = hitent;
                p->ownermodel = cl.entities[p->owner].render.model;
+               VectorAdd(org, normal, p->org);
+               VectorCopy(normal, p->vel);
+               // these relative things are only used to regenerate p->org and p->vel if p->owner is not world (0)
                Matrix4x4_Transform(&cl.entities[p->owner].render.inversematrix, org, p->relativeorigin);
                Matrix4x4_Transform3x3(&cl.entities[p->owner].render.inversematrix, normal, p->relativedirection);
-               VectorAdd(p->relativeorigin, p->relativedirection, p->relativeorigin);
        }
 }
 
@@ -1407,7 +1412,8 @@ void CL_MoveParticles (void)
 {
        particle_t *p;
        int i, maxparticle, j, a, content;
-       float gravity, dvel, bloodwaterfade, frametime, f, dist, org[3], oldorg[3];
+       float gravity, dvel, decalfade, frametime, f, dist, org[3], oldorg[3];
+       particletype_t *decaltype, *bloodtype;
        int hitent;
        trace_t trace;
 
@@ -1421,7 +1427,9 @@ void CL_MoveParticles (void)
        frametime = cl.time - cl.oldtime;
        gravity = frametime * sv_gravity.value;
        dvel = 1+4*frametime;
-       bloodwaterfade = max(cl_particles_blood_alpha.value, 0.01f) * frametime * 128.0f;
+       decalfade = frametime * 255 / cl_decals_fadetime.value;
+       decaltype = particletype + pt_decal;
+       bloodtype = particletype + pt_blood;
 
        maxparticle = -1;
        j = 0;
@@ -1434,6 +1442,39 @@ void CL_MoveParticles (void)
                        continue;
                }
                maxparticle = i;
+
+               // heavily optimized decal case
+               if (p->type == decaltype)
+               {
+                       // FIXME: this has fairly wacky handling of alpha
+                       if (cl.time > p->time2 + cl_decals_time.value)
+                       {
+                               p->alpha -= decalfade;
+                               if (p->alpha <= 0)
+                               {
+                                       p->type = NULL;
+                                       if (cl.free_particle > i)
+                                               cl.free_particle = i;
+                                       continue;
+                               }
+                       }
+                       if (p->owner)
+                       {
+                               if (cl.entities[p->owner].render.model == p->ownermodel)
+                               {
+                                       Matrix4x4_Transform(&cl.entities[p->owner].render.matrix, p->relativeorigin, p->org);
+                                       Matrix4x4_Transform3x3(&cl.entities[p->owner].render.matrix, p->relativedirection, p->vel);
+                               }
+                               else
+                               {
+                                       p->type = NULL;
+                                       if (cl.free_particle > i)
+                                               cl.free_particle = i;
+                               }
+                       }
+                       continue;
+               }
+
                content = 0;
 
                p->alpha -= p->alphafade * frametime;
@@ -1478,7 +1519,8 @@ void CL_MoveParticles (void)
                                                p->time2 = cl.time;
                                                p->alphafade = p->alpha / 0.4;
                                                p->bounce = 0;
-                                               p->friction = 0;
+                                               p->airfriction = 0;
+                                               p->liquidfriction = 0;
                                                p->gravity = 0;
                                                p->size *= 1.0f;
                                                p->sizeincrease = p->size * 16;
@@ -1486,7 +1528,7 @@ void CL_MoveParticles (void)
                                                while(count--)
                                                        particle(particletype + pt_spark, 0x000000, 0x707070, tex_particle, 0.25f, 0, lhrandom(64, 255), 512, 1, 0, p->org[0], p->org[1], p->org[2], p->vel[0]*16, p->vel[1]*16, 32 + p->vel[2]*16, 0, 0, 32);
                                        }
-                                       else if (p->type == particletype + pt_blood)
+                                       else if (p->type == bloodtype)
                                        {
                                                // blood - splash on solid
                                                if (trace.hitq3surfaceflags & Q3SURFACEFLAG_NOMARKS)
@@ -1509,12 +1551,14 @@ void CL_MoveParticles (void)
                                                p->texnum = tex_blooddecal[rand()&7];
                                                p->owner = hitent;
                                                p->ownermodel = cl.entities[hitent].render.model;
+                                               // these relative things are only used to regenerate p->org and p->vel if p->owner is not world (0)
                                                Matrix4x4_Transform(&cl.entities[hitent].render.inversematrix, p->org, p->relativeorigin);
                                                Matrix4x4_Transform3x3(&cl.entities[hitent].render.inversematrix, p->vel, p->relativedirection);
                                                p->time2 = cl.time;
                                                p->alphafade = 0;
                                                p->bounce = 0;
-                                               p->friction = 0;
+                                               p->airfriction = 0;
+                                               p->liquidfriction = 0;
                                                p->gravity = 0;
                                                p->size *= 2.0f;
                                        }
@@ -1536,12 +1580,14 @@ void CL_MoveParticles (void)
                        }
                        p->vel[2] -= p->gravity * gravity;
 
-                       if (p->friction)
+                       if (p->liquidfriction && CL_PointSuperContents(p->org) & SUPERCONTENTS_LIQUIDSMASK)
                        {
-                               f = p->friction * frametime;
-                               if (CL_PointSuperContents(p->org) & SUPERCONTENTS_LIQUIDSMASK)
-                                       f *= 4;
-                               f = 1.0f - f;
+                               f = 1.0f - min(p->liquidfriction * frametime, 1);
+                               VectorScale(p->vel, f, p->vel);
+                       }
+                       else if (p->airfriction)
+                       {
+                               f = 1.0f - min(p->airfriction * frametime, 1);
                                VectorScale(p->vel, f, p->vel);
                        }
                }
@@ -1595,20 +1641,6 @@ void CL_MoveParticles (void)
                                if (a & (SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_LIQUIDSMASK))
                                        p->type = NULL;
                                break;
-                       case pt_smoke:
-                               //p->size += frametime * 15;
-                               break;
-                       case pt_decal:
-                               // FIXME: this has fairly wacky handling of alpha
-                               p->alphafade = cl.time > (p->time2 + cl_decals_time.value) ? (255 / cl_decals_fadetime.value) : 0;
-                               if (cl.entities[p->owner].render.model == p->ownermodel)
-                               {
-                                       Matrix4x4_Transform(&cl.entities[p->owner].render.matrix, p->relativeorigin, p->org);
-                                       Matrix4x4_Transform3x3(&cl.entities[p->owner].render.matrix, p->relativedirection, p->vel);
-                               }
-                               else
-                                       p->type = NULL;
-                               break;
                        default:
                                break;
                        }
index f24fe71..260bfc0 100644 (file)
--- a/client.h
+++ b/client.h
@@ -589,7 +589,8 @@ typedef struct particle_s
        float           time2; // used for snow fluttering and decal fade
        float           bounce; // how much bounce-back from a surface the particle hits (0 = no physics, 1 = stop and slide, 2 = keep bouncing forever, 1.5 is typical)
        float           gravity; // how much gravity affects this particle (1.0 = normal gravity, 0.0 = none)
-       float           friction; // how much air friction affects this object (objects with a low mass/size ratio tend to get more air friction)
+       float           airfriction; // how much air friction affects this object (objects with a low mass/size ratio tend to get more air friction)
+       float           liquidfriction; // how much liquid friction affects this object (objects with a low mass/size ratio tend to get more liquid friction)
        unsigned char           color[4];
        unsigned short owner; // decal stuck to this entity
        model_t         *ownermodel; // model the decal is stuck to (used to make sure the entity is still alive)